mirror of
https://github.com/anomalyco/opencode.git
synced 2026-10-07 07:48:16 +00:00
Compare commits
58
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb589aa7c | ||
|
|
1573bf153d | ||
|
|
cdb5ac2c04 | ||
|
|
732d4c6c05 | ||
|
|
5c8485ab15 | ||
|
|
3c7afcc943 | ||
|
|
72780ce469 | ||
|
|
dd98eee547 | ||
|
|
7d01abfb67 | ||
|
|
4ed2978a30 | ||
|
|
944959566f | ||
|
|
a701129184 | ||
|
|
54630586a7 | ||
|
|
2a8f7f59a0 | ||
|
|
40fd54aabb | ||
|
|
0c11c8fc2f | ||
|
|
7725ac81eb | ||
|
|
4aba11e9d5 | ||
|
|
25909277aa | ||
|
|
e2d540042a | ||
|
|
ef07075156 | ||
|
|
eb2f0d5e5d | ||
|
|
f28f62439e | ||
|
|
1732ce1eeb | ||
|
|
e3c3786f43 | ||
|
|
759175abad | ||
|
|
88dd4417c7 | ||
|
|
4fb800734d | ||
|
|
473e4a960d | ||
|
|
2dfd08edc9 | ||
|
|
45e8c02bcc | ||
|
|
938baed23b | ||
|
|
494d70707b | ||
|
|
eab83d63fd | ||
|
|
fad352c5d0 | ||
|
|
e1b94a138e | ||
|
|
9e96aacd64 | ||
|
|
e19263ca87 | ||
|
|
63e33bc4dc | ||
|
|
999097bdac | ||
|
|
515b3022ac | ||
|
|
cb389aa679 | ||
|
|
30f4119459 | ||
|
|
4d17cf719f | ||
|
|
498b1deda3 | ||
|
|
25c54cbdf7 | ||
|
|
ae57dd0cf5 | ||
|
|
e86ec98711 | ||
|
|
c542a43503 | ||
|
|
2db9c2e1b3 | ||
|
|
3a861ff8b0 | ||
|
|
22803892bc | ||
|
|
69ba898a7b | ||
|
|
375ff827aa | ||
|
|
ed747091e9 | ||
|
|
44193bd71f | ||
|
|
238d4cf5ca | ||
|
|
3e77d5c170 |
No files matched your search
@@ -33,7 +33,7 @@
|
||||
},
|
||||
"packages/ai": {
|
||||
"name": "@opencode/ai",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-providers": "3.1057.0",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -55,7 +55,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode/app",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@corvu/drawer": "catalog:",
|
||||
"@dnd-kit/abstract": "0.5.0",
|
||||
@@ -112,7 +112,7 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@opencode/cli",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode.cjs",
|
||||
"opencode2": "./bin/opencode2.cjs",
|
||||
@@ -179,7 +179,7 @@
|
||||
},
|
||||
"packages/client": {
|
||||
"name": "@opencode/client",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opencode/protocol": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -195,7 +195,7 @@
|
||||
"zod": "catalog:",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"effect": "4.0.0-rc.118",
|
||||
"effect": "4.0.0-rc.112",
|
||||
"solid-js": ">=1.9.0",
|
||||
},
|
||||
"optionalPeers": [
|
||||
@@ -205,7 +205,7 @@
|
||||
},
|
||||
"packages/codemode": {
|
||||
"name": "@opencode/codemode",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"acorn": "8.15.0",
|
||||
"effect": "catalog:",
|
||||
@@ -218,7 +218,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode/console-app",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -254,7 +254,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode/console-core",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -281,7 +281,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode/console-function",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||
"@opencode/console-core": "workspace:*",
|
||||
@@ -298,7 +298,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode/console-mail",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -322,7 +322,7 @@
|
||||
},
|
||||
"packages/console/support": {
|
||||
"name": "@opencode/console-support",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@opencode/console-core": "workspace:*",
|
||||
@@ -342,7 +342,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode/core",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@ai-sdk/cohere": "3.0.27",
|
||||
"@ai-sdk/gateway": "3.0.104",
|
||||
@@ -383,7 +383,6 @@
|
||||
"mime-types": "3.0.2",
|
||||
"tree-sitter-bash": "0.25.0",
|
||||
"tree-sitter-powershell": "0.25.10",
|
||||
"venice-ai-sdk-provider": "2.1.1",
|
||||
"web-tree-sitter": "0.25.10",
|
||||
"which": "6.0.1",
|
||||
"zod": "catalog:",
|
||||
@@ -407,12 +406,11 @@
|
||||
"@types/node": "catalog:",
|
||||
"@types/which": "3.0.4",
|
||||
"drizzle-kit": "catalog:",
|
||||
"fast-check": "catalog:",
|
||||
},
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode/desktop",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@zip.js/zip.js": "2.7.62",
|
||||
"electron-context-menu": "5.0.0",
|
||||
@@ -457,7 +455,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode/enterprise",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
@@ -494,7 +492,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode/function",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -510,7 +508,7 @@
|
||||
},
|
||||
"packages/gui-extensions": {
|
||||
"name": "@opencode/gui-extensions",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@dnd-kit/abstract": "0.5.0",
|
||||
"@dnd-kit/dom": "0.5.0",
|
||||
@@ -555,9 +553,9 @@
|
||||
},
|
||||
"packages/http-recorder": {
|
||||
"name": "@opencode/http-recorder",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@effect/platform-node-shared": "4.0.0-rc.118",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.112",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -574,7 +572,7 @@
|
||||
},
|
||||
"packages/httpapi-codegen": {
|
||||
"name": "@opencode/httpapi-codegen",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"effect": "catalog:",
|
||||
"prettier": "3.6.2",
|
||||
@@ -587,7 +585,7 @@
|
||||
},
|
||||
"packages/latex": {
|
||||
"name": "@opencode/latex",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
@@ -601,7 +599,7 @@
|
||||
},
|
||||
"packages/merman": {
|
||||
"name": "@opencode/merman",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
@@ -616,7 +614,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode/plugin",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.8",
|
||||
"@opencode/ai": "workspace:*",
|
||||
@@ -655,7 +653,7 @@
|
||||
},
|
||||
"packages/plugin-browser": {
|
||||
"name": "@opencode/plugin-browser",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -685,7 +683,7 @@
|
||||
},
|
||||
"packages/protocol": {
|
||||
"name": "@opencode/protocol",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opencode/schema": "workspace:*",
|
||||
"effect": "catalog:",
|
||||
@@ -700,7 +698,7 @@
|
||||
},
|
||||
"packages/schema": {
|
||||
"name": "@opencode/schema",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -724,7 +722,7 @@
|
||||
},
|
||||
"packages/sdk": {
|
||||
"name": "@opencode/sdk",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opencode/client": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -745,7 +743,7 @@
|
||||
},
|
||||
"packages/server": {
|
||||
"name": "@opencode/server",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
"@effect/platform-node-shared": "catalog:",
|
||||
@@ -767,7 +765,7 @@
|
||||
},
|
||||
"packages/session-ui": {
|
||||
"name": "@opencode/session-ui",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode/client": "workspace:*",
|
||||
@@ -802,7 +800,7 @@
|
||||
},
|
||||
"packages/simulation": {
|
||||
"name": "@opencode/simulation",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opencode/ai": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -822,7 +820,7 @@
|
||||
},
|
||||
"packages/stats/app": {
|
||||
"name": "@opencode/stats-app",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@ibm/plex": "6.4.1",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -856,7 +854,7 @@
|
||||
},
|
||||
"packages/stats/core": {
|
||||
"name": "@opencode/stats-core",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-athena": "3.933.0",
|
||||
"@planetscale/database": "1.19.0",
|
||||
@@ -875,7 +873,7 @@
|
||||
},
|
||||
"packages/stats/server": {
|
||||
"name": "@opencode/stats-server",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-firehose": "3.933.0",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -921,7 +919,7 @@
|
||||
},
|
||||
"packages/theme": {
|
||||
"name": "@opencode/theme",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opentui/core": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -935,7 +933,7 @@
|
||||
},
|
||||
"packages/tui": {
|
||||
"name": "@opencode/tui",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@opencode/client": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -969,7 +967,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode/ui",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@pierre/diffs": "catalog:",
|
||||
@@ -1004,7 +1002,7 @@
|
||||
},
|
||||
"packages/util": {
|
||||
"name": "@opencode/util",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@effect/opentelemetry": "catalog:",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -1042,7 +1040,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode/web",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
@@ -1083,7 +1081,7 @@
|
||||
},
|
||||
"services/update": {
|
||||
"name": "@opencode/update",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"dependencies": {
|
||||
"jose": "6.0.11",
|
||||
"semver": "catalog:",
|
||||
@@ -1149,10 +1147,10 @@
|
||||
"catalog": {
|
||||
"@cloudflare/workers-types": "4.20251008.0",
|
||||
"@corvu/drawer": "0.2.4",
|
||||
"@effect/opentelemetry": "4.0.0-rc.118",
|
||||
"@effect/platform-node": "4.0.0-rc.118",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.118",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-rc.118",
|
||||
"@effect/opentelemetry": "4.0.0-rc.112",
|
||||
"@effect/platform-node": "4.0.0-rc.112",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.112",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-rc.112",
|
||||
"@hono/standard-validator": "0.2.0",
|
||||
"@hono/zod-validator": "0.4.2",
|
||||
"@kobalte/core": "0.13.13",
|
||||
@@ -1192,8 +1190,7 @@
|
||||
"dompurify": "3.4.14",
|
||||
"drizzle-kit": "1.0.0-rc.5-ab785fc",
|
||||
"drizzle-orm": "1.0.0-rc.5-169397b",
|
||||
"effect": "4.0.0-rc.118",
|
||||
"fast-check": "4.9.0",
|
||||
"effect": "4.0.0-rc.112",
|
||||
"fuzzysort": "3.1.0",
|
||||
"get-east-asian-width": "1.6.0",
|
||||
"hono": "4.10.7",
|
||||
@@ -1725,13 +1722,13 @@
|
||||
|
||||
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.12.0", "", {}, "sha512-mlUE+rZ8CatQekLhnaiN91Iemdd+e2gFKooGlnRB3oPTL3VghLfX24dx7HrzMNeC1JrIB/0kpsfyty3f5HNfxQ=="],
|
||||
|
||||
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-rc.118", "", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-node": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-web": ">=2.0.0 <3.0.0", "@opentelemetry/semantic-conventions": ">=1.33.0 <2.0.0", "effect": "^4.0.0-rc.118" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-N5dvEeCj1W/9zgBvyyp/GucOKOEJdV7QNirWp+4g/axFKTB/cfV2gx/ZhMDUb69HzlyRmOelNvKEmB3RA0PdVw=="],
|
||||
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-rc.112", "", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-node": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-web": ">=2.0.0 <3.0.0", "@opentelemetry/semantic-conventions": ">=1.33.0 <2.0.0", "effect": "^4.0.0-rc.112" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-OTRv1DxTHUmnakgJ6XVM8wVgF1KgZH4UXnOemwSLUwUjXO+RCikzF8oR/rlVmOGq81KtQzj1URM4M4nchlQOuQ=="],
|
||||
|
||||
"@effect/platform-node": ["@effect/platform-node@4.0.0-rc.118", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.118", "undici": "^8.11.2" }, "peerDependencies": { "effect": "^4.0.0-rc.118", "redis": ">=5.0.0 <7.0.0" } }, "sha512-qdAxPZ+5bKxVnzkwziqcHZTHRHz2hyfFX6NhwEmm75CBpmaIzXIZR2LRqGd1/8eI3J3cOrXcAYzByhln7T1/EA=="],
|
||||
"@effect/platform-node": ["@effect/platform-node@4.0.0-rc.112", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.112", "mime": "^4.1.0", "undici": "^8.10.0" }, "peerDependencies": { "effect": "^4.0.0-rc.112", "redis": ">=5.0.0 <7.0.0" } }, "sha512-/BMAcdNGQQskLmI0Zoa95KfTZkr9HV9N4NSxaSrusG6GeW6Ulp9KvZ+Rlaiw8lnOt43CXjFLdfll5/k5rxL4hQ=="],
|
||||
|
||||
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.118", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.22.0" }, "peerDependencies": { "effect": "^4.0.0-rc.118" } }, "sha512-pNbmIlxbAUxAthUNsp2xm1NLG9kxoYecsPkoYl9mNF2oxPcKDxAvkOar7tYnLSUpXJeATm4pxYVipdZjQfqO4Q=="],
|
||||
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.112", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.3" }, "peerDependencies": { "effect": "^4.0.0-rc.112" } }, "sha512-ttjz0xKamFN7vL8pNDYVwddJLjZvqKePc05djlz2VcdaKbLsnYbtMnL1rbOfHgEnIUSHGh7FkjaN4DM1Ov81sQ=="],
|
||||
|
||||
"@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-rc.118", "", { "peerDependencies": { "effect": "^4.0.0-rc.118" } }, "sha512-UF0oVOK7mQvEwpxySR9VTk5YoP5luRI//Z8NMOJKVG/SbZbsORGACd7Np+KZRiXXjgzSXEpfGb7Gs3G1cKfUCg=="],
|
||||
"@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-rc.112", "", { "peerDependencies": { "effect": "^4.0.0-rc.112" } }, "sha512-EqR8pWZo3VzedRvP6qo5HcfqNmFvSa+sQLWQl3oBMx2KY1FCc8NYjep79wYjNkW0qABnffrPUXCMTOncd1A+5g=="],
|
||||
|
||||
"@electron-internal/extract-zip": ["@electron-internal/extract-zip@1.0.5", "", {}, "sha512-+bqFCP98pLI0Tt0XQo1TmlXtwjWchISndDOxCkEcIuUgXWpBnLyRI+2DU+mesvnMMX6L1XDqYNA0lXNDHd/yiA=="],
|
||||
|
||||
@@ -2065,6 +2062,18 @@
|
||||
|
||||
"@motionone/utils": ["@motionone/utils@10.18.0", "", { "dependencies": { "@motionone/types": "^10.17.1", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="],
|
||||
|
||||
"@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="],
|
||||
|
||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.3", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q=="],
|
||||
@@ -3317,8 +3326,6 @@
|
||||
|
||||
"@webgpu/types": ["@webgpu/types@0.1.54", "", {}, "sha512-81oaalC8LFrXjhsczomEQ0u3jG+TqE6V9QHLA8GNZq/Rnot0KDugu3LhSYSlie8tSdooAN1Hov05asrUUp9qgg=="],
|
||||
|
||||
"@workflow/serde": ["@workflow/serde@4.1.0", "", {}, "sha512-pav4F2BoirECWR7Nf1TKt+2eETcBj7jj4cBefQ8VXQCA6NPkaKeLfj/zMgi+3zYV5ZIBT4GuUiphsj0/b9hPQQ=="],
|
||||
|
||||
"@xmldom/xmldom": ["@xmldom/xmldom@0.8.14", "", {}, "sha512-T4EDRUBVZYRldYApjEJiU0e1stYWaRAX7CuSnKzrpwdZKo53zGV8/pqfzV6FfwNl9YThD2OumQYvqtvjvgG7aQ=="],
|
||||
|
||||
"@yuuang/ffi-rs-android-arm64": ["@yuuang/ffi-rs-android-arm64@1.3.7", "", { "os": "android", "cpu": "arm64" }, "sha512-t6Wx3Xll6c07Nuk0k3xnZsxKFxlshm92i0U/BiTHc6kQbvu+fMJF+gKsj4yEj886jH51CM3EqZT9Xdhq9CdUVw=="],
|
||||
@@ -3359,8 +3366,6 @@
|
||||
|
||||
"agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
|
||||
|
||||
"ai": ["ai@7.0.66", "", { "dependencies": { "@ai-sdk/gateway": "4.0.52", "@ai-sdk/provider": "4.0.7", "@ai-sdk/provider-utils": "5.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-wBUyoCYF3GVr+62nelBgR8YbpTSsMZrzFyOOjiwijylNSM2TFCW35C+Pml2vc59/WLMpyhS/LWZ55M+B9DAcSg=="],
|
||||
|
||||
"ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
|
||||
|
||||
"ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="],
|
||||
@@ -3903,7 +3908,7 @@
|
||||
|
||||
"editorconfig": ["editorconfig@1.0.7", "", { "dependencies": { "@one-ini/wasm": "0.1.1", "commander": "^10.0.0", "minimatch": "^9.0.1", "semver": "^7.5.3" }, "bin": { "editorconfig": "bin/editorconfig" } }, "sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw=="],
|
||||
|
||||
"effect": ["effect@4.0.0-rc.118", "", {}, "sha512-hxhpCd+swzrtu9lnyPpEFre2ODQzJ9qxgyL1oHIEY8NKnW4PxTbM1XzplMZXiAsLD62HO+KJc41Nqxr9T791ZQ=="],
|
||||
"effect": ["effect@4.0.0-rc.112", "", { "dependencies": { "fast-check": "^4.9.0", "msgpackr": "^2.0.5" } }, "sha512-wXxwuh1Ywnv4cPRM3Wfa0vDwuOHnZ1TsTgHJkG9XgzND6inhBH9n1vBxhg3iIXOia/OrpmvVmd3lrD4vq6bF3A=="],
|
||||
|
||||
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
|
||||
|
||||
@@ -4741,7 +4746,7 @@
|
||||
|
||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||
|
||||
"mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
|
||||
"mime": ["mime@4.1.0", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw=="],
|
||||
|
||||
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||
|
||||
@@ -4789,6 +4794,10 @@
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"msgpackr": ["msgpackr@2.0.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-cef05H/dSYpLpqp3sj/qyZh5vhUYCalnaLO7j1yOmpsR0y/XwLVtK7r5gn+U/F7CTEfMowcGhlUQJDLcLf7jcA=="],
|
||||
|
||||
"msgpackr-extract": ["msgpackr-extract@3.0.4", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw=="],
|
||||
|
||||
"muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="],
|
||||
|
||||
"mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="],
|
||||
@@ -4831,6 +4840,8 @@
|
||||
|
||||
"node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="],
|
||||
|
||||
"node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
|
||||
|
||||
"node-html-parser": ["node-html-parser@7.1.0", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-iJo8b2uYGT40Y8BTyy5ufL6IVbN8rbm/1QK2xffXU/1a/v3AAa0d1YAoqBNYqaS4R/HajkWIpIfdE6KcyFh1AQ=="],
|
||||
|
||||
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
|
||||
@@ -5627,7 +5638,7 @@
|
||||
|
||||
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
|
||||
|
||||
"undici": ["undici@8.11.2", "", {}, "sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ=="],
|
||||
"undici": ["undici@8.10.0", "", {}, "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
@@ -5707,8 +5718,6 @@
|
||||
|
||||
"validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="],
|
||||
|
||||
"venice-ai-sdk-provider": ["venice-ai-sdk-provider@2.1.1", "", { "dependencies": { "@ai-sdk/openai-compatible": "^2.0.51", "@ai-sdk/provider": "^3.0.10", "@ai-sdk/provider-utils": "^4.0.30" }, "peerDependencies": { "ai": "^6.0.90" } }, "sha512-w3OHkuzzKZ3r2TOxER6myBYzZJNoDqol+DUHu3NnfBN/GETnUVxecZJab0CHQQ8GZc0jjzpFymepjcLDPS4SQg=="],
|
||||
|
||||
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
|
||||
|
||||
"vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
|
||||
@@ -6079,13 +6088,15 @@
|
||||
|
||||
"@bufbuild/protoplugin/typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="],
|
||||
|
||||
"@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
|
||||
|
||||
"@cloudflare/vite-plugin/vite": ["vite@7.3.6", "", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="],
|
||||
|
||||
"@cloudflare/vite-plugin/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
|
||||
|
||||
"@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
||||
|
||||
"@effect/platform-node-shared/ws": ["ws@8.22.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg=="],
|
||||
"@effect/platform-node-shared/ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="],
|
||||
|
||||
"@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="],
|
||||
|
||||
@@ -6375,12 +6386,6 @@
|
||||
|
||||
"@vscode/emmet-helper/jsonc-parser": ["jsonc-parser@2.3.1", "", {}, "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg=="],
|
||||
|
||||
"ai/@ai-sdk/gateway": ["@ai-sdk/gateway@4.0.52", "", { "dependencies": { "@ai-sdk/provider": "4.0.7", "@ai-sdk/provider-utils": "5.0.27", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-SXUM8jzzuTUJRq+EOgPd5to6DSx0EKslVn+IVZHbUEX6k/3vCPNrvjckbK26HnNxHU/STxm+zTSJteqrO+7Z0w=="],
|
||||
|
||||
"ai/@ai-sdk/provider": ["@ai-sdk/provider@4.0.7", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6or44XprPzKbr8zkmzosowSE0pxkvJcoojBL+mCZvPUt3kvXp3XSNqeVun9golb1acEfSo6yaEBRT18h2VU+1Q=="],
|
||||
|
||||
"ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@5.0.27", "", { "dependencies": { "@ai-sdk/provider": "4.0.7", "@standard-schema/spec": "^1.1.0", "@workflow/serde": "4.1.0", "eventsource-parser": "^3.0.8", "undici": "^7.28.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-EzAn4pdgG5g0xXtH6lE2zyNmfjDQIDjATkfqzuidEI35g++hh4+07vnjzkT/RmGmIClPZiRj/Q2GMPV2V7mkHw=="],
|
||||
|
||||
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
||||
@@ -6677,8 +6682,6 @@
|
||||
|
||||
"tw-to-css/tailwindcss": ["tailwindcss@3.3.2", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.18.2", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", "postcss": "^8.4.23", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.1", "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0", "resolve": "^1.22.2", "sucrase": "^3.32.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w=="],
|
||||
|
||||
"unifont/undici": ["undici@8.10.0", "", {}, "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ=="],
|
||||
|
||||
"unplugin/acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
|
||||
|
||||
"unused-filename/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
@@ -6687,12 +6690,6 @@
|
||||
|
||||
"unzipper/fs-extra": ["fs-extra@11.3.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.69", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.46" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-C99M0T0SpRkcCClmJxbQkpSqGmxLfh3NhTsNF3aNaUQZZ7oXN5sPWi9LGs49X5Q/r9FWxBYeZARXs15xxtGIig=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.40", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw=="],
|
||||
|
||||
"vite-plugin-dynamic-import/acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
|
||||
|
||||
"vite-plugin-icons-spritesheet/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||
@@ -7241,8 +7238,6 @@
|
||||
|
||||
"@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
|
||||
|
||||
"ai/@ai-sdk/provider-utils/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
||||
|
||||
"ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
@@ -7541,10 +7536,6 @@
|
||||
|
||||
"tw-to-css/tailwindcss/postcss": ["postcss@8.5.26", "", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.46", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^6.28.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tEtld97plCFiYevsJuOkGkeuhQndeMWFBVrJS4AjnbD5AqrNSXRCe0p+BZ3Cju/sxDeeZ9ym3q9YUV8fASA7aQ=="],
|
||||
|
||||
"vitest/@vitest/expect/chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
|
||||
|
||||
"vscode-languageserver/vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
|
||||
@@ -8423,8 +8414,6 @@
|
||||
|
||||
"tw-to-css/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider-utils/undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="],
|
||||
|
||||
"yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"@astrojs/cloudflare/@cloudflare/vite-plugin/miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.1" }, "os": "darwin", "cpu": "arm64" }, "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg=="],
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"nodeModules": {
|
||||
"x86_64-linux": "sha256-2RlbJRTEKSliuUbAE2lAktX63JFR/RKAuLkcCou8wb4=",
|
||||
"aarch64-linux": "sha256-P7DAE018lTJNGmttg87U9oaTAuw/wHlnMStdnXYKCr0=",
|
||||
"aarch64-darwin": "sha256-N+NfV1ObOTnW+ez7As+CS+6ci/iRGCQ6cslvyQFCp6E="
|
||||
"x86_64-linux": "sha256-4AqU8dPEwo0ukoyEX1SuDVzsXQ7G/fIPnxoL400zH4M=",
|
||||
"aarch64-linux": "sha256-p75sJYtR8a4oVKb1+Dgp8Kl+1onSmUw5NRv95bbV1+E=",
|
||||
"aarch64-darwin": "sha256-Psyvbw/lGulysQlhK/MqcHVIwx2aCDTr+Pfr+gRWsG4="
|
||||
}
|
||||
}
|
||||
+6
-7
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "opencode",
|
||||
"description": "AI-powered development tool",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"packageManager": "bun@1.4.2",
|
||||
@@ -43,10 +43,10 @@
|
||||
"packages/stats/*"
|
||||
],
|
||||
"catalog": {
|
||||
"@effect/opentelemetry": "4.0.0-rc.118",
|
||||
"@effect/platform-node": "4.0.0-rc.118",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.118",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-rc.118",
|
||||
"@effect/opentelemetry": "4.0.0-rc.112",
|
||||
"@effect/platform-node": "4.0.0-rc.112",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.112",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-rc.112",
|
||||
"@npmcli/arborist": "9.4.0",
|
||||
"@types/bun": "1.4.0",
|
||||
"@types/cross-spawn": "6.0.6",
|
||||
@@ -80,8 +80,7 @@
|
||||
"dompurify": "3.4.14",
|
||||
"drizzle-kit": "1.0.0-rc.5-ab785fc",
|
||||
"drizzle-orm": "1.0.0-rc.5-169397b",
|
||||
"effect": "4.0.0-rc.118",
|
||||
"fast-check": "4.9.0",
|
||||
"effect": "4.0.0-rc.112",
|
||||
"ai": "6.0.168",
|
||||
"cross-spawn": "7.0.6",
|
||||
"hono": "4.10.7",
|
||||
|
||||
@@ -106,6 +106,41 @@ for await (const event of ai.llm.stream(ai.llm.request(input))) {
|
||||
await ai.dispose()
|
||||
```
|
||||
|
||||
## Venice AI
|
||||
|
||||
`Venice` provides native Chat Completions with streaming tools and reasoning. `model` and `chat`
|
||||
select the same API; credentials default to `VENICE_API_KEY`.
|
||||
|
||||
```ts
|
||||
import { LLM } from "@opencode/ai"
|
||||
import { Venice } from "@opencode/ai/providers"
|
||||
import { Effect } from "effect"
|
||||
|
||||
const program = Effect.gen(function* () {
|
||||
const response = yield* LLM.generate({
|
||||
model: Venice.configure({ apiKey: process.env.VENICE_API_KEY }).chat("qwen3-6-27b"),
|
||||
prompt: "Explain this design.",
|
||||
providerOptions: {
|
||||
reasoningEffort: "high",
|
||||
veniceParameters: { includeVeniceSystemPrompt: false },
|
||||
},
|
||||
})
|
||||
console.log(response.text)
|
||||
})
|
||||
```
|
||||
|
||||
Effort lowers to `reasoning.effort`; `reasoning.enabled` and `reasoning.summary` are also available.
|
||||
Supported effort levels and toggles depend on the selected model. Omitted controls preserve its defaults.
|
||||
Venice's added system prompt is disabled by default, matching the previous OpenCode Venice SDK behavior.
|
||||
|
||||
Replay complete `response.message` values to retain signed/encrypted reasoning and Gemini thought
|
||||
signatures, including per-tool signatures. Venice's encrypted scalar trailers are excluded from visible
|
||||
reasoning but retained in provider metadata for replay. Cache affinity uses `promptCacheKey`, and cache-write
|
||||
usage reads Venice's `cache_creation_input_tokens` field.
|
||||
|
||||
The native package entrypoint is `@opencode/ai/providers/venice`. Image generation, embeddings, Responses, and
|
||||
client-side E2EE are not implemented by this provider.
|
||||
|
||||
## Experimental evaluation
|
||||
|
||||
Evaluation models compare shared state with typed choice, score, and boolean questions. The API is
|
||||
|
||||
@@ -15,7 +15,7 @@ import { OpenAI } from "@opencode/ai/providers"
|
||||
* hover imports and local values to see how the public API is typed.
|
||||
*/
|
||||
|
||||
const apiKey = Config.Redacted("OPENAI_API_KEY")
|
||||
const apiKey = Config.redacted("OPENAI_API_KEY")
|
||||
|
||||
// 1. Configure a provider. The configured facade records provider identity,
|
||||
// deployment options, authentication, and defaults. Per-modality selectors pick
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "2.0.22",
|
||||
"version": "2.0.23",
|
||||
"name": "@opencode/ai",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as path from "node:path"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import { AwsV4Signer } from "aws4fetch"
|
||||
import { Config, ConfigProvider, Effect, FileSystem, PlatformError, Redacted } from "effect"
|
||||
import { FetchHttpClient, HttpClient, HttpClientRequest, type HttpClientResponse } from "effect/http"
|
||||
import { FetchHttpClient, HttpClient, HttpClientRequest, type HttpClientResponse } from "effect/unstable/http"
|
||||
import * as ProviderShared from "../src/protocols/shared"
|
||||
import { CloudflareAIGateway } from "../src/providers/cloudflare-ai-gateway.js"
|
||||
import { CloudflareWorkersAI } from "../src/providers/cloudflare-workers-ai.js"
|
||||
@@ -383,7 +383,7 @@ const readEnvFile = Effect.fn("RecordingEnv.readFile")(function* () {
|
||||
})
|
||||
|
||||
const readConfigString = (provider: ConfigProvider.ConfigProvider, name: string) =>
|
||||
Config.String(name)
|
||||
Config.string(name)
|
||||
.parse(provider)
|
||||
.pipe(
|
||||
Effect.match({
|
||||
|
||||
@@ -42,6 +42,7 @@ const RESPECTS_INLINE_HINTS = new Set([
|
||||
"alibaba-messages",
|
||||
"anthropic-messages",
|
||||
"anthropic-compatible-messages",
|
||||
"bedrock-mantle-messages",
|
||||
"cloudflare-ai-gateway-messages",
|
||||
"google-vertex-messages",
|
||||
"meta-messages",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/http"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import {
|
||||
ChoiceQuestion,
|
||||
EvaluationInput,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
export * as Media from "./media.js"
|
||||
|
||||
import { Effect, FileSystem, Schema, SchemaGetter } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { Effect, Encoding, FileSystem, Schema, SchemaGetter } from "effect"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { ProviderID } from "./schema/ids.js"
|
||||
import { AIError, HttpContext, InvalidProviderOutputError, InvalidRequestError } from "./schema/errors.js"
|
||||
import { ProviderMetadata } from "./schema/options.js"
|
||||
@@ -141,7 +140,7 @@ export class Asset {
|
||||
inline(): Inline | undefined {
|
||||
const source = this.source
|
||||
if (source.type !== "bytes" && source.type !== "base64") return undefined
|
||||
const base64 = source.type === "base64" ? source.data : (this.#base64 ??= Base64.encode(source.data))
|
||||
const base64 = source.type === "base64" ? source.data : (this.#base64 ??= Encoding.encodeBase64(source.data))
|
||||
const mime = this.mediaType.toLowerCase()
|
||||
return { mime, base64, dataUrl: `data:${mime};base64,${base64}` }
|
||||
}
|
||||
@@ -156,7 +155,7 @@ export class Asset {
|
||||
return Effect.fail(invalid(`Cannot materialize provider ref ${source.provider}:${source.id}`))
|
||||
const decoded =
|
||||
source.type === "base64"
|
||||
? Effect.fromResult(Base64.decode(source.data)).pipe(
|
||||
? Effect.fromResult(Encoding.decodeBase64(source.data)).pipe(
|
||||
Effect.mapError((cause) => invalid(`Media asset contains invalid base64 data`, cause)),
|
||||
)
|
||||
: download(source, this.headers)
|
||||
@@ -169,7 +168,7 @@ export class Asset {
|
||||
const source = this.source
|
||||
if (source.type === "base64") return Effect.succeed(source.data)
|
||||
if (this.#base64 !== undefined) return Effect.succeed(this.#base64)
|
||||
return this.bytes().pipe(Effect.map((data) => (this.#base64 = Base64.encode(data))))
|
||||
return this.bytes().pipe(Effect.map((data) => (this.#base64 = Encoding.encodeBase64(data))))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -184,7 +183,7 @@ export class Asset {
|
||||
toJSON() {
|
||||
const source = this.source
|
||||
return {
|
||||
source: source.type === "bytes" ? { ...source, data: Base64.encode(source.data) } : source,
|
||||
source: source.type === "bytes" ? { ...source, data: Encoding.encodeBase64(source.data) } : source,
|
||||
info: this.info,
|
||||
providerMetadata: this.providerMetadata,
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Auth } from "../route/auth.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { Framing } from "../route/framing.js"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { Headers } from "effect/http"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { HttpTransport } from "../route/transport/index.js"
|
||||
import {
|
||||
AIError,
|
||||
@@ -422,57 +422,74 @@ const AnthropicUsage = Schema.StructWithRest(
|
||||
)
|
||||
type AnthropicUsage = Schema.Schema.Type<typeof AnthropicUsage>
|
||||
|
||||
const AnthropicStreamBlock = Schema.Struct({
|
||||
type: Schema.String,
|
||||
id: Schema.optional(Schema.String),
|
||||
name: Schema.optional(Schema.String),
|
||||
text: Schema.optional(Schema.String),
|
||||
thinking: Schema.optional(Schema.String),
|
||||
signature: Schema.optional(Schema.String),
|
||||
// redacted_thinking blocks arrive whole in content_block_start with the
|
||||
// encrypted payload in `data`; there is no streaming delta sequence.
|
||||
data: Schema.optional(Schema.String),
|
||||
input: Schema.optional(Schema.Unknown),
|
||||
// *_tool_result blocks arrive whole as content_block_start (no streaming
|
||||
// delta) with the structured payload in `content` and the originating
|
||||
// server_tool_use id in `tool_use_id`.
|
||||
tool_use_id: Schema.optional(Schema.String),
|
||||
content: Schema.optional(Schema.Unknown),
|
||||
})
|
||||
const AnthropicStreamBlock = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
type: Schema.String,
|
||||
id: Schema.optional(Schema.String),
|
||||
name: Schema.optional(Schema.String),
|
||||
text: Schema.optional(Schema.String),
|
||||
thinking: Schema.optional(Schema.String),
|
||||
signature: Schema.optional(Schema.String),
|
||||
// redacted_thinking blocks arrive whole in content_block_start with the
|
||||
// encrypted payload in `data`; there is no streaming delta sequence.
|
||||
data: Schema.optional(Schema.String),
|
||||
input: Schema.optional(Schema.Unknown),
|
||||
// *_tool_result blocks arrive whole as content_block_start (no streaming
|
||||
// delta) with the structured payload in `content` and the originating
|
||||
// server_tool_use id in `tool_use_id`.
|
||||
tool_use_id: Schema.optional(Schema.String),
|
||||
content: Schema.optional(Schema.Unknown),
|
||||
}),
|
||||
[JsonObject],
|
||||
)
|
||||
type AnthropicStreamBlock = Schema.Schema.Type<typeof AnthropicStreamBlock>
|
||||
const decodeAnthropicStreamBlock = Schema.decodeUnknownOption(AnthropicStreamBlock)
|
||||
|
||||
const AnthropicStreamDelta = Schema.Struct({
|
||||
content: optionalNull(Schema.String),
|
||||
type: Schema.optional(Schema.String),
|
||||
text: Schema.optional(Schema.String),
|
||||
thinking: Schema.optional(Schema.String),
|
||||
partial_json: Schema.optional(Schema.String),
|
||||
signature: Schema.optional(Schema.String),
|
||||
stop_reason: optionalNull(Schema.String),
|
||||
stop_sequence: optionalNull(Schema.String),
|
||||
stop_details: optionalNull(
|
||||
Schema.Struct({ category: optionalNull(Schema.String), explanation: optionalNull(Schema.String) }),
|
||||
),
|
||||
})
|
||||
const AnthropicStreamDelta = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
content: optionalNull(Schema.String),
|
||||
type: Schema.optional(Schema.String),
|
||||
text: Schema.optional(Schema.String),
|
||||
thinking: Schema.optional(Schema.String),
|
||||
partial_json: Schema.optional(Schema.String),
|
||||
signature: Schema.optional(Schema.String),
|
||||
stop_reason: optionalNull(Schema.String),
|
||||
stop_sequence: optionalNull(Schema.String),
|
||||
stop_details: optionalNull(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({ category: optionalNull(Schema.String), explanation: optionalNull(Schema.String) }),
|
||||
[JsonObject],
|
||||
),
|
||||
),
|
||||
}),
|
||||
[JsonObject],
|
||||
)
|
||||
type AnthropicStreamDelta = Schema.Schema.Type<typeof AnthropicStreamDelta>
|
||||
const decodeAnthropicStreamDelta = Schema.decodeUnknownOption(AnthropicStreamDelta)
|
||||
|
||||
const AnthropicEvent = Schema.Struct({
|
||||
type: Schema.String,
|
||||
index: Schema.optional(Schema.Number),
|
||||
message: Schema.optional(Schema.Struct({ usage: Schema.optional(AnthropicUsage) })),
|
||||
content_block: Schema.optional(Schema.Unknown),
|
||||
delta: Schema.optional(Schema.Unknown),
|
||||
usage: Schema.optional(AnthropicUsage),
|
||||
// `type` and `message` are both required per Anthropic's spec, but
|
||||
// OpenAI-compatible proxies and gateway translations occasionally drop one
|
||||
// or the other; mark them optional so a partial payload still parses and
|
||||
// the parser can fall back to whichever field is populated.
|
||||
error: Schema.optional(
|
||||
Schema.Struct({ type: Schema.optional(Schema.String), message: Schema.optional(Schema.String) }),
|
||||
),
|
||||
})
|
||||
const AnthropicEvent = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
type: Schema.String,
|
||||
index: Schema.optional(Schema.Number),
|
||||
message: Schema.optional(
|
||||
Schema.StructWithRest(Schema.Struct({ usage: Schema.optional(AnthropicUsage) }), [JsonObject]),
|
||||
),
|
||||
content_block: Schema.optional(Schema.Unknown),
|
||||
delta: Schema.optional(Schema.Unknown),
|
||||
usage: Schema.optional(AnthropicUsage),
|
||||
// `type` and `message` are both required per Anthropic's spec, but
|
||||
// OpenAI-compatible proxies and gateway translations occasionally drop one
|
||||
// or the other; mark them optional so a partial payload still parses and
|
||||
// the parser can fall back to whichever field is populated.
|
||||
error: Schema.optional(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({ type: Schema.optional(Schema.String), message: Schema.optional(Schema.String) }),
|
||||
[JsonObject],
|
||||
),
|
||||
),
|
||||
}),
|
||||
[JsonObject],
|
||||
)
|
||||
type AnthropicEvent = Schema.Schema.Type<typeof AnthropicEvent>
|
||||
|
||||
interface ParserState {
|
||||
@@ -584,10 +601,7 @@ const serverToolResultType = (name: string): AnthropicServerToolResultType | und
|
||||
return undefined
|
||||
}
|
||||
|
||||
const lowerServerToolResult = Effect.fn("AnthropicMessages.lowerServerToolResult")(function* (
|
||||
part: ToolResultPart,
|
||||
providerMetadataKey: string,
|
||||
) {
|
||||
const lowerServerToolResult = Effect.fnUntraced(function* (part: ToolResultPart, providerMetadataKey: string) {
|
||||
const wireType = serverToolResultType(part.name)
|
||||
if (!wireType)
|
||||
return yield* invalid(`Anthropic Messages does not know how to round-trip server tool result for ${part.name}`)
|
||||
@@ -657,10 +671,7 @@ const citationsFromMetadata = (metadata: MediaPart["metadata"]): AnthropicDocume
|
||||
|
||||
const isHttpUrl = (value: string) => /^https?:\/\//i.test(value.trim())
|
||||
|
||||
const lowerMedia = Effect.fn("AnthropicMessages.lowerMedia")(function* (
|
||||
part: MediaPart,
|
||||
breakpoints?: Cache.Breakpoints,
|
||||
) {
|
||||
const lowerMedia = Effect.fnUntraced(function* (part: MediaPart, breakpoints?: Cache.Breakpoints) {
|
||||
const mime = part.media.mediaType.toLowerCase()
|
||||
const cacheControlValue = breakpoints ? cacheControl(breakpoints, part.cache) : undefined
|
||||
const fileId = fileIdFromMetadata(part.metadata)
|
||||
@@ -804,9 +815,6 @@ const requireThinkingSignature = (request: LLMRequest) => {
|
||||
return true
|
||||
}
|
||||
|
||||
// Mid-conversation system messages became available with Opus 4.8 and version
|
||||
// 5 of the other supported Claude families. Treat later family versions as
|
||||
// compatible without assuming that every Anthropic Messages model is Claude.
|
||||
// Opus 4.8 and every Claude 5 model accept mid-conversation system messages; later versions inherit support.
|
||||
const supportsNativeSystemUpdates = (request: LLMRequest) => {
|
||||
const version = claudeVersion(String(request.model.id))
|
||||
@@ -815,25 +823,9 @@ const supportsNativeSystemUpdates = (request: LLMRequest) => {
|
||||
return version.major >= 5
|
||||
}
|
||||
|
||||
const endsInServerToolUse = (message: LLMRequest["messages"][number]) => {
|
||||
const last = message.content.at(-1)
|
||||
return message.role === "assistant" && last?.type === "tool-call" && last.providerExecuted === true
|
||||
}
|
||||
|
||||
const canUseNativeSystemUpdate = (request: LLMRequest, index: number) => {
|
||||
const previous = request.messages[index - 1]
|
||||
const next = request.messages[index + 1]
|
||||
// Vertex currently rejects/404s for a system message after local tool results,
|
||||
// so fold it into the user tool-result turn across continuations and history.
|
||||
if (request.model.route.id === "google-vertex-messages" && previous?.role === "tool") return false
|
||||
return (
|
||||
previous !== undefined &&
|
||||
previous.role !== "system" &&
|
||||
(previous.role === "user" || previous.role === "tool" || endsInServerToolUse(previous)) &&
|
||||
next?.role !== "system" &&
|
||||
(next === undefined || next.role === "assistant")
|
||||
)
|
||||
}
|
||||
// Native system messages must follow a user turn (tool results count) or a paused server-tool turn.
|
||||
const acceptsNativeSystemAfter = (message: AnthropicMessage | undefined) =>
|
||||
message?.role === "user" || (message?.role === "assistant" && message.content.at(-1)?.type === "server_tool_use")
|
||||
|
||||
const splitsLocalToolResults = (messages: LLMRequest["messages"], index: number) => {
|
||||
const pending = new Set<string>()
|
||||
@@ -847,7 +839,7 @@ const splitsLocalToolResults = (messages: LLMRequest["messages"], index: number)
|
||||
return pending.size > 0
|
||||
}
|
||||
|
||||
const lowerNativeSystemUpdate = Effect.fn("AnthropicMessages.lowerNativeSystemUpdate")(function* (
|
||||
const lowerNativeSystemUpdate = Effect.fnUntraced(function* (
|
||||
message: LLMRequest["messages"][number],
|
||||
breakpoints: Cache.Breakpoints,
|
||||
) {
|
||||
@@ -862,12 +854,34 @@ const lowerNativeSystemUpdate = Effect.fn("AnthropicMessages.lowerNativeSystemUp
|
||||
}
|
||||
})
|
||||
|
||||
const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (
|
||||
request: LLMRequest,
|
||||
const lowerWrappedSystemUpdate = Effect.fnUntraced(function* (
|
||||
message: LLMRequest["messages"][number],
|
||||
breakpoints: Cache.Breakpoints,
|
||||
) {
|
||||
const part = yield* ProviderShared.wrappedSystemUpdate("Anthropic Messages", message)
|
||||
return { type: "text" as const, text: part.text, cache_control: cacheControl(breakpoints, part.cache) }
|
||||
})
|
||||
|
||||
const appendToUserTurn = (messages: AnthropicMessage[], block: AnthropicUserBlock) => {
|
||||
const last = messages.at(-1)
|
||||
if (last?.role === "user") messages[messages.length - 1] = { role: "user", content: [...last.content, block] }
|
||||
else messages.push({ role: "user", content: [block] })
|
||||
}
|
||||
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest, breakpoints: Cache.Breakpoints) {
|
||||
const messages: AnthropicMessage[] = []
|
||||
const providerMetadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider)
|
||||
// Text updates stay where they are unless a user turn follows them; then they move after the latest
|
||||
// user turn, the nearest spot where Anthropic accepts a native system message.
|
||||
const holdUpdates = supportsNativeSystemUpdates(request)
|
||||
const held: Array<LLMRequest["messages"][number]> = []
|
||||
const releaseHeld = Effect.fnUntraced(function* () {
|
||||
const native = acceptsNativeSystemAfter(messages.findLast((message) => message.role !== "system"))
|
||||
for (const update of held.splice(0)) {
|
||||
if (native) messages.push(yield* lowerNativeSystemUpdate(update, breakpoints))
|
||||
else appendToUserTurn(messages, yield* lowerWrappedSystemUpdate(update, breakpoints))
|
||||
}
|
||||
})
|
||||
|
||||
for (const [index, message] of request.messages.entries()) {
|
||||
if (message.role === "system") {
|
||||
@@ -879,16 +893,8 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (
|
||||
}
|
||||
if (splitsLocalToolResults(request.messages, index))
|
||||
return yield* invalid("Anthropic Messages system updates cannot split a local tool call from its tool result")
|
||||
if (supportsNativeSystemUpdates(request) && canUseNativeSystemUpdate(request, index)) {
|
||||
messages.push(yield* lowerNativeSystemUpdate(message, breakpoints))
|
||||
continue
|
||||
}
|
||||
const part = yield* ProviderShared.wrappedSystemUpdate("Anthropic Messages", message)
|
||||
const block = { type: "text" as const, text: part.text, cache_control: cacheControl(breakpoints, part.cache) }
|
||||
const previous = messages.at(-1)
|
||||
if (previous?.role === "user")
|
||||
messages[messages.length - 1] = { role: "user", content: [...previous.content, block] }
|
||||
else messages.push({ role: "user", content: [block] })
|
||||
if (holdUpdates) held.push(message)
|
||||
else appendToUserTurn(messages, yield* lowerWrappedSystemUpdate(message, breakpoints))
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -964,7 +970,9 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (
|
||||
`Anthropic Messages assistant messages only support text, reasoning, and tool-call content for now`,
|
||||
)
|
||||
}
|
||||
if (content.length > 0) messages.push({ role: "assistant", content })
|
||||
if (content.length === 0) continue
|
||||
yield* releaseHeld()
|
||||
messages.push({ role: "assistant", content })
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -985,10 +993,14 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (
|
||||
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] }
|
||||
else messages.push({ role: "user", content })
|
||||
}
|
||||
yield* releaseHeld()
|
||||
|
||||
return messages
|
||||
})
|
||||
|
||||
// TODO: Move per-model capability heuristics (`supportsEffortUpdates`, `supportsNativeSystemUpdates`,
|
||||
// `supportsThinkingBlockBinding`) into explicit model/provider `compatibility` metadata so the protocol
|
||||
// only reads `request.model.compatibility`.
|
||||
// Per-turn effort started with Claude Opus 5 and every Claude 5.1 model; later versions of any family inherit it.
|
||||
const supportsEffortUpdates = (model: LLMRequest["model"]) => {
|
||||
const override = model.compatibility?.supportsEffortUpdates
|
||||
@@ -1300,7 +1312,7 @@ const onContentBlockStart = (
|
||||
return [{ ...state, lifecycle: Lifecycle.stepStart(state.lifecycle, events) }, [...events, result]]
|
||||
}
|
||||
|
||||
const onContentBlockDelta = Effect.fn("AnthropicMessages.onContentBlockDelta")(function* (
|
||||
const onContentBlockDelta = Effect.fnUntraced(function* (
|
||||
state: ParserState,
|
||||
event: AnthropicEvent & { readonly delta: AnthropicStreamDelta },
|
||||
) {
|
||||
@@ -1368,7 +1380,7 @@ const onContentBlockDelta = Effect.fn("AnthropicMessages.onContentBlockDelta")(f
|
||||
return [state, NO_EVENTS] satisfies StepResult
|
||||
})
|
||||
|
||||
const onContentBlockStop = Effect.fn("AnthropicMessages.onContentBlockStop")(function* (
|
||||
const onContentBlockStop = Effect.fnUntraced(function* (
|
||||
state: ParserState,
|
||||
event: AnthropicEvent,
|
||||
) {
|
||||
@@ -1439,7 +1451,7 @@ const onMessageDelta = (
|
||||
]
|
||||
}
|
||||
|
||||
const onMessageStop = Effect.fn("AnthropicMessages.onMessageStop")(function* (state: ParserState) {
|
||||
const onMessageStop = Effect.fnUntraced(function* (state: ParserState) {
|
||||
if (Object.keys(state.compactions).length)
|
||||
return yield* ProviderShared.eventError(ADAPTER, "Response ended with an incomplete compaction block")
|
||||
const result = yield* ToolStream.finishAll(ADAPTER, state.tools)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Effect, Encoding, Schema } from "effect"
|
||||
import { Route } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
@@ -286,7 +285,7 @@ const lowerToolCall = (part: ToolCallPart, normalizeID: (id: string) => string):
|
||||
},
|
||||
})
|
||||
|
||||
const lowerToolResultContent = Effect.fn("BedrockConverse.lowerToolResultContent")(function* (
|
||||
const lowerToolResultContent = Effect.fnUntraced(function* (
|
||||
part: ToolResultPart,
|
||||
documentNames: Set<string>,
|
||||
) {
|
||||
@@ -306,7 +305,7 @@ const lowerToolResultContent = Effect.fn("BedrockConverse.lowerToolResultContent
|
||||
return content
|
||||
})
|
||||
|
||||
const lowerToolResult = Effect.fn("BedrockConverse.lowerToolResult")(function* (
|
||||
const lowerToolResult = Effect.fnUntraced(function* (
|
||||
part: ToolResultPart,
|
||||
documentNames: Set<string>,
|
||||
normalizeID: (id: string) => string,
|
||||
@@ -323,7 +322,7 @@ const lowerToolResult = Effect.fn("BedrockConverse.lowerToolResult")(function* (
|
||||
// Keep Claude and Nova tool-result images inline; put other models' images beside the result.
|
||||
const keepToolImagesInline = (id: string) => id.includes("anthropic.claude-") || id.includes("amazon.nova-")
|
||||
|
||||
const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (
|
||||
const lowerMessages = Effect.fnUntraced(function* (
|
||||
request: LLMRequest,
|
||||
breakpoints: BedrockCache.Breakpoints,
|
||||
) {
|
||||
@@ -611,7 +610,7 @@ interface ParserState {
|
||||
readonly reasoningRedactedContent: Readonly<Record<number, Uint8Array[]>>
|
||||
}
|
||||
|
||||
const encodeRedactedContent = (chunks: ReadonlyArray<Uint8Array>) => Base64.encode(concatBytes(chunks))
|
||||
const encodeRedactedContent = (chunks: ReadonlyArray<Uint8Array>) => Encoding.encodeBase64(concatBytes(chunks))
|
||||
|
||||
const step = (state: ParserState, event: BedrockEvent) =>
|
||||
Effect.gen(function* () {
|
||||
@@ -660,7 +659,7 @@ const step = (state: ParserState, event: BedrockEvent) =>
|
||||
const events: LLMEvent[] = []
|
||||
const redactedChunk = yield* (() => {
|
||||
if (reasoning.redactedContent === undefined) return Effect.succeed(undefined)
|
||||
return Effect.fromResult(Base64.decode(reasoning.redactedContent)).pipe(
|
||||
return Effect.fromResult(Encoding.decodeBase64(reasoning.redactedContent)).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.eventError(
|
||||
ADAPTER,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { EventStreamCodec } from "@smithy/eventstream-codec"
|
||||
import { fromUtf8, toUtf8 } from "@smithy/util-utf8"
|
||||
import { Effect, Stream } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Effect, Encoding, Stream } from "effect"
|
||||
import { AIError, AIErrorReason, InvalidProviderOutputError } from "../schema/index.js"
|
||||
import { Framing } from "../route/framing.js"
|
||||
import { ProviderShared } from "./shared.js"
|
||||
@@ -48,7 +47,7 @@ const consumeFrames = (route: string) => (state: FrameBufferState, input: FrameI
|
||||
route,
|
||||
classification: "incomplete-stream",
|
||||
message: `Incomplete Bedrock Converse event-stream frame: ${remaining.length} buffered bytes remain at end of stream`,
|
||||
body: Base64.encode(remaining),
|
||||
body: Encoding.encodeBase64(remaining),
|
||||
}),
|
||||
})
|
||||
return [state, []] as const
|
||||
@@ -69,7 +68,7 @@ const consumeFrames = (route: string) => (state: FrameBufferState, input: FrameI
|
||||
`Failed to decode Bedrock Converse event-stream frame: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
Base64.encode(view.subarray(0, totalLength)),
|
||||
Encoding.encodeBase64(view.subarray(0, totalLength)),
|
||||
error,
|
||||
),
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
|
||||
@@ -75,7 +75,7 @@ const usesSse = (request: MediaProtocol.Addressed<Request>) => request.mode ===
|
||||
|
||||
const CONTAINERS: Readonly<Record<string, "raw" | "wav" | "mp3">> = { pcm: "raw", wav: "wav", mp3: "mp3" }
|
||||
|
||||
const outputFormat = Effect.fn("CartesiaSpeech.outputFormat")(function* (request: MediaProtocol.Addressed<Request>) {
|
||||
const outputFormat = Effect.fnUntraced(function* (request: MediaProtocol.Addressed<Request>) {
|
||||
const sse = usesSse(request)
|
||||
const format = request.format ?? (sse ? "pcm" : "mp3")
|
||||
const container = CONTAINERS[format]
|
||||
@@ -121,7 +121,7 @@ const fromRequest = Effect.fn("CartesiaSpeech.fromRequest")(function* (request:
|
||||
// 6. Stream parsing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const onEvent = Effect.fn("CartesiaSpeech.onEvent")(function* (state: State, frame: string) {
|
||||
const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const event = yield* decodeEvent(frame)
|
||||
if (event.type === "chunk" && event.data !== undefined) return SpeechStream.delta(state, event.data)
|
||||
if (event.type === "timestamps" && event.word_timestamps !== undefined) {
|
||||
@@ -140,7 +140,7 @@ const onEvent = Effect.fn("CartesiaSpeech.onEvent")(function* (state: State, fra
|
||||
return [state, []] as const
|
||||
})
|
||||
|
||||
const finish = Effect.fn("CartesiaSpeech.finish")(function* (
|
||||
const finish = Effect.fnUntraced(function* (
|
||||
state: State,
|
||||
context: MediaProtocol.ResponseContext<Request>,
|
||||
) {
|
||||
|
||||
@@ -252,7 +252,7 @@ const mapUsage = (usage: typeof NativeUsage.Type) =>
|
||||
})
|
||||
|
||||
// Lifecycle deltas open blocks on demand and ends are no-ops for closed blocks, so content-start needs no handling.
|
||||
const step = Effect.fn("CohereChat.step")(function* (state: State, event: Event) {
|
||||
const step = Effect.fnUntraced(function* (state: State, event: Event) {
|
||||
const events: LLMEvent[] = []
|
||||
switch (event.type) {
|
||||
case "message-start":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
import { mergeJsonRecords, type OpenString } from "../schema/index.js"
|
||||
|
||||
@@ -95,7 +95,7 @@ const OUTPUT_FORMATS: Readonly<Record<string, string>> = {
|
||||
}
|
||||
|
||||
/** WAV is served only by the non-streaming endpoints. */
|
||||
const outputFormat = Effect.fn("ElevenLabsSpeech.outputFormat")(function* (request: MediaProtocol.Addressed<Request>) {
|
||||
const outputFormat = Effect.fnUntraced(function* (request: MediaProtocol.Addressed<Request>) {
|
||||
const format = request.providerOptions?.outputFormat ?? OUTPUT_FORMATS[request.format ?? "mp3"]
|
||||
if (format === undefined)
|
||||
return yield* route.unsupported(
|
||||
@@ -138,7 +138,7 @@ const path = (request: MediaProtocol.Addressed<Request>) =>
|
||||
// 6. Stream parsing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const onRecord = Effect.fn("ElevenLabsSpeech.onRecord")(function* (state: State, frame: string) {
|
||||
const onRecord = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const record = yield* decodeRecord(frame)
|
||||
const [next, events] = SpeechStream.delta(state, record.audio_base64)
|
||||
const alignment = record.alignment
|
||||
@@ -169,7 +169,7 @@ const describeOutput = (format: string) => {
|
||||
return encoding === undefined ? SpeechStream.container(codec, sampleRate) : SpeechStream.pcm(encoding, sampleRate)
|
||||
}
|
||||
|
||||
const finish = Effect.fn("ElevenLabsSpeech.finish")(function* (
|
||||
const finish = Effect.fnUntraced(function* (
|
||||
state: State,
|
||||
context: MediaProtocol.ResponseContext<Request>,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
import { mergeJsonRecords, type OpenString } from "../schema/index.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
|
||||
@@ -283,7 +283,7 @@ const lowerToolConfig = (toolChoice: NonNullable<LLMRequest["toolChoice"]>) =>
|
||||
tool: (name) => ({ functionCallingConfig: { mode: "ANY" as const, allowedFunctionNames: [name] } }),
|
||||
})
|
||||
|
||||
const lowerContentPart = Effect.fn("Gemini.lowerContentPart")(function* (part: TextPart | MediaPart) {
|
||||
const lowerContentPart = Effect.fnUntraced(function* (part: TextPart | MediaPart) {
|
||||
if (part.type === "text") return { text: part.text }
|
||||
return yield* GeminiGenerateContent.mediaPart("Gemini", part.media)
|
||||
})
|
||||
@@ -302,7 +302,7 @@ const lowerToolCall = (part: ToolCallPart, omitIds: boolean, metadataKey: string
|
||||
thoughtSignature: thoughtSignature(part.providerMetadata, metadataKey),
|
||||
})
|
||||
|
||||
const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request: LLMRequest) {
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
const contents: GeminiContent[] = []
|
||||
const metadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider)
|
||||
const omitCallIds = omitsFunctionCallIds(request.model.id)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
|
||||
@@ -182,7 +182,7 @@ type StepResult = readonly [ParserState, ReadonlyArray<LLMEvent>]
|
||||
// =============================================================================
|
||||
// Request Body Construction
|
||||
// =============================================================================
|
||||
const mediaContent = Effect.fn("GoogleInteractions.mediaContent")(function* (asset: Media.Asset) {
|
||||
const mediaContent = Effect.fnUntraced(function* (asset: Media.Asset) {
|
||||
if (
|
||||
asset.kind !== "image" &&
|
||||
asset.kind !== "audio" &&
|
||||
@@ -208,7 +208,7 @@ const signature = (metadata: ProviderMetadata | undefined, key: string) => {
|
||||
: undefined
|
||||
}
|
||||
|
||||
const lowerMessages = Effect.fn("GoogleInteractions.lowerMessages")(function* (request: LLMRequest) {
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
const steps: InputStep[] = []
|
||||
const key = request.model.route.providerMetadataKey ?? String(request.model.provider)
|
||||
for (const message of request.messages) {
|
||||
@@ -275,7 +275,7 @@ const lowerMessages = Effect.fn("GoogleInteractions.lowerMessages")(function* (r
|
||||
return steps
|
||||
})
|
||||
|
||||
const lowerToolResult = Effect.fn("GoogleInteractions.lowerToolResult")(function* (part: ToolResultPart) {
|
||||
const lowerToolResult = Effect.fnUntraced(function* (part: ToolResultPart) {
|
||||
if (part.result.type === "json" && ProviderShared.isRecord(part.result.value)) return part.result.value
|
||||
if (part.result.type !== "content") return ProviderShared.toolResultText(part)
|
||||
|
||||
@@ -364,7 +364,7 @@ const mapUsage = (usage: RawUsage | undefined, key: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
const onStart = Effect.fn("GoogleInteractions.onStart")(function* (
|
||||
const onStart = Effect.fnUntraced(function* (
|
||||
state: ParserState,
|
||||
index: number,
|
||||
step: OutputStep,
|
||||
@@ -402,7 +402,7 @@ const onStart = Effect.fn("GoogleInteractions.onStart")(function* (
|
||||
return [{ ...state, lifecycle, tools, steps: { ...state.steps, [index]: step } }, events] satisfies StepResult
|
||||
})
|
||||
|
||||
const onDelta = Effect.fn("GoogleInteractions.onDelta")(function* (
|
||||
const onDelta = Effect.fnUntraced(function* (
|
||||
state: ParserState,
|
||||
index: number,
|
||||
delta: typeof Delta.Type,
|
||||
@@ -447,7 +447,7 @@ const onDelta = Effect.fn("GoogleInteractions.onDelta")(function* (
|
||||
return yield* ProviderShared.eventError(ADAPTER, `Unsupported Interactions delta: ${delta.type}`, encodeJson(delta))
|
||||
})
|
||||
|
||||
const onStop = Effect.fn("GoogleInteractions.onStop")(function* (state: ParserState, index: number) {
|
||||
const onStop = Effect.fnUntraced(function* (state: ParserState, index: number) {
|
||||
const step = state.steps[index]
|
||||
if (!step) return yield* ProviderShared.eventError(ADAPTER, "Interactions step.stop without step.start")
|
||||
const events: LLMEvent[] = []
|
||||
@@ -465,7 +465,7 @@ const onStop = Effect.fn("GoogleInteractions.onStop")(function* (state: ParserSt
|
||||
return [{ ...state, tools: result.tools }, result.events ?? []] satisfies StepResult
|
||||
})
|
||||
|
||||
const step = Effect.fn("GoogleInteractions.step")(function* (state: ParserState, event: Event) {
|
||||
const step = Effect.fnUntraced(function* (state: ParserState, event: Event) {
|
||||
switch (event.event_type) {
|
||||
case "step.start":
|
||||
return yield* onStart(state, event.index, event.step)
|
||||
|
||||
@@ -94,7 +94,7 @@ const fromRequest = Effect.fn("GoogleSpeech.fromRequest")(function* (request: Me
|
||||
// 6. Stream parsing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const step = Effect.fn("GoogleSpeech.step")(function* (state: State, frame: string) {
|
||||
const step = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const chunk = yield* decodeChunk(frame)
|
||||
const blocked = GeminiGenerateContent.blocked(route.name, chunk, frame)
|
||||
if (blocked !== undefined) return yield* blocked
|
||||
|
||||
@@ -138,7 +138,7 @@ const turn = (part: Schema.Schema.Type<typeof AudioTranscription>) => {
|
||||
}
|
||||
}
|
||||
|
||||
const step = Effect.fn("GoogleTranscription.step")(function* (state: State, frame: string) {
|
||||
const step = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const chunk = yield* decodeChunk(frame)
|
||||
const blocked = GeminiGenerateContent.blocked(route.name, chunk, frame)
|
||||
if (blocked !== undefined) return yield* blocked
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Effect, Encoding, Schema } from "effect"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { LLMEvent, LLMRequest, Message, ToolResultPart } from "../schema/index.js"
|
||||
import { OpenResponses } from "./open-responses.js"
|
||||
@@ -96,7 +95,7 @@ const HOSTED_TOOLS = {
|
||||
image_generation_call: {
|
||||
name: "image_generation",
|
||||
input: () => ({}),
|
||||
result: Effect.fn("MetaResponses.imageResult")(function* (raw: ResponsesHostedTools.Item) {
|
||||
result: Effect.fnUntraced(function* (raw: ResponsesHostedTools.Item) {
|
||||
const item = yield* Schema.decodeUnknownEffect(ImageItem)(raw).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.eventError(
|
||||
@@ -114,7 +113,7 @@ const HOSTED_TOOLS = {
|
||||
"Meta returned an image without data",
|
||||
ProviderShared.encodeJson(raw),
|
||||
)
|
||||
const data = yield* Effect.fromResult(Base64.decode(item.result)).pipe(
|
||||
const data = yield* Effect.fromResult(Encoding.decodeBase64(item.result)).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.eventError(
|
||||
ADAPTER,
|
||||
@@ -137,7 +136,7 @@ const HOSTED_TOOLS = {
|
||||
},
|
||||
} satisfies ResponsesHostedTools.Definitions
|
||||
|
||||
const onEvent = Effect.fn("MetaResponses.onEvent")(function* (
|
||||
const onEvent = Effect.fnUntraced(function* (
|
||||
state: OpenResponses.ParserState,
|
||||
input: OpenResponses.Event,
|
||||
) {
|
||||
@@ -174,7 +173,7 @@ const onEvent = Effect.fn("MetaResponses.onEvent")(function* (
|
||||
] satisfies OpenResponses.StepResult
|
||||
})
|
||||
|
||||
const step = Effect.fn("MetaResponses.step")(function* (state: ParserState, input: OpenResponses.Event) {
|
||||
const step = Effect.fnUntraced(function* (state: ParserState, input: OpenResponses.Event) {
|
||||
const completedItems = new Set(state.completedItems)
|
||||
const event = OpenResponses.normalize(state, input)
|
||||
if (event.type === "response.output_item.done" && event.item && completedItems.has(event.item.id))
|
||||
|
||||
@@ -226,7 +226,7 @@ const MistralEvent = Schema.StructWithRest(
|
||||
type MistralEvent = Schema.Schema.Type<typeof MistralEvent>
|
||||
const MistralStreamEvent = Schema.Union([Schema.Literal(DONE), Protocol.jsonEvent(MistralEvent)])
|
||||
|
||||
const lowerMedia = Effect.fn("MistralChat.lowerMedia")(function* (part: MediaPart) {
|
||||
const lowerMedia = Effect.fnUntraced(function* (part: MediaPart) {
|
||||
const mime = part.media.mediaType.toLowerCase()
|
||||
const url =
|
||||
ProviderShared.mediaUrl(part.media) ??
|
||||
@@ -236,7 +236,7 @@ const lowerMedia = Effect.fn("MistralChat.lowerMedia")(function* (part: MediaPar
|
||||
return yield* ProviderShared.invalidRequest(`Mistral Chat does not support media type ${part.media.mediaType}`)
|
||||
})
|
||||
|
||||
const lowerUser = Effect.fn("MistralChat.lowerUser")(function* (message: LLMRequest["messages"][number]) {
|
||||
const lowerUser = Effect.fnUntraced(function* (message: LLMRequest["messages"][number]) {
|
||||
const content: MistralUserContent[] = []
|
||||
for (const part of message.content) {
|
||||
if (part.type === "text") {
|
||||
@@ -260,7 +260,7 @@ const lowerToolCall = (part: ToolCallPart, normalizeID: (id: string) => string):
|
||||
function: { name: part.name, arguments: ProviderShared.encodeJson(part.input) },
|
||||
})
|
||||
|
||||
const lowerAssistant = Effect.fn("MistralChat.lowerAssistant")(function* (
|
||||
const lowerAssistant = Effect.fnUntraced(function* (
|
||||
message: LLMRequest["messages"][number],
|
||||
normalizeID: (id: string) => string,
|
||||
prefix: boolean,
|
||||
@@ -298,7 +298,7 @@ const lowerAssistant = Effect.fn("MistralChat.lowerAssistant")(function* (
|
||||
}
|
||||
})
|
||||
|
||||
const lowerToolResults = Effect.fn("MistralChat.lowerToolResults")(function* (
|
||||
const lowerToolResults = Effect.fnUntraced(function* (
|
||||
message: LLMRequest["messages"][number],
|
||||
normalizeID: (id: string) => string,
|
||||
) {
|
||||
@@ -335,7 +335,7 @@ const lowerToolResults = Effect.fn("MistralChat.lowerToolResults")(function* (
|
||||
return output
|
||||
})
|
||||
|
||||
const lowerMessages = Effect.fn("MistralChat.lowerMessages")(function* (request: LLMRequest) {
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
const normalizeID = MistralToolID.normalizer(request)
|
||||
const messages: MistralMessage[] =
|
||||
request.system.length === 0
|
||||
@@ -596,7 +596,7 @@ const toolText = (tool: MistralToolDelta) => {
|
||||
return value === null || value === undefined ? "" : ProviderShared.encodeJson(value)
|
||||
}
|
||||
|
||||
const appendTools = Effect.fn("MistralChat.appendTools")(function* (
|
||||
const appendTools = Effect.fnUntraced(function* (
|
||||
initial: ParserState,
|
||||
events: LLMEvent[],
|
||||
deltas: ReadonlyArray<MistralToolDelta>,
|
||||
@@ -662,7 +662,7 @@ const hasLateContent = (event: MistralEvent) => {
|
||||
)
|
||||
}
|
||||
|
||||
const step = Effect.fn("MistralChat.step")(function* (state: ParserState, event: MistralEvent) {
|
||||
const step = Effect.fnUntraced(function* (state: ParserState, event: MistralEvent) {
|
||||
if (event.error) {
|
||||
const body = ProviderShared.encodeJson(event)
|
||||
return yield* new AIError({
|
||||
@@ -726,7 +726,7 @@ const step = Effect.fn("MistralChat.step")(function* (state: ParserState, event:
|
||||
] as const
|
||||
})
|
||||
|
||||
const finishEvents = Effect.fn("MistralChat.finishEvents")(function* (state: ParserState) {
|
||||
const finishEvents = Effect.fnUntraced(function* (state: ParserState) {
|
||||
if (!state.finishReason)
|
||||
return yield* new AIError({
|
||||
reason: new InvalidProviderOutputError({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema, Stream } from "effect"
|
||||
import { Headers } from "effect/http"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Framing } from "../route/framing.js"
|
||||
import type { HttpContext } from "../schema/index.js"
|
||||
import {
|
||||
|
||||
@@ -301,18 +301,26 @@ export const OpenResponsesBody = Schema.Struct({
|
||||
})
|
||||
export type OpenResponsesBody = Schema.Schema.Type<typeof OpenResponsesBody>
|
||||
|
||||
export const OpenResponsesUsage = Schema.Struct({
|
||||
input_tokens: Schema.optional(Schema.Number),
|
||||
input_tokens_details: optionalNull(
|
||||
Schema.Struct({
|
||||
cached_tokens: Schema.optional(Schema.Number),
|
||||
cache_write_tokens: Schema.optional(Schema.Number),
|
||||
}),
|
||||
),
|
||||
output_tokens: Schema.optional(Schema.Number),
|
||||
output_tokens_details: optionalNull(Schema.Struct({ reasoning_tokens: Schema.optional(Schema.Number) })),
|
||||
total_tokens: Schema.optional(Schema.Number),
|
||||
})
|
||||
export const OpenResponsesUsage = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
input_tokens: Schema.optional(Schema.Number),
|
||||
input_tokens_details: optionalNull(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
cached_tokens: Schema.optional(Schema.Number),
|
||||
cache_write_tokens: Schema.optional(Schema.Number),
|
||||
}),
|
||||
[JsonObject],
|
||||
),
|
||||
),
|
||||
output_tokens: Schema.optional(Schema.Number),
|
||||
output_tokens_details: optionalNull(
|
||||
Schema.StructWithRest(Schema.Struct({ reasoning_tokens: Schema.optional(Schema.Number) }), [JsonObject]),
|
||||
),
|
||||
total_tokens: Schema.optional(Schema.Number),
|
||||
}),
|
||||
[JsonObject],
|
||||
)
|
||||
type OpenResponsesUsage = Schema.Schema.Type<typeof OpenResponsesUsage>
|
||||
|
||||
// The spec requires `id` on every output item, but some gateways drop it from
|
||||
@@ -442,7 +450,7 @@ interface ReasoningStreamItem {
|
||||
// =============================================================================
|
||||
// Request Lowering
|
||||
// =============================================================================
|
||||
export const lowerTool = Effect.fn("OpenResponses.lowerTool")(function* (protocolName: string, tool: ToolDefinition) {
|
||||
export const lowerTool = Effect.fnUntraced(function* (protocolName: string, tool: ToolDefinition) {
|
||||
if (tool.native !== undefined)
|
||||
return yield* ProviderShared.invalidRequest(`${protocolName} does not support provider-native tool ${tool.name}`)
|
||||
return {
|
||||
@@ -507,7 +515,10 @@ const lowerReasoning = (part: ReasoningPart, providerMetadataKey: string): OpenR
|
||||
}
|
||||
}
|
||||
|
||||
const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (
|
||||
const decodeImageDetail = ProviderShared.validateWith(Schema.decodeUnknownEffect(OpenResponsesInputImage.fields.detail))
|
||||
const decodeMessageMetadata = ProviderShared.validateWith(Schema.decodeUnknownEffect(MessageMetadata))
|
||||
|
||||
const lowerMedia = Effect.fnUntraced(function* (
|
||||
part: MediaPart,
|
||||
request: LLMRequest,
|
||||
adapter: ProviderAdapter,
|
||||
@@ -516,9 +527,8 @@ const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (
|
||||
const media = part.media.inline()
|
||||
const providerMedia = adapter.lowerMedia?.({ part, media, request })
|
||||
if (providerMedia) return providerMedia
|
||||
const detail = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(OpenResponsesInputImage.fields.detail))(
|
||||
part.providerMetadata?.[metadataKey(request.model)]?.detail,
|
||||
)
|
||||
const rawDetail = part.providerMetadata?.[metadataKey(request.model)]?.detail
|
||||
const detail = rawDetail === undefined ? undefined : yield* decodeImageDetail(rawDetail)
|
||||
const mime = part.media.mediaType.toLowerCase()
|
||||
const url = ProviderShared.mediaUrl(part.media)
|
||||
const location = url ?? (yield* ProviderShared.requireInlineMedia(adapter.name, part.media)).dataUrl
|
||||
@@ -591,7 +601,7 @@ const lowerToolResultOutput = Effect.fnUntraced(function* (
|
||||
|
||||
const DEFAULT_EFFORT = "medium"
|
||||
|
||||
const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (
|
||||
const lowerMessages = Effect.fnUntraced(function* (
|
||||
request: LLMRequest,
|
||||
adapter: ProviderAdapter,
|
||||
) {
|
||||
@@ -599,9 +609,8 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (
|
||||
const providerMetadataKey = metadataKey(request.model)
|
||||
|
||||
for (const message of request.messages) {
|
||||
const metadata = yield* ProviderShared.validateWith(
|
||||
Schema.decodeUnknownEffect(Schema.UndefinedOr(MessageMetadata)),
|
||||
)(message.providerMetadata?.[providerMetadataKey])
|
||||
const rawMetadata = message.providerMetadata?.[providerMetadataKey]
|
||||
const metadata = rawMetadata === undefined ? undefined : yield* decodeMessageMetadata(rawMetadata)
|
||||
if (message.role === "system") {
|
||||
const update = effortUpdate(message)
|
||||
if (update) {
|
||||
@@ -755,7 +764,7 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (
|
||||
return input
|
||||
})
|
||||
|
||||
export const lowerConversation = Effect.fn("OpenResponses.lowerConversation")(function* (
|
||||
export const lowerConversation = Effect.fnUntraced(function* (
|
||||
request: LLMRequest,
|
||||
adapter: ProviderAdapter,
|
||||
) {
|
||||
@@ -1142,7 +1151,7 @@ const onReasoningSummaryPartDone = (state: ParserState, event: Event): StepResul
|
||||
]
|
||||
}
|
||||
|
||||
const onFunctionCallArgumentsDelta = Effect.fn("OpenResponses.onFunctionCallArgumentsDelta")(function* (
|
||||
const onFunctionCallArgumentsDelta = Effect.fnUntraced(function* (
|
||||
state: ParserState,
|
||||
event: Event,
|
||||
) {
|
||||
@@ -1173,7 +1182,7 @@ const onFunctionCallArgumentsDelta = Effect.fn("OpenResponses.onFunctionCallArgu
|
||||
return [{ ...state, lifecycle, tools: result.tools }, events] satisfies StepResult
|
||||
})
|
||||
|
||||
const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
|
||||
const onOutputItemDone = Effect.fnUntraced(function* (
|
||||
state: ParserState,
|
||||
item: NormalizedEvent["item"],
|
||||
) {
|
||||
@@ -1309,7 +1318,7 @@ const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
|
||||
return [state, NO_EVENTS] satisfies StepResult
|
||||
})
|
||||
|
||||
const onResponseFinish = Effect.fn("OpenResponses.onResponseFinish")(function* (state: ParserState, event: Event) {
|
||||
const onResponseFinish = Effect.fnUntraced(function* (state: ParserState, event: Event) {
|
||||
let current = state
|
||||
const events: LLMEvent[] = []
|
||||
if (event.type === "response.completed") {
|
||||
|
||||
@@ -65,7 +65,7 @@ const ExtraContent = Schema.Struct({
|
||||
})
|
||||
const decodeExtraContent = (value: unknown) => Option.getOrUndefined(Schema.decodeUnknownOption(ExtraContent)(value))
|
||||
|
||||
const OpenAIChatAssistantToolCall = Schema.Struct({
|
||||
export const OpenAIChatAssistantToolCall = Schema.Struct({
|
||||
id: Schema.String,
|
||||
type: Schema.tag("function"),
|
||||
function: Schema.Struct({
|
||||
@@ -134,7 +134,7 @@ const OpenAIChatUserContent = Schema.Union([
|
||||
])
|
||||
type OpenAIChatUserContent = Schema.Schema.Type<typeof OpenAIChatUserContent>
|
||||
|
||||
const OpenAIChatMessage = Schema.Union([
|
||||
export const OpenAIChatMessage = Schema.Union([
|
||||
Schema.Struct({
|
||||
role: Schema.Literal("system"),
|
||||
content: Schema.Union([Schema.String, Schema.Array(OpenAIChatUserContent)]),
|
||||
@@ -200,7 +200,7 @@ export type OpenAIChatBody = Schema.Schema.Type<typeof OpenAIChatBody>
|
||||
// The event schema is one decoded SSE `data:` payload. `Framing.sse` splits the
|
||||
// byte stream into strings, then `Protocol.jsonEvent` decodes each string into
|
||||
// this provider-native event shape.
|
||||
const OpenAIChatUsage = Schema.StructWithRest(
|
||||
export const OpenAIChatUsage = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
prompt_tokens: optionalNull(Schema.Number),
|
||||
completion_tokens: optionalNull(Schema.Number),
|
||||
@@ -238,7 +238,7 @@ const OpenAIChatToolCallDeltaFunction = Schema.Struct({
|
||||
arguments: optionalNull(Schema.String),
|
||||
})
|
||||
|
||||
const OpenAIChatToolCallDelta = Schema.Struct({
|
||||
export const OpenAIChatToolCallDelta = Schema.Struct({
|
||||
index: optionalNull(Schema.Number),
|
||||
id: optionalNull(Schema.String),
|
||||
function: optionalNull(OpenAIChatToolCallDeltaFunction),
|
||||
@@ -246,7 +246,7 @@ const OpenAIChatToolCallDelta = Schema.Struct({
|
||||
})
|
||||
type OpenAIChatToolCallDelta = Schema.Schema.Type<typeof OpenAIChatToolCallDelta>
|
||||
|
||||
const OpenAIChatDelta = Schema.StructWithRest(
|
||||
export const OpenAIChatDelta = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
content: optionalNull(Schema.String),
|
||||
refusal: optionalNull(Schema.String),
|
||||
@@ -259,7 +259,7 @@ const OpenAIChatDelta = Schema.StructWithRest(
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
|
||||
const OpenAIChatChoice = Schema.StructWithRest(
|
||||
export const OpenAIChatChoice = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
delta: optionalNull(OpenAIChatDelta),
|
||||
finish_reason: optionalNull(Schema.String),
|
||||
@@ -326,6 +326,8 @@ export interface ParserState {
|
||||
interface LoweringOptions {
|
||||
readonly cacheControl?: (cache: CacheHint | undefined) => OpenAIChatCacheControl | undefined
|
||||
readonly toolCallID?: (id: string) => string
|
||||
/** Project provider-specific fields from the exact source, even when other messages are dropped during lowering. */
|
||||
readonly assistant?: (source: LLMRequest["messages"][number], message: OpenAIChatMessage) => OpenAIChatMessage
|
||||
}
|
||||
|
||||
const lowerTool = (tool: ToolDefinition, options: LoweringOptions, supportsStrictMode: boolean): OpenAIChatTool => ({
|
||||
@@ -360,7 +362,7 @@ const lowerToolCall = (
|
||||
extra_content: decodeExtraContent(part.providerMetadata?.[options.providerMetadataKey]?.extraContent),
|
||||
})
|
||||
|
||||
const lowerMedia = Effect.fn("OpenAIChat.lowerMedia")(function* (part: MediaPart) {
|
||||
const lowerMedia = Effect.fnUntraced(function* (part: MediaPart) {
|
||||
// Chat Completions accepts PDFs, and no other documents, as inline `file` parts; file URLs are not supported.
|
||||
if (part.media.mediaType.toLowerCase() === "application/pdf")
|
||||
return {
|
||||
@@ -406,7 +408,7 @@ const lowerReasoningDetail = (detail: ReasoningDetail) => {
|
||||
|
||||
const isKimiDetail = (detail: { readonly type: string }) => detail.type === "summary" || detail.type === "encrypted"
|
||||
|
||||
const lowerUserMessage = Effect.fn("OpenAIChat.lowerUserMessage")(function* (
|
||||
const lowerUserMessage = Effect.fnUntraced(function* (
|
||||
message: OpenAIChatRequestMessage,
|
||||
options: LoweringOptions,
|
||||
) {
|
||||
@@ -430,7 +432,7 @@ const lowerUserMessage = Effect.fn("OpenAIChat.lowerUserMessage")(function* (
|
||||
return { role: "user" as const, content }
|
||||
})
|
||||
|
||||
const lowerAssistantMessage = Effect.fn("OpenAIChat.lowerAssistantMessage")(function* (
|
||||
const lowerAssistantMessage = Effect.fnUntraced(function* (
|
||||
message: OpenAIChatRequestMessage,
|
||||
configuredField: string | undefined,
|
||||
requireReasoning: boolean,
|
||||
@@ -495,7 +497,7 @@ const lowerAssistantMessage = Effect.fn("OpenAIChat.lowerAssistantMessage")(func
|
||||
return { ...result, [field]: reasoningText }
|
||||
})
|
||||
|
||||
const lowerToolMessages = Effect.fn("OpenAIChat.lowerToolMessages")(function* (
|
||||
const lowerToolMessages = Effect.fnUntraced(function* (
|
||||
message: OpenAIChatRequestMessage,
|
||||
options: LoweringOptions,
|
||||
) {
|
||||
@@ -532,19 +534,21 @@ const toolMessage = (toolCallID: string, text: string, cacheControl: OpenAIChatC
|
||||
content: cacheControl === undefined ? text : [{ type: "text" as const, text, cache_control: cacheControl }],
|
||||
})
|
||||
|
||||
const lowerMessage = Effect.fn("OpenAIChat.lowerMessage")(function* (
|
||||
const lowerMessage = Effect.fnUntraced(function* (
|
||||
message: OpenAIChatRequestMessage,
|
||||
reasoningField: string | undefined,
|
||||
requireReasoning: boolean,
|
||||
options: LoweringOptions & { readonly providerMetadataKey: string },
|
||||
) {
|
||||
if (message.role === "user") return [yield* lowerUserMessage(message, options)]
|
||||
if (message.role === "assistant")
|
||||
return [yield* lowerAssistantMessage(message, reasoningField, requireReasoning, options)]
|
||||
if (message.role === "assistant") {
|
||||
const lowered = yield* lowerAssistantMessage(message, reasoningField, requireReasoning, options)
|
||||
return [options.assistant?.(message, lowered) ?? lowered]
|
||||
}
|
||||
return (yield* lowerToolMessages(message, options)).messages
|
||||
})
|
||||
|
||||
const lowerMessages = Effect.fn("OpenAIChat.lowerMessages")(function* (request: LLMRequest, options: LoweringOptions) {
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest, options: LoweringOptions) {
|
||||
const system: OpenAIChatMessage[] =
|
||||
request.system.length === 0
|
||||
? []
|
||||
@@ -855,7 +859,7 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (
|
||||
// Streaming parsers are small state machines: every event returns a new state
|
||||
// plus the common `LLMEvent`s produced by that event. Tool calls are accumulated
|
||||
// because OpenAI streams JSON arguments across multiple deltas.
|
||||
const mapFinishReason = Effect.fn("OpenAIChat.mapFinishReason")(function* (event: OpenAIChatEvent, reason: string) {
|
||||
const mapFinishReason = Effect.fnUntraced(function* (event: OpenAIChatEvent, reason: string) {
|
||||
switch (reason) {
|
||||
case "error":
|
||||
return yield* new AIError({
|
||||
@@ -1214,7 +1218,7 @@ const step = (state: ParserState, event: OpenAIChatEvent) =>
|
||||
] as const
|
||||
})
|
||||
|
||||
const finishEvents = Effect.fn("OpenAIChat.finishEvents")(function* (state: ParserState) {
|
||||
export const finishEvents = Effect.fnUntraced(function* (state: ParserState) {
|
||||
if (state.finishReason === undefined && state.requireFinishReason)
|
||||
return yield* new AIError({
|
||||
reason: new InvalidProviderOutputError({
|
||||
|
||||
@@ -208,7 +208,7 @@ const eventImage = (frame: string, label: string, data: string, format: string,
|
||||
info: info(format, size),
|
||||
})
|
||||
|
||||
const onEvent = Effect.fn("OpenAIImages.onEvent")(function* (state: State, frame: string) {
|
||||
const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const event = yield* decodeEvent(frame)
|
||||
const format = event.output_format
|
||||
if ("partial_image_index" in event) {
|
||||
@@ -229,7 +229,7 @@ const onEvent = Effect.fn("OpenAIImages.onEvent")(function* (state: State, frame
|
||||
] as const
|
||||
})
|
||||
|
||||
const onDocument = Effect.fn("OpenAIImages.onDocument")(function* (frame: Exclude<Frame, string>) {
|
||||
const onDocument = Effect.fnUntraced(function* (frame: Exclude<Frame, string>) {
|
||||
const invalid = (message: string, cause?: unknown) => route.frameError(message, frame.document, cause)
|
||||
const decoded = yield* decodeDocument(frame.document).pipe(
|
||||
Effect.mapError((cause) => invalid(`${route.name} returned an invalid response`, cause)),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Headers } from "effect/http"
|
||||
import { Effect, Encoding, Schema } from "effect"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Route } from "../route/client.js"
|
||||
import { Auth } from "../route/auth.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
@@ -158,7 +157,7 @@ const nativeImageTool = (tool: ToolDefinition) => {
|
||||
return Schema.is(OpenAIResponsesImageGenerationTool)(native) ? native : undefined
|
||||
}
|
||||
|
||||
const lowerTool = Effect.fn("OpenAIResponses.lowerTool")(function* (tool: ToolDefinition) {
|
||||
const lowerTool = Effect.fnUntraced(function* (tool: ToolDefinition) {
|
||||
const native = nativeImageToolInput(tool)
|
||||
if (native !== undefined) {
|
||||
if (Schema.is(OpenAIResponsesImageGenerationTool)(native)) return native
|
||||
@@ -169,7 +168,7 @@ const lowerTool = Effect.fn("OpenAIResponses.lowerTool")(function* (tool: ToolDe
|
||||
|
||||
// Native namespaces hold only function tools, so deeper levels flatten into
|
||||
// the leaf names the same way non-native protocols flatten the whole tree.
|
||||
const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (tool: ToolEntry) {
|
||||
const lowerToolEntry = Effect.fnUntraced(function* (tool: ToolEntry) {
|
||||
if (tool.type === "tool") return yield* lowerTool(tool)
|
||||
// OpenAI requires a namespace description; fall back to a generic one so a
|
||||
// missing description never blocks the request.
|
||||
@@ -238,10 +237,10 @@ const checkpointBody = {
|
||||
}),
|
||||
}
|
||||
|
||||
const hostedToolResult = Effect.fn("OpenAIResponses.hostedToolResult")(function* (item: ResponsesHostedTools.Item) {
|
||||
const hostedToolResult = Effect.fnUntraced(function* (item: ResponsesHostedTools.Item) {
|
||||
const isError = item.error !== undefined && item.error !== null
|
||||
if (item.type === "image_generation_call" && item.result) {
|
||||
yield* Effect.fromResult(Base64.decode(item.result)).pipe(
|
||||
yield* Effect.fromResult(Encoding.decodeBase64(item.result)).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.eventError(ADAPTER, "OpenAI Responses returned invalid image base64", undefined, cause),
|
||||
),
|
||||
|
||||
@@ -94,7 +94,7 @@ const fromRequest = Effect.fn("OpenAISpeech.fromRequest")(function* (request: Me
|
||||
|
||||
const isSse = (body: MediaProtocol.Body) => body.type === "json" && body.value.stream_format === "sse"
|
||||
|
||||
const onEvent = Effect.fn("OpenAISpeech.onEvent")(function* (state: State, frame: string) {
|
||||
const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const event = yield* decodeEvent(frame)
|
||||
if (event.type === "speech.audio.delta") return SpeechStream.delta(state, event.audio)
|
||||
const usage = event.usage
|
||||
|
||||
@@ -210,7 +210,7 @@ const segment = (value: Schema.Schema.Type<typeof Segment>): TranscriptionSegmen
|
||||
speaker: value.speaker,
|
||||
})
|
||||
|
||||
const onEvent = Effect.fn("OpenAITranscription.onEvent")(function* (state: State, frame: string) {
|
||||
const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
if (!EVENT_TYPES.has((yield* decodeEventType(frame)).type)) return [state, []] as const
|
||||
const event = yield* decodeEvent(frame)
|
||||
if (event.type === "error")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Tool } from "@opencode/schema/tool"
|
||||
import { Effect, Option, Schema } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/http"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import { Media } from "../media.js"
|
||||
import {
|
||||
InvalidProviderOutputError,
|
||||
@@ -154,7 +154,7 @@ export const wrapSystemUpdate = (parts: ReadonlyArray<{ readonly text: string }>
|
||||
* raw retrieved, tool, or web content into privileged updates: keep untrusted
|
||||
* data in ordinary user/tool messages instead.
|
||||
*/
|
||||
export const systemUpdateText = Effect.fn("ProviderShared.systemUpdateText")(function* (
|
||||
export const systemUpdateText = Effect.fnUntraced(function* (
|
||||
route: string,
|
||||
message: LLMRequest["messages"][number],
|
||||
) {
|
||||
@@ -167,7 +167,7 @@ export const systemUpdateText = Effect.fn("ProviderShared.systemUpdateText")(fun
|
||||
})
|
||||
|
||||
/** Lower an unsupported privileged update into visible, in-order user text. */
|
||||
export const wrappedSystemUpdate = Effect.fn("ProviderShared.wrappedSystemUpdate")(function* (
|
||||
export const wrappedSystemUpdate = Effect.fnUntraced(function* (
|
||||
route: string,
|
||||
message: LLMRequest["messages"][number],
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
@@ -82,7 +82,7 @@ const endpoint = (model: string) => (model.startsWith("sd3") ? "sd3" : model)
|
||||
|
||||
const RESERVED_FORM_FIELDS = new Set(["image", "prompt", "mode", "model"])
|
||||
|
||||
const form = Effect.fn("StabilityImages.form")(function* (
|
||||
const form = Effect.fnUntraced(function* (
|
||||
identity: MediaProtocol.Identity,
|
||||
fields: Record<string, unknown>,
|
||||
native: Record<string, unknown> | undefined,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AwsV4Signer } from "aws4fetch"
|
||||
import { Effect } from "effect"
|
||||
import { Headers } from "effect/http"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Auth, type AuthInput } from "../../route/auth.js"
|
||||
import { AIError, AuthenticationError } from "../../schema/index.js"
|
||||
import { ProviderShared } from "../shared.js"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Effect, Encoding, Schema } from "effect"
|
||||
import type { MediaPart } from "../../schema/index.js"
|
||||
import { ProviderShared } from "../shared.js"
|
||||
|
||||
@@ -77,14 +76,14 @@ function documentName(filename: string | undefined, names: Set<string>) {
|
||||
return name
|
||||
}
|
||||
|
||||
const mediaBase64 = Effect.fn("BedrockMedia.mediaBase64")(function* (part: MediaPart) {
|
||||
const mediaBase64 = Effect.fnUntraced(function* (part: MediaPart) {
|
||||
const media = yield* ProviderShared.requireInlineMedia("Bedrock Converse", part.media)
|
||||
const bytes = yield* Effect.fromResult(Base64.decode(media.base64)).pipe(
|
||||
const bytes = yield* Effect.fromResult(Encoding.decodeBase64(media.base64)).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.invalidRequest("Bedrock Converse media data must be valid base64", cause),
|
||||
),
|
||||
)
|
||||
return Base64.encode(bytes)
|
||||
return Encoding.encodeBase64(bytes)
|
||||
})
|
||||
|
||||
// Route by MIME. Known image/document formats lower into a typed block; anything
|
||||
@@ -92,7 +91,7 @@ const mediaBase64 = Effect.fn("BedrockMedia.mediaBase64")(function* (part: Media
|
||||
// document block. Image MIME types not in `IMAGE_FORMATS` (e.g. `image/svg+xml`)
|
||||
// get an image-specific error so the caller knows it's a format-support issue,
|
||||
// not a kind-detection issue.
|
||||
export const lower = Effect.fn("BedrockMedia.lower")(function* (part: MediaPart, documentNames: Set<string>) {
|
||||
export const lower = Effect.fnUntraced(function* (part: MediaPart, documentNames: Set<string>) {
|
||||
const mime = part.media.mediaType.toLowerCase()
|
||||
const imageFormat = IMAGE_FORMATS[mime as keyof typeof IMAGE_FORMATS]
|
||||
if (imageFormat) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { Status } from "../../generation.js"
|
||||
import type { Media } from "../../media.js"
|
||||
import { MediaProtocol } from "../../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Effect } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Effect, Encoding } from "effect"
|
||||
import { Media } from "../../media.js"
|
||||
import type { MediaProtocol } from "../../route/media-protocol.js"
|
||||
import { mergeJsonRecords, type AIError, type ProviderID } from "../../schema/index.js"
|
||||
@@ -11,7 +10,7 @@ export const inlineBytes = (route: string, asset: Media.Asset): Effect.Effect<Ui
|
||||
if (asset.source.type === "bytes") return Effect.succeed(asset.source.data)
|
||||
const inline = asset.inline()
|
||||
if (!inline) return Effect.fail(ProviderShared.inlineRequired(route, asset))
|
||||
return Effect.fromResult(Base64.decode(inline.base64)).pipe(
|
||||
return Effect.fromResult(Encoding.decodeBase64(inline.base64)).pipe(
|
||||
Effect.mapError((cause) => ProviderShared.invalidRequest(`${route} media contains invalid base64 data`, cause)),
|
||||
)
|
||||
}
|
||||
@@ -53,7 +52,7 @@ export const decodedAsset = (
|
||||
mediaType: string | undefined,
|
||||
options?: Media.AssetOptions,
|
||||
) =>
|
||||
Effect.fromResult(Base64.decode(data)).pipe(
|
||||
Effect.fromResult(Encoding.decodeBase64(data)).pipe(
|
||||
Effect.mapError((cause) => invalid(`${label} contains invalid base64 data`, cause)),
|
||||
Effect.map((bytes) => Media.bytes(bytes, mediaType, options)),
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ interface State {
|
||||
readonly responseID?: string
|
||||
}
|
||||
|
||||
const onOutputItem = Effect.fn("ResponsesCheckpoint.onOutputItem")(function* (
|
||||
const onOutputItem = Effect.fnUntraced(function* (
|
||||
state: State,
|
||||
input: OpenResponses.Event,
|
||||
) {
|
||||
@@ -63,7 +63,7 @@ export const make = <Body>(body: RouteBody<Body>): TriggerCompactOperation =>
|
||||
checkpoints: {},
|
||||
}),
|
||||
terminal: OpenResponses.terminal,
|
||||
step: Effect.fn("ResponsesCheckpoint.step")(function* (state: State, event: OpenResponses.Event) {
|
||||
step: Effect.fnUntraced(function* (state: State, event: OpenResponses.Event) {
|
||||
if (event.response?.id && state.responseID && event.response.id !== state.responseID)
|
||||
return yield* ProviderShared.eventError(source.id, "Compaction response ID changed during execution")
|
||||
if (event.type === "response.created") return [{ ...state, responseID: event.response?.id }, []] as const
|
||||
|
||||
@@ -33,7 +33,7 @@ export const onDone: (
|
||||
state: OpenResponses.ParserState,
|
||||
item: Item,
|
||||
tools: Definitions,
|
||||
) => Effect.Effect<OpenResponses.StepResult, AIError> = Effect.fn("ResponsesHostedTools.onDone")(
|
||||
) => Effect.Effect<OpenResponses.StepResult, AIError> = Effect.fnUntraced(
|
||||
function* (state, item, tools) {
|
||||
const tool = tools[item.type]
|
||||
if (!tool) return [state, []] satisfies OpenResponses.StepResult
|
||||
|
||||
@@ -60,14 +60,21 @@ const inputStart = (tool: PendingTool) =>
|
||||
providerMetadata: tool.providerMetadata,
|
||||
})
|
||||
|
||||
const inputDelta = (tool: PendingTool, text: string) =>
|
||||
LLMEvent.toolInputDelta({
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
namespace: tool.namespace,
|
||||
text,
|
||||
input: Option.getOrElse(parsePartialInput(tool.input), () => ({})),
|
||||
})
|
||||
const inputDelta = (tool: PendingTool, text: string): LLMEvent => {
|
||||
const raw = tool.input
|
||||
let parsed: unknown
|
||||
return {
|
||||
...LLMEvent.toolInputDelta({
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
namespace: tool.namespace,
|
||||
text,
|
||||
}),
|
||||
get input() {
|
||||
return (parsed ??= Option.getOrElse(parsePartialInput(raw), () => ({})))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const toolCall = (route: string, tool: PendingTool, inputOverride?: string) => {
|
||||
const raw = inputOverride ?? tool.input
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { AIError, LLMEvent, type LanguageModelCompatibility, type LLMRequest } from "../schema/index.js"
|
||||
import { classifyProviderFailure } from "../provider-error.js"
|
||||
import { OpenAIChat } from "./openai-chat.js"
|
||||
import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js"
|
||||
import { cacheControl } from "./utils/cache.js"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public options and request body
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type ReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | (string & {})
|
||||
|
||||
const Parameters = Schema.Struct({
|
||||
enableWebSearch: Schema.optional(Schema.String),
|
||||
enableWebScraping: Schema.optional(Schema.Boolean),
|
||||
enableWebCitations: Schema.optional(Schema.Boolean),
|
||||
enableXSearch: Schema.optional(Schema.Boolean),
|
||||
stripThinkingResponse: Schema.optional(Schema.Boolean),
|
||||
disableThinking: Schema.optional(Schema.Boolean),
|
||||
includeVeniceSystemPrompt: Schema.optional(Schema.Boolean),
|
||||
characterSlug: Schema.optional(Schema.String),
|
||||
includeSearchResultsInStream: Schema.optional(Schema.Boolean),
|
||||
returnSearchResultsAsDocuments: Schema.optional(Schema.Boolean),
|
||||
})
|
||||
|
||||
const Reasoning = Schema.Struct({
|
||||
effort: Schema.optional(Schema.String),
|
||||
enabled: Schema.optional(Schema.Boolean),
|
||||
summary: Schema.optional(Schema.String),
|
||||
})
|
||||
|
||||
export type OptionsInput = {
|
||||
readonly reasoningEffort?: ReasoningEffort
|
||||
readonly reasoning?: {
|
||||
readonly effort?: ReasoningEffort
|
||||
readonly enabled?: boolean
|
||||
readonly summary?: "auto" | "concise" | "detailed" | (string & {})
|
||||
}
|
||||
readonly veniceParameters?: Omit<typeof Parameters.Type, "enableWebSearch"> & {
|
||||
readonly enableWebSearch?: "off" | "on" | "auto" | (string & {})
|
||||
}
|
||||
readonly promptCacheKey?: string
|
||||
readonly promptCacheRetention?: "default" | "extended" | "24h" | (string & {})
|
||||
readonly parallelToolCalls?: boolean
|
||||
readonly maxCompletionTokens?: number
|
||||
readonly maxTokens?: number
|
||||
readonly minP?: number
|
||||
readonly repetitionPenalty?: number
|
||||
readonly stopTokenIds?: readonly number[]
|
||||
readonly logprobs?: boolean
|
||||
readonly topLogprobs?: number
|
||||
readonly maxTemp?: number
|
||||
readonly minTemp?: number
|
||||
readonly responseFormat?: Readonly<Record<string, unknown>>
|
||||
readonly user?: string
|
||||
}
|
||||
|
||||
const Options = Schema.Struct({
|
||||
reasoningEffort: Schema.optional(Schema.String),
|
||||
reasoning: Schema.optional(Reasoning),
|
||||
veniceParameters: Schema.optional(Parameters),
|
||||
promptCacheKey: Schema.optional(Schema.String),
|
||||
promptCacheRetention: Schema.optional(Schema.String),
|
||||
parallelToolCalls: Schema.optional(Schema.Boolean),
|
||||
maxCompletionTokens: Schema.optional(Schema.Number),
|
||||
maxTokens: Schema.optional(Schema.Number),
|
||||
minP: Schema.optional(Schema.Number),
|
||||
repetitionPenalty: Schema.optional(Schema.Number),
|
||||
stopTokenIds: Schema.optional(Schema.Array(Schema.Number)),
|
||||
logprobs: Schema.optional(Schema.Boolean),
|
||||
topLogprobs: Schema.optional(Schema.Number),
|
||||
maxTemp: Schema.optional(Schema.Number),
|
||||
minTemp: Schema.optional(Schema.Number),
|
||||
responseFormat: Schema.optional(JsonObject),
|
||||
user: Schema.optional(Schema.String),
|
||||
})
|
||||
|
||||
const ToolCall = Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatAssistantToolCall.fields,
|
||||
thought_signature: Schema.optional(Schema.String),
|
||||
})
|
||||
const Assistant = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatMessage.cases.assistant.schema.fields,
|
||||
tool_calls: optionalArray(ToolCall),
|
||||
thought_signature: Schema.optional(Schema.String),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
const Messages = Schema.Array(
|
||||
Schema.Union([
|
||||
OpenAIChat.OpenAIChatMessage.cases.system,
|
||||
OpenAIChat.OpenAIChatMessage.cases.user,
|
||||
Assistant,
|
||||
OpenAIChat.OpenAIChatMessage.cases.tool,
|
||||
]),
|
||||
)
|
||||
const Body = Schema.Struct({
|
||||
...OpenAIChat.bodyFields,
|
||||
messages: Messages,
|
||||
reasoning: Schema.optional(Reasoning),
|
||||
venice_parameters: Schema.Record(Schema.String, Schema.Union([Schema.String, Schema.Boolean])),
|
||||
prompt_cache_retention: Options.fields.promptCacheRetention,
|
||||
parallel_tool_calls: Options.fields.parallelToolCalls,
|
||||
min_p: Options.fields.minP,
|
||||
top_k: Schema.optional(Schema.Number),
|
||||
repetition_penalty: Options.fields.repetitionPenalty,
|
||||
stop_token_ids: Options.fields.stopTokenIds,
|
||||
logprobs: Options.fields.logprobs,
|
||||
top_logprobs: Options.fields.topLogprobs,
|
||||
max_temp: Options.fields.maxTemp,
|
||||
min_temp: Options.fields.minTemp,
|
||||
response_format: Options.fields.responseFormat,
|
||||
user: Options.fields.user,
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Streaming schemas and state
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const ToolDelta = Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatToolCallDelta.fields,
|
||||
thought_signature: optionalNull(Schema.String),
|
||||
})
|
||||
const Delta = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatDelta.schema.fields,
|
||||
tool_calls: optionalNull(Schema.Array(ToolDelta)),
|
||||
thought_signature: optionalNull(Schema.String),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
const Choice = Schema.StructWithRest(
|
||||
Schema.Struct({ ...OpenAIChat.OpenAIChatChoice.schema.fields, delta: optionalNull(Delta) }),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
const Usage = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatUsage.schema.fields,
|
||||
prompt_tokens_details: optionalNull(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
cached_tokens: optionalNull(Schema.Number),
|
||||
cache_write_tokens: optionalNull(Schema.Number),
|
||||
cache_creation_input_tokens: optionalNull(Schema.Number),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
),
|
||||
),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
const Event = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatEvent.schema.fields,
|
||||
choices: optionalNull(Schema.Array(Choice)),
|
||||
usage: optionalNull(Usage),
|
||||
error: optionalNull(Schema.Union([Schema.String, OpenAIChat.OpenAIChatEvent.schema.fields.error.schema])),
|
||||
issues: optionalArray(
|
||||
Schema.Struct({
|
||||
message: Schema.String,
|
||||
path: Schema.optional(Schema.Array(Schema.Union([Schema.String, Schema.Number]))),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
|
||||
interface State {
|
||||
readonly shared: OpenAIChat.ParserState
|
||||
readonly pending: string
|
||||
readonly reasoning: string
|
||||
readonly encrypted: boolean
|
||||
readonly signature?: string
|
||||
readonly tools: Readonly<Record<string, string>>
|
||||
}
|
||||
|
||||
const MARKER = "__ENCRYPTED_REASONING__"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Request lowering
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const fromRequest = Effect.fn("VeniceChat.fromRequest")(function* (request: LLMRequest) {
|
||||
const options = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Options))(request.providerOptions ?? {})
|
||||
const body = yield* OpenAIChat.fromRequest(request, {
|
||||
cacheControl: cacheControl(),
|
||||
assistant: (source, message) => {
|
||||
if (message.role !== "assistant") return message
|
||||
const parts = source.content.filter(
|
||||
(part) => part.type === "text" || part.type === "reasoning" || part.type === "tool-call",
|
||||
)
|
||||
const calls = source.content.filter((part) => part.type === "tool-call")
|
||||
const signature = parts
|
||||
.map((part) => part.providerMetadata?.venice?.messageThoughtSignature)
|
||||
.find((value) => typeof value === "string")
|
||||
const raw = parts
|
||||
.map((part) => part.providerMetadata?.venice?.encryptedReasoningContent)
|
||||
.find((value) => typeof value === "string")
|
||||
return {
|
||||
...message,
|
||||
...(signature === undefined ? {} : { thought_signature: signature }),
|
||||
...(raw === undefined ? {} : { reasoning_content: raw }),
|
||||
tool_calls: message.tool_calls?.map((call, index) => {
|
||||
const signature = calls[index]?.providerMetadata?.venice?.thoughtSignature
|
||||
return { ...call, ...(typeof signature === "string" ? { thought_signature: signature } : {}) }
|
||||
}),
|
||||
}
|
||||
},
|
||||
})
|
||||
return {
|
||||
...body,
|
||||
max_completion_tokens: options.maxCompletionTokens ?? options.maxTokens ?? request.generation?.maxTokens,
|
||||
reasoning_effort: undefined,
|
||||
reasoning:
|
||||
options.reasoningEffort === undefined
|
||||
? options.reasoning
|
||||
: { ...options.reasoning, effort: options.reasoningEffort },
|
||||
// Match the previous Venice SDK default, not the gateway's added prompt.
|
||||
venice_parameters: Object.fromEntries(
|
||||
Object.entries({
|
||||
...options.veniceParameters,
|
||||
includeVeniceSystemPrompt: options.veniceParameters?.includeVeniceSystemPrompt ?? false,
|
||||
})
|
||||
.filter(([, value]) => value !== undefined)
|
||||
.map(([key, value]) => [key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`), value]),
|
||||
),
|
||||
prompt_cache_retention: options.promptCacheRetention,
|
||||
parallel_tool_calls: options.parallelToolCalls,
|
||||
min_p: options.minP,
|
||||
top_k: request.generation?.topK,
|
||||
repetition_penalty: options.repetitionPenalty,
|
||||
stop_token_ids: options.stopTokenIds,
|
||||
logprobs: options.logprobs,
|
||||
top_logprobs: options.topLogprobs,
|
||||
max_temp: options.maxTemp,
|
||||
min_temp: options.minTemp,
|
||||
response_format: options.responseFormat,
|
||||
user: options.user,
|
||||
}
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Venice normalization around the shared Chat state machine
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const step = Effect.fn("VeniceChat.step")(function* (state: State, event: typeof Event.Type) {
|
||||
if (typeof event.error === "string")
|
||||
return yield* new AIError({
|
||||
reason: classifyProviderFailure({
|
||||
message: [
|
||||
event.error,
|
||||
...(event.issues ?? []).map(
|
||||
(issue) => `${issue.path?.length ? `${issue.path.join(".")}: ` : ""}${issue.message}`,
|
||||
),
|
||||
].join("; "),
|
||||
rawBody: ProviderShared.encodeJson(event),
|
||||
}),
|
||||
})
|
||||
const delta = event.choices?.[0]?.delta
|
||||
const scalar = delta?.reasoning_content ?? ""
|
||||
const text = state.pending + scalar
|
||||
const marker = text.indexOf(MARKER)
|
||||
const pending =
|
||||
marker >= 0 || state.encrypted
|
||||
? 0
|
||||
: (Array.from({ length: Math.min(text.length, MARKER.length - 1) }, (_, index) => index + 1)
|
||||
.filter((length) => text.endsWith(MARKER.slice(0, length)))
|
||||
.at(-1) ?? 0)
|
||||
const visible = state.encrypted ? "" : marker >= 0 ? text.slice(0, marker) : text.slice(0, text.length - pending)
|
||||
const result = yield* OpenAIChat.protocol.stream.step(state.shared, {
|
||||
...event,
|
||||
error: event.error,
|
||||
usage: event.usage
|
||||
? {
|
||||
...event.usage,
|
||||
prompt_tokens_details: event.usage.prompt_tokens_details
|
||||
? {
|
||||
...event.usage.prompt_tokens_details,
|
||||
cache_write_tokens:
|
||||
event.usage.prompt_tokens_details.cache_write_tokens ??
|
||||
event.usage.prompt_tokens_details.cache_creation_input_tokens,
|
||||
}
|
||||
: event.usage.prompt_tokens_details,
|
||||
}
|
||||
: event.usage,
|
||||
choices: event.choices?.map((choice, index) =>
|
||||
index === 0 && choice.delta
|
||||
? {
|
||||
...choice,
|
||||
delta: {
|
||||
...choice.delta,
|
||||
reasoning_content: visible || undefined,
|
||||
// Opaque-only scalar reasoning still needs a canonical part for replay.
|
||||
reasoning_details: choice.delta.reasoning_details ?? (marker >= 0 ? [] : undefined),
|
||||
},
|
||||
}
|
||||
: choice,
|
||||
),
|
||||
})
|
||||
const tools = { ...state.tools }
|
||||
for (const call of delta?.tool_calls ?? []) {
|
||||
if (!call.thought_signature) continue
|
||||
const index = call.index ?? result[0].latestToolIndex
|
||||
const id =
|
||||
call.id ?? (index === undefined ? undefined : (result[0].tools[index]?.id ?? result[0].pendingTools[index]?.id))
|
||||
if (id) tools[id] = call.thought_signature
|
||||
}
|
||||
return [
|
||||
{
|
||||
shared: result[0],
|
||||
pending: pending ? text.slice(-pending) : "",
|
||||
reasoning: state.reasoning + scalar,
|
||||
encrypted: state.encrypted || marker >= 0,
|
||||
signature: delta?.thought_signature ?? state.signature,
|
||||
tools,
|
||||
},
|
||||
result[1],
|
||||
] as const
|
||||
})
|
||||
|
||||
const onHalt = Effect.fn("VeniceChat.onHalt")(function* (state: State) {
|
||||
const events = yield* OpenAIChat.finishEvents(state.shared)
|
||||
return events.flatMap((event): LLMEvent[] => {
|
||||
if (
|
||||
event.type !== "reasoning-end" &&
|
||||
event.type !== "text-end" &&
|
||||
event.type !== "tool-call" &&
|
||||
event.type !== "tool-input-end"
|
||||
)
|
||||
return [event]
|
||||
const signature = event.type === "tool-call" || event.type === "tool-input-end" ? state.tools[event.id] : undefined
|
||||
const providerMetadata = {
|
||||
...event.providerMetadata,
|
||||
venice: {
|
||||
...event.providerMetadata?.venice,
|
||||
...(state.signature ? { messageThoughtSignature: state.signature } : {}),
|
||||
...(signature ? { thoughtSignature: signature } : {}),
|
||||
...(event.type === "reasoning-end" && state.encrypted ? { encryptedReasoningContent: state.reasoning } : {}),
|
||||
},
|
||||
}
|
||||
if (event.type === "reasoning-end" && state.pending)
|
||||
return [LLMEvent.reasoningDelta({ id: event.id, text: state.pending }), { ...event, providerMetadata }]
|
||||
return [{ ...event, providerMetadata }]
|
||||
})
|
||||
})
|
||||
|
||||
export const compatibility = {
|
||||
maxTokensField: "max_completion_tokens",
|
||||
supportsStore: false,
|
||||
supportsPromptCacheKey: true,
|
||||
} satisfies LanguageModelCompatibility
|
||||
|
||||
export const protocol = Protocol.make({
|
||||
id: "venice-chat",
|
||||
body: { schema: Body, from: fromRequest },
|
||||
stream: {
|
||||
event: Schema.Union([Schema.Literal("[DONE]"), Protocol.jsonEvent(Event)]),
|
||||
initial: (request): State => ({
|
||||
shared: OpenAIChat.protocol.stream.initial(request),
|
||||
pending: "",
|
||||
reasoning: "",
|
||||
encrypted: false,
|
||||
tools: {},
|
||||
}),
|
||||
step: (state: State, event) => (event === "[DONE]" ? Effect.succeed([state, []] as const) : step(state, event)),
|
||||
terminal: (event) => event === "[DONE]",
|
||||
onHalt,
|
||||
},
|
||||
})
|
||||
|
||||
export * as VeniceChat from "./venice-chat.js"
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
import { Route, type RouteDefaultsInput } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import type { ProviderPackage } from "../provider-package.js"
|
||||
import { AnthropicMessages } from "../protocols/anthropic-messages.js"
|
||||
import { OpenAIChat } from "../protocols/openai-chat.js"
|
||||
import { OpenResponses } from "../protocols/open-responses.js"
|
||||
import { BedrockAuth, type Credentials } from "../protocols/utils/bedrock-auth.js"
|
||||
import { claudeVersion } from "../protocols/utils/claude-model.js"
|
||||
import { ProviderConfigurationError, ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options.js"
|
||||
|
||||
export const id = ProviderID.make("amazon-bedrock")
|
||||
|
||||
export type Config = RouteDefaultsInput & {
|
||||
export type OpenAIOptionsInput = OpenAIProviderOptionsInput
|
||||
export type MessagesOptionsInput = AnthropicMessages.ProviderOptionsInput
|
||||
|
||||
export type Config = Omit<RouteDefaultsInput, "providerOptions"> & {
|
||||
/** Bedrock API key. Falls back to `AWS_BEARER_TOKEN_BEDROCK`; bearer auth takes precedence over SigV4. */
|
||||
readonly apiKey?: string
|
||||
/** `sigv4` ignores `apiKey` fallbacks from the environment; `bearer` requires a token. */
|
||||
@@ -20,11 +25,11 @@ export type Config = RouteDefaultsInput & {
|
||||
/** Shared config profile for the default credential chain. */
|
||||
readonly profile?: string
|
||||
readonly region?: string
|
||||
readonly providerOptions?: OpenAIProviderOptionsInput
|
||||
readonly providerOptions?: OpenAIProviderOptionsInput | AnthropicMessages.ProviderOptionsInput
|
||||
}
|
||||
|
||||
export type Settings = ProviderPackage.Settings &
|
||||
OpenAIProviderOptionsInput & {
|
||||
export type Settings<Options = OpenAIProviderOptionsInput> = ProviderPackage.Settings &
|
||||
Options & {
|
||||
readonly apiKey?: string
|
||||
readonly auth?: "bearer" | "sigv4"
|
||||
readonly baseURL?: string
|
||||
@@ -34,6 +39,8 @@ export type Settings = ProviderPackage.Settings &
|
||||
readonly topP?: number
|
||||
}
|
||||
|
||||
export type MessagesSettings = Settings<AnthropicMessages.ProviderOptionsInput>
|
||||
|
||||
const responsesRoute = Route.make({
|
||||
id: "bedrock-mantle-responses",
|
||||
provider: id,
|
||||
@@ -50,12 +57,35 @@ const chatRoute = OpenAIChat.route.with({
|
||||
providerMetadataKey: "mantle",
|
||||
})
|
||||
|
||||
export const routes = [responsesRoute, chatRoute]
|
||||
const messagesRoute = Route.make({
|
||||
id: "bedrock-mantle-messages",
|
||||
provider: id,
|
||||
providerMetadataKey: "mantle",
|
||||
protocol: {
|
||||
...AnthropicMessages.protocol,
|
||||
// Mantle rejects mid-conversation `output_config` on Opus 5.0; support starts at 5.1+.
|
||||
supportsEffortUpdates: (request) => {
|
||||
const override = request.model.compatibility?.supportsEffortUpdates
|
||||
if (override !== undefined) return override
|
||||
const version = claudeVersion(request.model.id)
|
||||
return version !== undefined && (version.major > 5 || (version.major === 5 && version.minor >= 1))
|
||||
},
|
||||
},
|
||||
endpoint: Endpoint.path(AnthropicMessages.PATH),
|
||||
transport: AnthropicMessages.transport<AnthropicMessages.AnthropicMessagesBody>(),
|
||||
headers: () => ({ "anthropic-version": "2023-06-01" }),
|
||||
})
|
||||
|
||||
const configuredRoute = <Body, Prepared>(route: Route<Body, Prepared>, input: Config) => {
|
||||
export const routes = [responsesRoute, chatRoute, messagesRoute]
|
||||
|
||||
const configuredRoute = <Body, Prepared>(
|
||||
route: Route<Body, Prepared>,
|
||||
input: Config,
|
||||
defaultBaseURL = (region: string) => `https://bedrock-mantle.${region}.api.aws/v1`,
|
||||
) => {
|
||||
const region = BedrockAuth.resolveRegion(input)
|
||||
return route.with({
|
||||
endpoint: { baseURL: input.baseURL ?? `https://bedrock-mantle.${region}.api.aws/v1` },
|
||||
endpoint: { baseURL: input.baseURL ?? defaultBaseURL(region) },
|
||||
auth: BedrockAuth.resolveAuth(input, region, {
|
||||
service: "bedrock-mantle",
|
||||
name: "Bedrock Mantle",
|
||||
@@ -87,6 +117,11 @@ export const configure = (input: Config = {}) => {
|
||||
})
|
||||
const configuredResponsesRoute = configuredRoute(responsesRoute, input)
|
||||
const configuredChatRoute = configuredRoute(chatRoute, input)
|
||||
const configuredMessagesRoute = configuredRoute(
|
||||
messagesRoute,
|
||||
input,
|
||||
(region) => `https://bedrock-mantle.${region}.api.aws/anthropic/v1`,
|
||||
)
|
||||
const modelDefaults = defaults(input)
|
||||
const responses = (modelID: string | ModelID) =>
|
||||
configuredResponsesRoute
|
||||
@@ -96,11 +131,14 @@ export const configure = (input: Config = {}) => {
|
||||
configuredChatRoute
|
||||
.with(withOpenAIOptions(modelID, modelDefaults))
|
||||
.model<OpenAIProviderOptionsInput>({ id: modelID })
|
||||
const messages = (modelID: string | ModelID) =>
|
||||
configuredMessagesRoute.with(modelDefaults).model<AnthropicMessages.ProviderOptionsInput>({ id: modelID })
|
||||
|
||||
return {
|
||||
id,
|
||||
model: responses,
|
||||
chat,
|
||||
messages,
|
||||
responses,
|
||||
configure,
|
||||
}
|
||||
@@ -119,7 +157,7 @@ const fromSettings = ({
|
||||
region,
|
||||
topP,
|
||||
...providerOptions
|
||||
}: Settings) =>
|
||||
}: Settings<Config["providerOptions"]>) =>
|
||||
configure({
|
||||
apiKey,
|
||||
auth,
|
||||
@@ -137,6 +175,10 @@ export const chatModel: ProviderPackage.Definition<Settings, OpenAIProviderOptio
|
||||
modelID,
|
||||
settings,
|
||||
) => fromSettings(settings).chat(modelID)
|
||||
export const messagesModel: ProviderPackage.Definition<
|
||||
MessagesSettings,
|
||||
AnthropicMessages.ProviderOptionsInput
|
||||
>["model"] = (modelID, settings) => fromSettings(settings).messages(modelID)
|
||||
export const responsesModel: ProviderPackage.Definition<Settings, OpenAIProviderOptionsInput>["model"] = (
|
||||
modelID,
|
||||
settings,
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export { messagesModel as model } from "../../amazon-bedrock-mantle.js"
|
||||
export type { MessagesSettings as Settings } from "../../amazon-bedrock-mantle.js"
|
||||
@@ -54,6 +54,7 @@ const route = Route.make({
|
||||
),
|
||||
},
|
||||
stream: AnthropicMessages.protocol.stream,
|
||||
supportsEffortUpdates: AnthropicMessages.protocol.supportsEffortUpdates,
|
||||
}),
|
||||
endpoint: Endpoint.path(({ request }) => `/${request.model.id}:streamRawPredict`),
|
||||
auth: Auth.none,
|
||||
|
||||
@@ -40,6 +40,7 @@ export * as Stability from "./stability.js"
|
||||
export * as TogetherAI from "./togetherai.js"
|
||||
export * as TypeSafeAI from "./typesafe-ai.js"
|
||||
export * as VercelAIGateway from "./vercel-ai-gateway.js"
|
||||
export * as Venice from "./venice.js"
|
||||
export * as XAI from "./xai.js"
|
||||
export * as ZAI from "./zai.js"
|
||||
export * as ZAICodingPlan from "./zai-coding-plan.js"
|
||||
@@ -50,7 +50,7 @@ export const gpt5DefaultOptions = (modelID: string): ProviderOptions | undefined
|
||||
export const openAIDefaultOptions = (modelID: string): ProviderOptions | undefined =>
|
||||
mergeProviderOptions(openAIProviderOptions({ store: false }), gpt5DefaultOptions(modelID))
|
||||
|
||||
export const withOpenAIOptions = <Options extends { readonly providerOptions?: OpenAIProviderOptionsInput }>(
|
||||
export const withOpenAIOptions = <Options extends { readonly providerOptions?: ProviderOptions }>(
|
||||
modelID: string,
|
||||
options: Options,
|
||||
): Omit<Options, "providerOptions"> & { readonly providerOptions?: ProviderOptions } => {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import type { ProviderPackage } from "../provider-package.js"
|
||||
import { VeniceChat } from "../protocols/venice-chat.js"
|
||||
import { OpenAIChat } from "../protocols/openai-chat.js"
|
||||
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
|
||||
import { Route, type RouteDefaultsInput } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { ProviderID, type ModelID } from "../schema/index.js"
|
||||
|
||||
export const id = ProviderID.make("venice")
|
||||
export type ChatOptionsInput = VeniceChat.OptionsInput
|
||||
export type Config = Omit<RouteDefaultsInput, "providerOptions"> &
|
||||
ProviderAuthOption<"optional"> & {
|
||||
readonly baseURL?: string
|
||||
readonly queryParams?: Readonly<Record<string, string>>
|
||||
readonly providerOptions?: ChatOptionsInput
|
||||
}
|
||||
export type Settings = ProviderPackage.Settings &
|
||||
ChatOptionsInput & {
|
||||
readonly apiKey?: string
|
||||
readonly baseURL?: string
|
||||
readonly queryParams?: Readonly<Record<string, string>>
|
||||
}
|
||||
|
||||
const route = Route.make({
|
||||
id: "venice-chat",
|
||||
provider: id,
|
||||
providerMetadataKey: "venice",
|
||||
protocol: VeniceChat.protocol,
|
||||
endpoint: Endpoint.path("/chat/completions", { baseURL: "https://api.venice.ai/api/v1" }),
|
||||
framing: OpenAIChat.framing,
|
||||
})
|
||||
export const routes = [route]
|
||||
|
||||
export const configure = (input: Config = {}) => {
|
||||
const { apiKey: _apiKey, auth: _auth, baseURL, queryParams, ...rest } = input
|
||||
const chat = (modelID: string | ModelID) =>
|
||||
route
|
||||
.with({
|
||||
...rest,
|
||||
endpoint: { baseURL: baseURL ?? route.endpoint.baseURL, query: queryParams },
|
||||
auth: AuthOptions.bearer(input, "VENICE_API_KEY"),
|
||||
})
|
||||
.model<ChatOptionsInput>({ id: modelID, compatibility: VeniceChat.compatibility })
|
||||
return { id, model: chat, chat, configure }
|
||||
}
|
||||
|
||||
export const provider = configure()
|
||||
export const chat = provider.chat
|
||||
export const model: ProviderPackage.Definition<Settings, ChatOptionsInput>["model"] = (
|
||||
modelID,
|
||||
{ apiKey, baseURL, queryParams, body, headers, ...providerOptions },
|
||||
) =>
|
||||
configure({
|
||||
apiKey,
|
||||
baseURL,
|
||||
queryParams,
|
||||
headers,
|
||||
http: body === undefined ? undefined : { body: { ...body } },
|
||||
providerOptions,
|
||||
}).model(modelID)
|
||||
|
||||
export * as Venice from "./venice.js"
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/http"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import {
|
||||
EvaluationAnswer,
|
||||
EvaluationInput,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Config, Effect, Option, Redacted } from "effect"
|
||||
import { Headers } from "effect/http"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { AuthenticationError, AIError, type HttpOptions } from "../schema/index.js"
|
||||
|
||||
export class MissingCredentialError extends Error {
|
||||
@@ -95,7 +95,7 @@ export const optional = (secret: Secret | undefined, source = "optional value")
|
||||
export const config = (name: string) =>
|
||||
credential(
|
||||
Effect.gen(function* () {
|
||||
const secret = yield* Config.option(Config.Redacted(name))
|
||||
const secret = yield* Config.option(Config.redacted(name))
|
||||
if (Option.isSome(secret) && Redacted.value(secret.value) !== "") return secret.value
|
||||
return yield* Effect.fail(new MissingCredentialError(name, `${name} is not set`))
|
||||
}),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Context, type Effect } from "effect"
|
||||
import type { HttpClientRequest, HttpClientResponse } from "effect/http"
|
||||
import type { HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
|
||||
import type { AIError } from "../schema/errors.js"
|
||||
|
||||
// The service tag lives in its own leaf module so `Media.Asset` (imported by the schema layer) can require the
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
HttpClientError,
|
||||
HttpClientRequest,
|
||||
HttpClientResponse,
|
||||
} from "effect/http"
|
||||
} from "effect/unstable/http"
|
||||
import { HttpContext, HttpRateLimitDetails, AIError, TransportError } from "../schema/index.js"
|
||||
import { classifyProviderFailure, providerErrorMessage } from "../provider-error.js"
|
||||
import { Service, type HttpMiddleware, type Interface } from "./executor-service.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Stream } from "effect"
|
||||
import { makeParser, type Event } from "effect/encoding/Sse"
|
||||
import { makeParser } from "effect/unstable/encoding/Sse"
|
||||
import { AIError, InvalidProviderOutputError } from "../schema/index.js"
|
||||
|
||||
/**
|
||||
@@ -42,43 +42,39 @@ export const sseFraming = (
|
||||
Stream.decodeText(),
|
||||
Stream.mapAccumEffect(
|
||||
() => {
|
||||
const output: Event[] = []
|
||||
const output: string[] = []
|
||||
return {
|
||||
output,
|
||||
parser: makeParser((event) => {
|
||||
if (event._tag === "Event") output.push(event)
|
||||
if (
|
||||
event._tag === "Event" &&
|
||||
(events === undefined || events.has(event.event)) &&
|
||||
event.data.length > 0 &&
|
||||
// Some OpenAI-compatible proxies serialize an empty flush as a bare
|
||||
// `data: null`, between events or after `[DONE]`. No protocol has a
|
||||
// null event, so it carries nothing and must not abort the stream.
|
||||
event.data !== "null" &&
|
||||
// Vertex AI partner models (e.g. `xai/grok-4.6`) send their SSE
|
||||
// keepalive comment as `data: : keepalive` while reasoning.
|
||||
event.data !== ": keepalive" &&
|
||||
(event.data !== "[DONE]" || includeDone || (events !== undefined && event.event !== "message"))
|
||||
)
|
||||
output.push(event.data)
|
||||
}),
|
||||
}
|
||||
},
|
||||
(state, chunk) =>
|
||||
Effect.gen(function* () {
|
||||
const error = state.parser.feed(chunk)
|
||||
if (error)
|
||||
return yield* new AIError({
|
||||
reason: new InvalidProviderOutputError({
|
||||
route: "sse",
|
||||
message: error.message,
|
||||
body: chunk,
|
||||
cause: error,
|
||||
}),
|
||||
})
|
||||
return [state, state.output.splice(0)] as const
|
||||
}),
|
||||
(state, chunk) => {
|
||||
const error = state.parser.feed(chunk)
|
||||
if (!error) return Effect.succeed([state, state.output.splice(0)] as const)
|
||||
const reason = new InvalidProviderOutputError({
|
||||
route: "sse",
|
||||
message: error.message,
|
||||
body: chunk,
|
||||
cause: error,
|
||||
})
|
||||
return Effect.fail(new AIError({ reason }))
|
||||
},
|
||||
),
|
||||
Stream.filter(
|
||||
(event) =>
|
||||
(events === undefined || events.has(event.event)) &&
|
||||
event.data.length > 0 &&
|
||||
// Some OpenAI-compatible proxies serialize an empty flush as a bare
|
||||
// `data: null`, between events or after `[DONE]`. No protocol has a
|
||||
// null event, so it carries nothing and must not abort the stream.
|
||||
event.data !== "null" &&
|
||||
// Vertex AI partner models (e.g. `xai/grok-4.6`) send their SSE
|
||||
// keepalive comment as `data: : keepalive` while reasoning.
|
||||
event.data !== ": keepalive" &&
|
||||
(event.data !== "[DONE]" || includeDone || (events !== undefined && event.event !== "message")),
|
||||
),
|
||||
Stream.map((event) => event.data),
|
||||
)
|
||||
|
||||
/** Server-Sent Events framing. Used by every JSON-streaming HTTP provider. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Clock, Duration, Effect, Schema, type Stream } from "effect"
|
||||
import { HttpClientResponse } from "effect/http"
|
||||
import { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { Snapshot, Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import type { AuthInput } from "./auth.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schedule, Schema, Stream } from "effect"
|
||||
import { Headers, HttpClientRequest, type HttpClientResponse } from "effect/http"
|
||||
import { Headers, HttpClientRequest, type HttpClientResponse } from "effect/unstable/http"
|
||||
import { Auth, type AuthInput } from "./auth.js"
|
||||
import { Endpoint } from "./endpoint.js"
|
||||
import { RequestExecutorService, type Interface } from "./executor-service.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Clock, Duration, Effect, Stream } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/http"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import { Auth } from "../auth.js"
|
||||
import { render as renderEndpoint } from "../endpoint.js"
|
||||
import { Framing } from "../framing.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Effect, Scope, Stream } from "effect"
|
||||
import type { Headers } from "effect/http"
|
||||
import type { Headers } from "effect/unstable/http"
|
||||
import type { AIError, HttpContext } from "../../schema/index.js"
|
||||
|
||||
export interface WebSocketChannelExecutor {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Cause, Effect, Queue, Stream } from "effect"
|
||||
import { Headers } from "effect/http"
|
||||
import { Socket } from "effect/socket"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Socket } from "effect/unstable/socket"
|
||||
import {
|
||||
AIError,
|
||||
AIErrorReason,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Schema } from "effect"
|
||||
import { withStatics } from "@opencode/schema/schema"
|
||||
import { Tool } from "@opencode/schema/tool"
|
||||
import {
|
||||
CacheHint,
|
||||
@@ -29,7 +28,7 @@ export type SystemPart = Schema.Schema.Type<typeof systemPartSchema>
|
||||
|
||||
const makeSystemPart = (text: string): SystemPart => ({ type: "text", text })
|
||||
|
||||
export const SystemPart = withStatics(systemPartSchema, {
|
||||
export const SystemPart = Object.assign(systemPartSchema, {
|
||||
make: makeSystemPart,
|
||||
content: (input?: string | SystemPart | ReadonlyArray<SystemPart>) => {
|
||||
if (input === undefined) return []
|
||||
@@ -77,7 +76,7 @@ const toolResultValueSchema = Schema.Union([
|
||||
export type ToolResultValue = Schema.Schema.Type<typeof toolResultValueSchema>
|
||||
const isToolResultValue = Schema.is(toolResultValueSchema)
|
||||
|
||||
export const ToolResultValue = withStatics(toolResultValueSchema, {
|
||||
export const ToolResultValue = Object.assign(toolResultValueSchema, {
|
||||
is: isToolResultValue,
|
||||
make: (value: unknown, type: ToolResultValue["type"] = "json"): ToolResultValue => {
|
||||
if (isToolResultValue(value)) return value
|
||||
@@ -91,7 +90,7 @@ export interface ToolOutput {
|
||||
readonly content: ReadonlyArray<Tool.Content>
|
||||
}
|
||||
|
||||
export const ToolOutput = withStatics(
|
||||
export const ToolOutput = Object.assign(
|
||||
Schema.Struct({
|
||||
structured: Schema.Unknown,
|
||||
content: Schema.Array(Tool.Content),
|
||||
@@ -128,7 +127,7 @@ const toolResultText = (value: unknown) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const ToolCallPart = withStatics(
|
||||
export const ToolCallPart = Object.assign(
|
||||
Schema.Struct({
|
||||
type: Schema.Literal("tool-call"),
|
||||
id: Schema.String,
|
||||
@@ -146,7 +145,7 @@ export const ToolCallPart = withStatics(
|
||||
)
|
||||
export type ToolCallPart = Schema.Schema.Type<typeof ToolCallPart>
|
||||
|
||||
export const ToolResultPart = withStatics(
|
||||
export const ToolResultPart = Object.assign(
|
||||
Schema.Struct({
|
||||
type: Schema.Literal("tool-result"),
|
||||
id: Schema.String,
|
||||
@@ -210,7 +209,7 @@ const compactionPartSchema = Schema.Struct({
|
||||
)
|
||||
.annotate({ identifier: "LLM.Content.Compaction" })
|
||||
export type CompactionPart = typeof compactionPartSchema.Type
|
||||
export const CompactionPart = withStatics(compactionPartSchema, {
|
||||
export const CompactionPart = Object.assign(compactionPartSchema, {
|
||||
make: (input: Omit<CompactionPart, "type" | "encrypted" | "text"> & CompactionContent): CompactionPart =>
|
||||
Schema.decodeUnknownSync(compactionPartSchema)({ type: "compaction", ...input }),
|
||||
})
|
||||
@@ -327,7 +326,7 @@ export type ToolNamespaceEntryInput = ToolNamespaceInput & { readonly type: "nam
|
||||
|
||||
export const ToolNamespace: Schema.Codec<ToolNamespace> & {
|
||||
readonly make: (input: ToolNamespace | ToolNamespaceInput) => ToolNamespace
|
||||
} = withStatics(
|
||||
} = Object.assign(
|
||||
Schema.Struct({
|
||||
type: Schema.Literal("namespace"),
|
||||
name: Schema.String,
|
||||
@@ -347,7 +346,7 @@ export type ToolEntry = ToolDefinition | ToolNamespace
|
||||
export type ToolEntryInput = ToolDefinition.Input | ToolNamespaceEntryInput
|
||||
export const ToolEntry: Schema.Codec<ToolEntry> & {
|
||||
readonly make: (input: ToolEntryInput) => ToolEntry
|
||||
} = withStatics(
|
||||
} = Object.assign(
|
||||
Schema.Union([ToolDefinition, ToolNamespace]).pipe(
|
||||
Schema.toTaggedUnion("type"),
|
||||
Schema.annotate({ identifier: "LLM.ToolEntry" }),
|
||||
|
||||
+3
-32
@@ -1,4 +1,4 @@
|
||||
import { Effect, JsonSchema, Schema, SchemaAST } from "effect"
|
||||
import { Effect, JsonSchema, Schema } from "effect"
|
||||
import { Tool } from "@opencode/schema/tool"
|
||||
import type {
|
||||
ToolCallPart,
|
||||
@@ -6,7 +6,6 @@ import type {
|
||||
ToolOutput as ToolOutputType,
|
||||
} from "./schema/index.js"
|
||||
import { ToolDefinition, ToolFailure, ToolOutput } from "./schema/index.js"
|
||||
import { isRecord } from "./utils/record.js"
|
||||
|
||||
/**
|
||||
* Schema constraint for tool parameters / success values: no decoding or
|
||||
@@ -201,7 +200,7 @@ export function make(config: TypedToolConfig | DynamicToolConfig): AnyTool {
|
||||
_definition: new ToolDefinition({
|
||||
name: "",
|
||||
description: config.description,
|
||||
inputSchema: emptyInputJsonSchema(config.parameters) ?? toJsonSchema(config.parameters),
|
||||
inputSchema: toJsonSchema(config.parameters),
|
||||
outputSchema: toJsonSchema(config.success),
|
||||
}),
|
||||
}
|
||||
@@ -231,36 +230,8 @@ export const toDefinitions = (tools: Tools): ReadonlyArray<ToolDefinitionClass>
|
||||
}),
|
||||
)
|
||||
|
||||
/**
|
||||
* Describes a no-argument Effect tool input as an empty object, or returns
|
||||
* `undefined` when the input takes arguments.
|
||||
*
|
||||
* Effect emits `{ not: { type: "null" } }` for `Struct({})`, but providers
|
||||
* require tool parameters to describe an object. Emptiness is decided by the
|
||||
* encoded side, which is what the model sends, so a transformation from an
|
||||
* empty struct qualifies while one into an empty struct does not. The schema is
|
||||
* inlined rather than a root `$ref`, and the title, description, and other
|
||||
* metadata Effect emits are retained. Checked encoded structs are left as
|
||||
* Effect emits them, because their constraints or JSON Schema overrides could
|
||||
* contradict the closed object shape.
|
||||
*/
|
||||
export const emptyInputJsonSchema = (schema: Schema.Top): JsonSchema.JsonSchema | undefined => {
|
||||
const encoded = SchemaAST.toEncoded(schema.ast)
|
||||
if (
|
||||
!SchemaAST.isObjects(encoded) ||
|
||||
encoded.propertySignatures.length > 0 ||
|
||||
encoded.indexSignatures.length > 0 ||
|
||||
encoded.checks !== undefined
|
||||
)
|
||||
return undefined
|
||||
const { not, ...metadata } = Schema.toJsonSchemaDocument(schema, { referencePolicy: () => undefined }).schema
|
||||
// Rewrite only the shape Effect is known to emit for an empty struct.
|
||||
if (!isRecord(not) || not.type !== "null" || Object.keys(not).length !== 1) return undefined
|
||||
return { ...metadata, type: "object", properties: {}, additionalProperties: false }
|
||||
}
|
||||
|
||||
const toJsonSchema = (schema: Schema.Top): JsonSchema.JsonSchema => {
|
||||
const document = Schema.toJsonSchemaDocument(schema, { onExcessProperty: "error" })
|
||||
const document = Schema.toJsonSchemaDocument(schema)
|
||||
if (Object.keys(document.definitions).length === 0) return document.schema
|
||||
return { ...document.schema, $defs: document.definitions }
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ type LanguageModel = {
|
||||
declare const auth: Auth.Definition
|
||||
declare const optionalAuthModel: LanguageModelFactory<BaseOptions, "optional", LanguageModel>
|
||||
declare const requiredAuthModel: LanguageModelFactory<BaseOptions, "required", LanguageModel>
|
||||
const configApiKey = Config.Redacted("OPENAI_API_KEY")
|
||||
const configApiKey = Config.redacted("OPENAI_API_KEY")
|
||||
|
||||
OpenAIChat.route.model({ id: "gpt-4.1-mini" })
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { ConfigProvider, Effect } from "effect"
|
||||
import { Headers } from "effect/http"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { LLM } from "../src/index.js"
|
||||
import { Auth } from "../src/route/auth.js"
|
||||
import * as OpenAIChat from "../src/protocols/openai-chat.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { FetchHttpClient } from "effect/http"
|
||||
import { FetchHttpClient } from "effect/unstable/http"
|
||||
import { LLM, LLMRequest, Message } from "../src/index.js"
|
||||
import { LLMClient } from "../src/route/client.js"
|
||||
import { OpenAI } from "../src/providers.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Effect, Ref, Schema } from "effect"
|
||||
import { HttpClientRequest, HttpClientResponse } from "effect/http"
|
||||
import { HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
|
||||
import {
|
||||
LLM,
|
||||
LLMRequest,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { compileRequest } from "../src/route/client.js"
|
||||
import { AnthropicMessages } from "../src/protocols/anthropic-messages.js"
|
||||
import { OpenAIResponses } from "../src/protocols/openai-responses.js"
|
||||
import { Gemini } from "../src/protocols/gemini.js"
|
||||
import { GoogleVertexMessages, OpenAI } from "../src/providers.js"
|
||||
import { AmazonBedrockMantle, GoogleVertexMessages, OpenAI } from "../src/providers.js"
|
||||
import { applyEffortUpdates } from "../src/effort-updates.js"
|
||||
import { it, testEffect } from "./lib/effect.js"
|
||||
import { dynamicResponse } from "./lib/http.js"
|
||||
@@ -171,6 +171,33 @@ describe("Anthropic Messages effort updates", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("releases a held system update next to an effort marker as one valid section", () =>
|
||||
Effect.gen(function* () {
|
||||
const prepared = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: opus5,
|
||||
messages: [
|
||||
Message.user("Fix it."),
|
||||
Message.assistant("Done."),
|
||||
lowFromHigh,
|
||||
Message.system("Update."),
|
||||
Message.user("Next."),
|
||||
],
|
||||
providerOptions: { effort: "low" },
|
||||
cache: "none",
|
||||
}),
|
||||
)
|
||||
|
||||
expect(prepared.body.messages).toEqual([
|
||||
{ role: "user", content: [{ type: "text", text: "Fix it." }] },
|
||||
{ role: "assistant", content: [{ type: "text", text: "Done." }] },
|
||||
{ role: "system", content: [], output_config: { effort: "low" } },
|
||||
{ role: "user", content: [{ type: "text", text: "Next." }] },
|
||||
{ role: "system", content: [{ type: "text", text: "Update.", cache_control: undefined }] },
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("falls back to a plain top-level effort when history drifted from the current effort", () =>
|
||||
Effect.gen(function* () {
|
||||
const drifted = yield* compileRequest(
|
||||
@@ -241,20 +268,53 @@ describe("Anthropic Messages effort updates", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("strips markers on the Vertex Anthropic route, whose protocol wrapper does not forward support", () =>
|
||||
it.effect("strips markers for Opus 5.0 on Bedrock Mantle Messages while lowering Opus 5.5", () =>
|
||||
Effect.gen(function* () {
|
||||
const prepared = yield* compileRequest(
|
||||
const mantle = AmazonBedrockMantle.configure({ apiKey: "test", region: "us-east-1" })
|
||||
const opus50 = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: GoogleVertexMessages.configure({ accessToken: "test", location: "global", project: "test" }).model(
|
||||
"claude-opus-5",
|
||||
),
|
||||
model: mantle.messages("anthropic.claude-opus-5"),
|
||||
messages: conversation,
|
||||
providerOptions: { effort: "low" },
|
||||
}),
|
||||
)
|
||||
const opus55 = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: mantle.messages("anthropic.claude-opus-5-5"),
|
||||
messages: conversation,
|
||||
providerOptions: { effort: "low" },
|
||||
}),
|
||||
)
|
||||
|
||||
expect(systemMessages(prepared.body)).toHaveLength(0)
|
||||
expect(prepared.body.output_config).toEqual({ effort: "low" })
|
||||
expect(systemMessages(opus50.body)).toHaveLength(0)
|
||||
expect(opus50.body.output_config).toEqual({ effort: "low" })
|
||||
expect(systemMessages(opus55.body)).toEqual([{ role: "system", content: [], output_config: { effort: "low" } }])
|
||||
expect(opus55.body.output_config).toEqual({ effort: "high" })
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("lowers markers on the Vertex Anthropic route for models that support them", () =>
|
||||
Effect.gen(function* () {
|
||||
const vertex = GoogleVertexMessages.configure({ accessToken: "test", location: "global", project: "test" })
|
||||
const opus5 = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: vertex.model("claude-opus-5"),
|
||||
messages: conversation,
|
||||
providerOptions: { effort: "low" },
|
||||
}),
|
||||
)
|
||||
const opus48 = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: vertex.model("claude-opus-4-8"),
|
||||
messages: conversation,
|
||||
providerOptions: { effort: "low" },
|
||||
}),
|
||||
)
|
||||
|
||||
expect(systemMessages(opus5.body)).toEqual([{ role: "system", content: [], output_config: { effort: "low" } }])
|
||||
expect(opus5.body.output_config).toEqual({ effort: "high" })
|
||||
expect(systemMessages(opus48.body)).toHaveLength(0)
|
||||
expect(opus48.body.output_config).toEqual({ effort: "low" })
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { Evaluation, EvaluationClient } from "../src/experimental.js"
|
||||
import { OpenCodeZen, OpenRouter, TypeSafeAI, VercelAIGateway } from "../src/providers.js"
|
||||
import { it } from "./lib/effect.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Deferred, Effect, Fiber, Layer, Ref, Stream } from "effect"
|
||||
import { Headers, HttpClientError, HttpClientRequest, HttpClientResponse } from "effect/http"
|
||||
import { Headers, HttpClientError, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
|
||||
import { LLM, AIError, HttpContext, InvalidProviderOutputError, TransportError, isRetryable } from "../src/index.js"
|
||||
import {
|
||||
LLMClient,
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"model": "anthropic.claude-opus-5-5",
|
||||
"tags": [
|
||||
"prefix:bedrock-mantle-messages",
|
||||
"provider:amazon-bedrock",
|
||||
"protocol:anthropic-messages",
|
||||
"reasoning",
|
||||
"effort-update"
|
||||
],
|
||||
"name": "bedrock-mantle-messages/applies-mid-conversation-effort-updates-and-thinking-block-binding-on-opus-5-5",
|
||||
"recordedAt": "2026-10-04T03:56:23.139Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://bedrock-mantle.us-east-1.api.aws/anthropic/v1/messages",
|
||||
"headers": {
|
||||
"anthropic-beta": "interleaved-thinking-2025-05-14,thinking-binding-controls-2026-08-01",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"anthropic.claude-opus-5-5\",\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"Compute 37 * 43 step by step, then reply with only the integer.\",\"cache_control\":{\"type\":\"ephemeral\"}}]}],\"stream\":true,\"max_tokens\":2048,\"thinking\":{\"type\":\"adaptive\",\"display\":\"summarized\",\"block_binding\":{\"prefix_mismatch_behavior\":\"drop_block\"}},\"output_config\":{\"effort\":\"high\"}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-opus-5-5\",\"id\":\"msg_bdrk_y7h2x5bz6w6ggmekuxekbi6rseptglsljkwgj36phisnsnu3syea\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"container\":null,\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":31,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":2,\"service_tier\":\"standard\"},\"input_transformations\":[]}}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"They\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" want\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" only\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" the final\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" integer, so\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" I just\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" need\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" to compute 37\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"×43 \"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"using the dif\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"ference of squares: 40\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"²−3²\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" = 1600−9 =\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" 1591.\\n\\n\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"CAQSogUKEggSEAEYAjgBQgh0aGlua2luZxIM48GlQ7IvNDW3jk2BGgw0Aq5cIs+m8gjYEIQiMFOyG984KYDLRzchzn2ApX6Rs3r7+CtXL0KeCRsXr1XKY3Y0UNK73Qrjyk94TGFPTSq9BCCZALbMiaeiIDqgB3H8jfrU26rP6kORoTJuF84ByBhXGI9AGo30c3RU2ZueXE/oLvRkK12g8r3TPql2fam1gcC/SeZ627fqGykV6G8WrPH7kthjbR45vnRuaqgFZmyA4C/XCxEH0zSSlVAhXf3Um9sjO/RD8lMJttQCAJSurbB5wmKbUQmZeOjIn8augHV/KmsGcFaHBjGLNfnwfEUwLEbRjNh5eIsmcs9dFfIeYHYNRgtLnBkERACoKPQLp2xU090/wCwrFHIGgLYbklR5wUhGqrAERhOAybqMxlNN3dwd7dV5Tbd16xEghDWb6wUtoxnNQdsUsV/0F/b8Ov9TSu93db/QJAkR74OBMtPuEu914SxtC4NBtqX5YZQAo//O4piaQGzFRVE7TahKzMS5bD111w/qz/cLpqEI/bZMqsXKdzBuMMOAox9TvgTumemdiiPu8tn2ONQeAnuNLjArrr7Jz1mbE9GqPl6aJW9HYWPb0BxCQ/hRXFz5d0v+okmmn5KCV2nD55wk2ySWz9OxIMQUsJ6uEUVOZPk7O0ZJ2ppoLAx6GYq2f55nNcUCsbKB4gB4+QlNp3Tf5IemDdZaY/tGW71dgpYI7iWYYEhqNtlC8pXpoEIbO31IvAHS9BGeQRYQQh1h0muEz4S1+YICPTdXnUmjc0uJ9MGBIKOuBsUhg+E4dzZzOfwS4KteNmJgjhj53WVdjJgRslemZle0tZphrTLLgvZpLZDVIYmOkIpbo2tf5Cflx/rf/NPg7RgB\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"1591\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null,\"container\":null},\"usage\":{\"input_tokens\":31,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":86,\"output_tokens_details\":{\"thinking_tokens\":82}}}\n\nevent: message_stop\ndata: {\"type\":\"message_stop\"}\n\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://bedrock-mantle.us-east-1.api.aws/anthropic/v1/messages",
|
||||
"headers": {
|
||||
"anthropic-beta": "interleaved-thinking-2025-05-14,mid-conversation-output-config-2026-07-01,thinking-binding-controls-2026-08-01",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"anthropic.claude-opus-5-5\",\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"Compute 37 * 43 step by step, then reply with only the integer.\"}]},{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"They want only the final integer, so I just need to compute 37×43 using the difference of squares: 40²−3² = 1600−9 = 1591.\\n\\n\",\"signature\":\"CAQSogUKEggSEAEYAjgBQgh0aGlua2luZxIM48GlQ7IvNDW3jk2BGgw0Aq5cIs+m8gjYEIQiMFOyG984KYDLRzchzn2ApX6Rs3r7+CtXL0KeCRsXr1XKY3Y0UNK73Qrjyk94TGFPTSq9BCCZALbMiaeiIDqgB3H8jfrU26rP6kORoTJuF84ByBhXGI9AGo30c3RU2ZueXE/oLvRkK12g8r3TPql2fam1gcC/SeZ627fqGykV6G8WrPH7kthjbR45vnRuaqgFZmyA4C/XCxEH0zSSlVAhXf3Um9sjO/RD8lMJttQCAJSurbB5wmKbUQmZeOjIn8augHV/KmsGcFaHBjGLNfnwfEUwLEbRjNh5eIsmcs9dFfIeYHYNRgtLnBkERACoKPQLp2xU090/wCwrFHIGgLYbklR5wUhGqrAERhOAybqMxlNN3dwd7dV5Tbd16xEghDWb6wUtoxnNQdsUsV/0F/b8Ov9TSu93db/QJAkR74OBMtPuEu914SxtC4NBtqX5YZQAo//O4piaQGzFRVE7TahKzMS5bD111w/qz/cLpqEI/bZMqsXKdzBuMMOAox9TvgTumemdiiPu8tn2ONQeAnuNLjArrr7Jz1mbE9GqPl6aJW9HYWPb0BxCQ/hRXFz5d0v+okmmn5KCV2nD55wk2ySWz9OxIMQUsJ6uEUVOZPk7O0ZJ2ppoLAx6GYq2f55nNcUCsbKB4gB4+QlNp3Tf5IemDdZaY/tGW71dgpYI7iWYYEhqNtlC8pXpoEIbO31IvAHS9BGeQRYQQh1h0muEz4S1+YICPTdXnUmjc0uJ9MGBIKOuBsUhg+E4dzZzOfwS4KteNmJgjhj53WVdjJgRslemZle0tZphrTLLgvZpLZDVIYmOkIpbo2tf5Cflx/rf/NPg7RgB\"},{\"type\":\"text\",\"text\":\"1591\"}]},{\"role\":\"system\",\"content\":[],\"output_config\":{\"effort\":\"low\"}},{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"Add 9 to that result. Reply with only the integer.\",\"cache_control\":{\"type\":\"ephemeral\"}}]}],\"stream\":true,\"max_tokens\":2048,\"thinking\":{\"type\":\"adaptive\",\"display\":\"summarized\",\"block_binding\":{\"prefix_mismatch_behavior\":\"drop_block\"}},\"output_config\":{\"effort\":\"high\"}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-opus-5-5\",\"id\":\"msg_bdrk_yzpmbqh3aag3i7kymdm7ctqputcpeuln3cy44msgbdnctkcweena\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"container\":null,\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":139,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":4,\"service_tier\":\"standard\"},\"input_transformations\":[]}}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"1600\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null,\"container\":null},\"usage\":{\"input_tokens\":139,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":4,\"output_tokens_details\":{\"thinking_tokens\":0}}}\n\nevent: message_stop\ndata: {\"type\":\"message_stop\"}\n\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"model": "anthropic.claude-haiku-4-5",
|
||||
"tags": [
|
||||
"prefix:bedrock-mantle-messages",
|
||||
"provider:amazon-bedrock",
|
||||
"protocol:anthropic-messages",
|
||||
"reasoning",
|
||||
"system-update"
|
||||
],
|
||||
"name": "bedrock-mantle-messages/lowers-system-updates-to-wrapped-user-text-on-haiku-4-5-with-budget-thinking",
|
||||
"recordedAt": "2026-10-04T03:56:18.874Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://bedrock-mantle.us-east-1.api.aws/anthropic/v1/messages",
|
||||
"headers": {
|
||||
"anthropic-beta": "interleaved-thinking-2025-05-14",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"anthropic.claude-haiku-4-5\",\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"What is 19 multiplied by 23?\"},{\"type\":\"text\",\"text\":\"<system-update>\\nReply with only the integer.\\n</system-update>\",\"cache_control\":{\"type\":\"ephemeral\"}}]}],\"stream\":true,\"max_tokens\":2048,\"thinking\":{\"type\":\"enabled\",\"budget_tokens\":1024}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-haiku-4-5-20251001\",\"id\":\"msg_bdrk_prlwlyj7mdyfbm6ejq74ibwylnwd6deibs6j5xjq6lsc4dzuyzqa\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"container\":null,\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":65,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\"}}}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"19\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" × 23 = ?\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n\\nLet me calculate\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" this:\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n19 × 23 =\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" 19 × (20 +\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" 3)\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n= 19 × 20\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" + 19 × 3\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n= 380 + 57\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n= 437\\n\\nOr\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" alternatively\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\":\\n19 × 23 \"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"= (\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"20 - 1) × \"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"23\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n= 20 × 23 \"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"- 23\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n= 460 - 23\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n= 437\\n\\nSo\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" the\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" answer is 437.\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"ErEDCoQBCBIQARgCKkBdVqTX3D5rRVz4O3SlBHJaAUb4Jv4CxOT9igcrHKXsDtU6Wwh9dw7QJbtvpCA0UJh0Wi0PCzu1Tlp8W8jmIU9wMhljbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxOABCCHRoaW5raW5nWgwyMzI3NzE4NTY3ODGoAeKch9YGEgyP1xZ80Q63y4Uko9EaDHZo9a+qBGcqeBRLcSIw5/J5NpbvXm6aIqCN58pfjKvW9/35kh6B+t2jS/7dssFzks6J4m+5jtG7BRf9x65GKtkBOhxxxMXrJDYW8RJkXU9iKampxOVFPJuSrvSw43H1MF4V/dt2RFIXeKMNmIJ4umr4nTNVtSlaIEUt+uYmT/F0QL4wXB1Pd40e4VMcBqkJ3CmHkspPJgkyLursJIpDVJQ4TMCHDBzvEObimdAgoAzHM8ahMVOzb9nW9C7ZGE7OFinrq/uR+AzXR0N4zyBIenjcDF76n+OFm3ap3S7ngBQl6+2enaRiseO/UZ4UzgrYYkxk/V4oobGytu64Dn+ngeceb7P+uszDG8BsDs3zXWQdi2w56OvD6HGFVhgB\"}}\n\nevent: content_block_stop\ndata: {Line truncated
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"model": "anthropic.claude-opus-4-8",
|
||||
"tags": [
|
||||
"prefix:bedrock-mantle-messages",
|
||||
"provider:amazon-bedrock",
|
||||
"protocol:anthropic-messages",
|
||||
"tool",
|
||||
"tool-loop",
|
||||
"reasoning",
|
||||
"system-update"
|
||||
],
|
||||
"name": "bedrock-mantle-messages/replays-signed-thinking-through-a-tool-loop-and-native-system-update",
|
||||
"recordedAt": "2026-10-04T04:05:26.433Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://bedrock-mantle.us-east-1.api.aws/anthropic/v1/messages",
|
||||
"headers": {
|
||||
"anthropic-beta": "interleaved-thinking-2025-05-14",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"anthropic.claude-opus-4-8\",\"system\":[{\"type\":\"text\",\"text\":\"You are a concise assistant.\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"First calculate 37 * 43. Then call get_weather for Paris. After receiving the tool result, state both the product and the weather.\",\"cache_control\":{\"type\":\"ephemeral\"}}]}],\"tools\":[{\"name\":\"get_weather\",\"description\":\"Get the current weather in a city\",\"input_schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\",\"enum\":[\"Paris\"]}},\"required\":[\"city\"],\"additionalProperties\":false},\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true,\"max_tokens\":2048,\"thinking\":{\"type\":\"adaptive\",\"display\":\"summarized\"},\"output_config\":{\"effort\":\"medium\"}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-opus-4-8\",\"id\":\"msg_bdrk_fycfxoffsnlt6mj5wu2urbd2psp276vwn4pddgbaazfim6fxcvhq\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"container\":null,\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":439,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":2,\"service_tier\":\"standard\"}}}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"37\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" times\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" 43\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" is 1591\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\", that\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" one\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"'s\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" quick to do\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" my\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"self. Now I'll go\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" ahead and call get\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"_weather.\\n\\n\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EqoDCngIEhABGAIqQIGpXRhzl8JEPJWxprG5sxaT1WjZ8/kEJgxZTN2qtzM5uC63GiumUjsHzfEIJikrldkFbwPbc0enJCXIoLr0G5UyDWNsYXVkZS1xdWluY2U4AEIIdGhpbmtpbmdaDDIzMjc3MTg1Njc4MagBhaGH1gYSDI7iCpVUnPgOaCirJBoMR20SZNRICFBH7f84IjDDaA7qNPHUlJN+eQa/aYqKn6Z2LobkjfWtscoBJs9sjR8qTy477EOozPy6lTkt1Pwq3wFcgWmJHdh5a0V2iRnSN4CtMEwxVPqC2im7vDCJDpNeAld8VmAO0u594guMJca+jme4lM/MW5oy3WrkmcL6Uc+qRByhUXhSqTWra8w9Xxf5S2nbPcT+FXjx1z1oDR1I8SIMzZrUM1DGOtQp7L/oWPadGwJYZ9EqKf9beRmSoc23kJKF5eA6+ZE9+HbS5gG1XxMDRFvx5rETS+mYMamOsfdowxWGWP7TzqHMhv+VGSCXoy2IXEIPBkXwen0K+dSAtgy/t21chzEmsGlBdBrAn7Ab0rCSqHvbZNZuA2T8CFPtGAE=\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"37 × 43 \"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"= 1591.\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_bdrk_011We3Z1qCBXge7JLoyNwDat\",\"name\":\"get_weather\",\"input\":{}}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"city\\\": \\\"Pa\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"ris\\\"}\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null,\"container\":null},\"usage\":{\"input_tokens\":439,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":135,\"output_tokens_details\":{\"thinking_tokens\":73}}}\n\nevent: message_stop\ndata: {\"type\":\"message_stop\"}\n\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://bedrock-mantle.us-east-1.api.aws/anthropic/v1/messages",
|
||||
"headers": {
|
||||
"anthropic-beta": "interleaved-thinking-2025-05-14",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"anthropic.claude-opus-4-8\",\"system\":[{\"type\":\"text\",\"text\":\"You are a concise assistant.\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"First calculate 37 * 43. Then call get_weather for Paris. After receiving the tool result, state both the product and the weather.\"}]},{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"37 times 43 is 1591, that one's quick to do myself. Now I'll go ahead and call get_weather.\\n\\n\",\"signature\":\"EqoDCngIEhABGAIqQIGpXRhzl8JEPJWxprG5sxaT1WjZ8/kEJgxZTN2qtzM5uC63GiumUjsHzfEIJikrldkFbwPbc0enJCXIoLr0G5UyDWNsYXVkZS1xdWluY2U4AEIIdGhpbmtpbmdaDDIzMjc3MTg1Njc4MagBhaGH1gYSDI7iCpVUnPgOaCirJBoMR20SZNRICFBH7f84IjDDaA7qNPHUlJN+eQa/aYqKn6Z2LobkjfWtscoBJs9sjR8qTy477EOozPy6lTkt1Pwq3wFcgWmJHdh5a0V2iRnSN4CtMEwxVPqC2im7vDCJDpNeAld8VmAO0u594guMJca+jme4lM/MW5oy3WrkmcL6Uc+qRByhUXhSqTWra8w9Xxf5S2nbPcT+FXjx1z1oDR1I8SIMzZrUM1DGOtQp7L/oWPadGwJYZ9EqKf9beRmSoc23kJKF5eA6+ZE9+HbS5gG1XxMDRFvx5rETS+mYMamOsfdowxWGWP7TzqHMhv+VGSCXoy2IXEIPBkXwen0K+dSAtgy/t21chzEmsGlBdBrAn7Ab0rCSqHvbZNZuA2T8CFPtGAE=\"},{\"type\":\"text\",\"text\":\"37 × 43 = 1591.\"},{\"type\":\"tool_use\",\"id\":\"toolu_bdrk_011We3Z1qCBXge7JLoyNwDat\",\"name\":\"get_weather\",\"input\":{\"city\":\"Paris\"}}]},{\"role\":\"user\",\"content\":[{\"type\":\"tool_result\",\"tool_use_id\":\"toolu_bdrk_011We3Z1qCBXge7JLoyNwDat\",\"content\":\"{\\\"condition\\\":\\\"sunny\\\",\\\"temperatureC\\\":18}\"}]},{\"role\":\"system\",\"content\":[{\"type\":\"text\",\"text\":\"Reply in French in one short sentence.\",\"cache_control\":{\"type\":\"ephemeral\"}}]}],\"tools\":[{\"name\":\"get_weather\",\"description\":\"Get the current weather in a city\",\"input_schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\",\"enum\":[\"Paris\"]}},\"required\":[\"city\"],\"additionalProperties\":false},\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true,\"max_tokens\":2048,\"thinking\":{\"type\":\"adaptive\",\"display\":\"summarized\"},\"output_config\":{\"effort\":\"medium\"}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-opus-4-8\",\"id\":\"msg_bdrk_uak5dibczxblk4xunblaiowmid7zhky7ozwinjhpjtcbtgzvuwyq\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"container\":null,\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":611,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":3,\"service_tier\":\"standard\"}}}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"Le produ\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"it est \"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"1591 \"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"et il\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\" f\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"ait beau à Paris av\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"ec 18°C.\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null,\"container\":null},\"usage\":{\"input_tokens\":611,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":28,\"output_tokens_details\":{\"thinking_tokens\":0}}}\n\nevent: message_stop\ndata: {\"type\":\"message_stop\"}\n\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"model": "anthropic.claude-opus-5",
|
||||
"tags": [
|
||||
"prefix:bedrock-mantle-messages",
|
||||
"provider:amazon-bedrock",
|
||||
"protocol:anthropic-messages",
|
||||
"reasoning",
|
||||
"effort-update"
|
||||
],
|
||||
"name": "bedrock-mantle-messages/strips-unsupported-mid-conversation-effort-updates-on-opus-5-0",
|
||||
"recordedAt": "2026-10-04T03:56:23.956Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://bedrock-mantle.us-east-1.api.aws/anthropic/v1/messages",
|
||||
"headers": {
|
||||
"anthropic-beta": "interleaved-thinking-2025-05-14",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"anthropic.claude-opus-5\",\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"What is 12 + 30?\"}]},{\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"42\"}]},{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"Add 8 to that result. Reply with only the integer.\",\"cache_control\":{\"type\":\"ephemeral\"}}]}],\"stream\":true,\"max_tokens\":1024,\"thinking\":{\"type\":\"adaptive\",\"display\":\"summarized\"},\"output_config\":{\"effort\":\"low\"}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-opus-5\",\"id\":\"msg_bdrk_5mwa5agz3cvj44w72lno46ljoylvzjhipc4jmraridpzxktjquha\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"container\":null,\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":38,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\"}}}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"50\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null,\"container\":null},\"usage\":{\"input_tokens\":38,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":3,\"output_tokens_details\":{\"thinking_tokens\":0}}}\n\nevent: message_stop\ndata: {\"type\":\"message_stop\"}\n\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"model": "claude-opus-4-8",
|
||||
"tags": [
|
||||
"prefix:venice-chat",
|
||||
"provider:venice",
|
||||
"protocol:venice-chat",
|
||||
"reasoning",
|
||||
"tool",
|
||||
"tool-loop",
|
||||
"continuation",
|
||||
"usage",
|
||||
"signed"
|
||||
],
|
||||
"name": "venice-chat/claude-opus-4-8-preserves-reasoning-through-a-tool-loop-and-follow-up",
|
||||
"recordedAt": "2026-10-05T03:00:37.127Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"claude-opus-4-8\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169233,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\"},\"finish_reason\":null}]}\n\n: processing\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"I need to find the rate for\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\"I need to find the rate for\"}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" ZEBRA.\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\" ZEBRA.\"}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"\\n\\n\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\"\\n\\n\"}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\"\",\"signature\":\"EsECCrwBCBIYAipASM082xA/ckQU1q1MLSuAGRD/F94kvqoBlyXoEKdxvH2f2kn+ESR0AZfmYtv8VB8ux7LQ+qq4DnODYQ2iBHemajIPY2xhdWRlLW9wdXMtNC04OABCCHRoaW5raW5nWiQ1YzJjNzI5YS0wMzVjLTQ5ZDYtODNiOC03NGNhZTAyMzU2NWRyEOtICOPsjcfgmcoVEjPetDWIAQGaAREKD2NsYXVkZS1vcHVzLTQtOKgB0qWM1gawAQISDFJE1AThUPJ/0OxIBxoMak46jCiQRsOzj1nIIjBV1UQ4WoUBtZX8F6kyFtKyRPkLdWp7WQKQYd+f4VT3GvmEqenUY2ANNJImtDj/BQAqMhz7JVFNqrlemYzJNRbF6ntHDPc2enCrd/tYXBG6nms1qbcfKWc7CYc2ZGogOqiItKNDGAE=\",\"id\":\"toolu_01KYDseHbTDZXSYg9bNwiwxU\"}],\"tool_calls\":[{\"index\":0,\"id\":\"toolu_01KYDseHbTDZXSYg9bNwiwxU\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"\"}}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"code\\\"\"}}]},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\": \\\"ZEBR\"}}]},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"A\\\"}\"}}]},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"tool_calls\"}]}\n\ndata: {\"id\":\"msg_011CfiLtM3Rj4dVUWFJAEjoy\",\"object\":\"chat.completion.chunk\",\"created\":1791169234,\"model\":\"claude-opus-4-8\",\"choices\":[],\"usage\":{\"prompt_tokens\":499,\"completion_tokens\":74,\"total_tokens\":573,\"prompt_tokens_details\":{\"cached_tokens\":0}},\"cost\":{\"usd\":0.005214,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"claude-opus-4-8\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"toolu_01KYDseHbTDZXSYg9bNwiwxU\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}],\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"I need to find the rate for ZEBRA.\\n\\n\",\"id\":\"toolu_01KYDseHbTDZXSYg9bNwiwxU\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"signature\":\"EsECCrwBCBIYAipASM082xA/ckQU1q1MLSuAGRD/F94kvqoBlyXoEKdxvH2f2kn+ESR0AZfmYtv8VB8ux7LQ+qq4DnODYQ2iBHemajIPY2xhdWRlLW9wdXMtNC04OABCCHRoaW5raW5nWiQ1YzJjNzI5YS0wMzVjLTQ5ZDYtODNiOC03NGNhZTAyMzU2NWRyEOtICOPsjcfgmcoVEjPetDWIAQGaAREKD2NsYXVkZS1vcHVzLTQtOKgB0qWM1gawAQISDFJE1AThUPJ/0OxIBxoMak46jCiQRsOzj1nIIjBV1UQ4WoUBtZX8F6kyFtKyRPkLdWp7WQKQYd+f4VT3GvmEqenUY2ANNJImtDj/BQAqMhz7JVFNqrlemYzJNRbF6ntHDPc2enCrd/tYXBG6nms1qbcfKWc7CYc2ZGogOqiItKNDGAE=\"}],\"reasoning_content\":\"I need to find the rate for ZEBRA.\\n\\n\"},{\"role\":\"tool\",\"tool_call_id\":\"toolu_01KYDseHbTDZXSYg9bNwiwxU\",\"content\":\"{\\\"code\\\":\\\"ZEBRA\\\",\\\"rate\\\":23}\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"tool_choice\":\"none\",\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169235,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\"},\"finish_reason\":null}]}\n\n: processing\n\ndata: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169236,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"23 times 17 is \",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\"23 times 17 is \"}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169236,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"391, plus 9 g\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\"391, plus 9 g\"}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169236,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"ives 400.\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\"ives 400.\"}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169236,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"\\n\\n\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\"\\n\\n\"}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169236,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"text\":\"\",\"signature\":\"ErgCCrwBCBIYAipAzm6Uz1fiUimJZ7ry16/5jOPhPfQ9Zm3zSb449atO4+Dv3KroxOwD17dLjPUhdRWeFNghT/lQsCRlsY9T6SWyMzIPY2xhdWRlLW9wdXMtNC04OABCCHRoaW5raW5nWiQ1YzJjNzI5YS0wMzVjLTQ5ZDYtODNiOC03NGNhZTAyMzU2NWRyEGhpfnmythMRLK5wcAMHasmIAQGaAREKD2NsYXVkZS1vcHVzLTQtOKgB1KWM1gawAQISDA4K+cR55K4LQVXyhhoMBUHsSBuaNQlHp5ZPIjBvSX58DhVBxFRl9sVZYgZwrMDqGzC1/tgyH1wflAP4TkHTPje+Gdbv0yUxBBIQtaEqKSS4Bh4olHSAKxLEG1SyH4Iy46lp50SxdXxGJ/PIwTfHI47SEaE9pEfNGAE=\"}],\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169236,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"400\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169236,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}]}\n\ndata: {\"id\":\"msg_011CfiLtUi3ffKFSXdhWtFbp\",\"object\":\"chat.completion.chunk\",\"created\":1791169236,\"model\":\"claude-opus-4-8\",\"choices\":[],\"usage\":{\"prompt_tokens\":183,\"completion_tokens\":23,\"total_tokens\":206,\"prompt_tokens_details\":{\"cached_tokens\":0}},\"cost\":{\"usd\":0.001788,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"claude-opus-4-8\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"toolu_01KYDseHbTDZXSYg9bNwiwxU\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}],\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"I need to find the rate for ZEBRA.\\n\\n\",\"id\":\"toolu_01KYDseHbTDZXSYg9bNwiwxU\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"signature\":\"EsECCrwBCBIYAipASM082xA/ckQU1q1MLSuAGRD/F94kvqoBlyXoEKdxvH2f2kn+ESR0AZfmYtv8VB8ux7LQ+qq4DnODYQ2iBHemajIPY2xhdWRlLW9wdXMtNC04OABCCHRoaW5raW5nWiQ1YzJjNzI5YS0wMzVjLTQ5ZDYtODNiOC03NGNhZTAyMzU2NWRyEOtICOPsjcfgmcoVEjPetDWIAQGaAREKD2NsYXVkZS1vcHVzLTQtOKgB0qWM1gawAQISDFJE1AThUPJ/0OxIBxoMak46jCiQRsOzj1nIIjBV1UQ4WoUBtZX8F6kyFtKyRPkLdWp7WQKQYd+f4VT3GvmEqenUY2ANNJImtDj/BQAqMhz7JVFNqrlemYzJNRbF6ntHDPc2enCrd/tYXBG6nms1qbcfKWc7CYc2ZGogOqiItKNDGAE=\"}],\"reasoning_content\":\"I need to find the rate for ZEBRA.\\n\\n\"},{\"role\":\"tool\",\"tool_call_id\":\"toolu_01KYDseHbTDZXSYg9bNwiwxU\",\"content\":\"{\\\"code\\\":\\\"ZEBRA\\\",\\\"rate\\\":23}\"},{\"role\":\"assistant\",\"content\":\"400\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"23 times 17 is 391, plus 9 gives 400.\\n\\n\",\"format\":\"anthropic-claude-v1\",\"index\":0,\"signature\":\"ErgCCrwBCBIYAipAzm6Uz1fiUimJZ7ry16/5jOPhPfQ9Zm3zSb449atO4+Dv3KroxOwD17dLjPUhdRWeFNghT/lQsCRlsY9T6SWyMzIPY2xhdWRlLW9wdXMtNC04OABCCHRoaW5raW5nWiQ1YzJjNzI5YS0wMzVjLTQ5ZDYtODNiOC03NGNhZTAyMzU2NWRyEGhpfnmythMRLK5wcAMHasmIAQGaAREKD2NsYXVkZS1vcHVzLTQtOKgB1KWM1gawAQISDA4K+cR55K4LQVXyhhoMBUHsSBuaNQlHp5ZPIjBvSX58DhVBxFRl9sVZYgZwrMDqGzC1/tgyH1wflAP4TkHTPje+Gdbv0yUxBBIQtaEqKSS4Bh4olHSAKxLEG1SyH4Iy46lp50SxdXxGJ/PIwTfHI47SEaE9pEfNGAE=\"}],\"reasoning_content\":\"23 times 17 is 391, plus 9 gives 400.\\n\\n\"},{\"role\":\"user\",\"content\":\"Add 7 to your previous final answer. Reply with just the number.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"tool_choice\":\"none\",\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"msg_011CfiLtbruiyeuxJmswkPPt\",\"object\":\"chat.completion.chunk\",\"created\":1791169237,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\"},\"finish_reason\":null}]}\n\n: processing\n\ndata: {\"id\":\"msg_011CfiLtbruiyeuxJmswkPPt\",\"object\":\"chat.completion.chunk\",\"created\":1791169237,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"407\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"msg_011CfiLtbruiyeuxJmswkPPt\",\"object\":\"chat.completion.chunk\",\"created\":1791169237,\"model\":\"claude-opus-4-8\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}]}\n\ndata: {\"id\":\"msg_011CfiLtbruiyeuxJmswkPPt\",\"object\":\"chat.completion.chunk\",\"created\":1791169237,\"model\":\"claude-opus-4-8\",\"choices\":[],\"usage\":{\"prompt_tokens\":229,\"completion_tokens\":3,\"total_tokens\":232,\"prompt_tokens_details\":{\"cached_tokens\":0}},\"cost\":{\"usd\":0.001464,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"model": "deepseek-v4-flash",
|
||||
"tags": [
|
||||
"prefix:venice-chat",
|
||||
"provider:venice",
|
||||
"protocol:venice-chat",
|
||||
"reasoning",
|
||||
"tool",
|
||||
"tool-loop",
|
||||
"continuation",
|
||||
"usage",
|
||||
"scalar"
|
||||
],
|
||||
"name": "venice-chat/deepseek-v4-flash-preserves-reasoning-through-a-tool-loop-and-follow-up",
|
||||
"recordedAt": "2026-10-05T02:59:53.799Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"deepseek-v4-flash\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"service_tier\":null,\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"Th\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"e user wants me to look\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" up the conversi\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"on rate fo\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"r code ZEBRA\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\", then mult\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"iply by\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" 17 and add 9. Let m\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"e start by lo\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"oking up the rate.\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":[{\"index\":0,\"id\":\"chatcmpl-tool-ab656a8b683341f2\",\"function\":{\"arguments\":\"\",\"name\":\"lookup_rate\"},\"type\":\"function\"}]},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-Rhr7pZI7Hv6zIafL3B1KoyzY\",\"object\":\"chat.completion.chunk\",\"created\":1791169188,\Line truncated
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"deepseek-v4-flash\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"chatcmpl-tool-ab656a8b683341f2\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}],\"reasoning_content\":\"The user wants me to look up the conversion rate for code ZEBRA, then multiply by 17 and add 9. Let me start by looking up the rate.\"},{\"role\":\"tool\",\"tool_call_id\":\"chatcmpl-tool-ab656a8b683341f2\",\"content\":\"{\\\"code\\\":\\\"ZEBRA\\\",\\\"rate\\\":23}\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"tool_choice\":\"none\",\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"service_tier\":null,\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"We have the\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" rate: 2\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"3. Mul\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"tiply by\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" 17: 2\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"3 * 17\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" = 391.\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" Then ad\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"d 9:\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" 391 + 9 = 400.\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"400\",\"reasoning_content\":\" So the answer is 400.\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":\"stop\"}]}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RtwpMZBraGwqJiKRKQFrmmIq\",\"object\":\"chat.completion.chunk\",\"created\":1791169191,\"model\":\"deepseek-v4-flash\",\"choices\":[],\"usage\":{\"prompt_tokens\":128,\"completion_tokens\":46,\"total_tokens\":174,\"prompt_tokens_details\":{\"cached_tokens\":0}}Line truncated
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"deepseek-v4-flash\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"chatcmpl-tool-ab656a8b683341f2\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}],\"reasoning_content\":\"The user wants me to look up the conversion rate for code ZEBRA, then multiply by 17 and add 9. Let me start by looking up the rate.\"},{\"role\":\"tool\",\"tool_call_id\":\"chatcmpl-tool-ab656a8b683341f2\",\"content\":\"{\\\"code\\\":\\\"ZEBRA\\\",\\\"rate\\\":23}\"},{\"role\":\"assistant\",\"content\":\"400\",\"reasoning_content\":\"We have the rate: 23. Multiply by 17: 23 * 17 = 391. Then add 9: 391 + 9 = 400. So the answer is 400.\"},{\"role\":\"user\",\"content\":\"Add 7 to your previous final answer. Reply with just the number.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"tool_choice\":\"none\",\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"service_tier\":null,\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"We need to add\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" 7 to t\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"h\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"e previous ans\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"wer,\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" which\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\" was 400. S\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":\"o 400+7=407. Reply wi\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"407\",\"reasoning_content\":\"th just the number.\",\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":\"stop\"}]}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-R0MMWxoRA5NidBHTttxrMoVe\",\"object\":\"chat.completion.chunk\",\"created\":1791169192,\"model\":\"deepseek-v4-flash\",\"choices\":[],\"usage\":{\"prompt_tokens\":148,\"completion_tokens\":33,\"total_tokens\":181,\"prompt_tokens_details\":{\"cached_tokens\":0}},\"cost\":{\"usd\":0.000029499,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"model": "gemini-3-1-pro-preview",
|
||||
"tags": [
|
||||
"prefix:venice-chat",
|
||||
"provider:venice",
|
||||
"protocol:venice-chat",
|
||||
"reasoning",
|
||||
"tool",
|
||||
"tool-loop",
|
||||
"continuation",
|
||||
"usage",
|
||||
"details"
|
||||
],
|
||||
"name": "venice-chat/gemini-3-1-pro-preview-preserves-reasoning-through-a-tool-loop-and-follow-up",
|
||||
"recordedAt": "2026-10-05T03:00:58.104Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"gemini-3-1-pro-preview\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"gen-1791169245-MjiWKnEhpgHVKzFcOlS0\",\"object\":\"chat.completion.chunk\",\"created\":1791169245,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"**Calculating ZEBRA Conversion**\\n\\nI'm currently processing the calculation involving ZEBRA's conversion rate. My next step is to use the `lookup_rate` tool with the code \\\"ZEBRA\\\" to fetch the necessary value, which will then be used in the full equation.\\n\\n\",\"format\":\"google-gemini-v1\",\"index\":0}],\"reasoning_content\":\"**Calculating ZEBRA Conversion**\\n\\nI'm currently processing the calculation involving ZEBRA's conversion rate. My next step is to use the `lookup_rate` tool with the code \\\"ZEBRA\\\" to fetch the necessary value, which will then be used in the full equation.\\n\\n\"},\"finish_reason\":null,\"native_finish_reason\":null}]}\n\ndata: {\"id\":\"gen-1791169245-MjiWKnEhpgHVKzFcOlS0\",\"object\":\"chat.completion.chunk\",\"created\":1791169245,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\",\"reasoning_details\":[{\"type\":\"reasoning.encrypted\",\"data\":\"AY89a19Tkd2zuyuB3m6as2cMeOoFk8xFfcBdsUI+RBkTCE1GVBd5hMIfNsjOj+YTucPL1hYoWodr2oZsMKDnPuYee0AmGYl8jHzVKgQFSXzgIeWEhG+hOMvTEa4BoruFowcHzbLhym48OlBys47Tlo7WF4tK4s8Z7q8cpbqGsA0NkUqPt8P7Uk3ZaRTUJBbIE08+JgNUUwiJkT4AVSO635aMUYTcIkt+8TVbqOLITfSdDtkxhAmrInfn7FqGlNop3RH1TUcb3xnUOsnHXoreWLlAyWTlWNvOa7hjUH8vUwILPmtG6ixKZdf4i/UIgm551Z5tgE05SJBcR/m7ALagyOyEilWqxGkyf+5jvNycUlk/mBkNHLV45amgUG5zhboVEAEVFYPRa+Nnfzxi+DEdM1ntDURrB5dl4Jbotx67627EbsZm4z2sKUZ4jo/eBj9fI3MUqjTYKtMXBSyuen/m/Uw2Ji9iIQIlWUt/G86kOjQUYFY60g6TxEO4BLouwLZJ0fXxWdolvtMnH90+skJ+I7aFQjGrnwdjGsT0oXA0/vG3W8GhRSokdICVQBq14EFvjcVvI1kEgj7NTtKkB/+UWRtRbRhSA5F25/dHvqAT4ioYy/5sRwYFXMwJmM52I8DpLiaBrp8wTidLNjTpD9KlImbd2r89LS9GG5NeqNWksF9XbEQAMannsu19HC9xf+CCz5FBz5PjpR0+pvybIJLmph94u4I0cdLsbycbbdIaihqeIc593sQv3nvm9VYZMJcgnQWIKmXofSlV4zi6p0wRPvmgeiPo+Lv6DrtPTtcaRLkkyGrg8uvkq2Is9H6me8y8HCXGIze3np22MjWM5r2+UYMia+xY+E3neBC1AZrlN+GJarvf0THgHInLLnE78f+w3mJByFgXMy6OOEs4QI0+F8yxF9GembhqebXYKWGWUkuArnLfV6TZ13v8s1J9IiNObPU0AJjq+wmlg2ChAIs082sh8Q==\",\"format\":\"google-gemini-v1\",\"id\":\"call_4908320\",\"index\":0}],\"reasoning_encrypted\":true},\"finish_reason\":null,\"native_finish_reason\":null}]}\n\ndata: {\"id\":\"gen-1791169245-MjiWKnEhpgHVKzFcOlS0\",\"object\":\"chat.completion.chunk\",\"created\":1791169245,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\",\"tool_calls\":[{\"index\":0,\"id\":\"call_4908320\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"\"}}]},\"finish_reason\":null,\"native_finish_reason\":null}]}\n\ndata: {\"id\":\"gen-1791169245-MjiWKnEhpgHVKzFcOlS0\",\"object\":\"chat.completion.chunk\",\"created\":1791169245,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\",\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}]},\"finish_reason\":null,\"native_finish_reason\":null}]}\n\ndata: {\"id\":\"gen-1791169245-MjiWKnEhpgHVKzFcOlS0\",\"object\":\"chat.completion.chunk\",\"created\":1791169245,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\"},\"finish_reason\":\"tool_calls\",\"native_finish_reason\":\"STOP\"}]}\n\ndata: {\"id\":\"gen-1791169245-MjiWKnEhpgHVKzFcOlS0\",\"object\":\"chat.completion.chunk\",\"created\":1791169245,\"model\":\"gemini-3-1-pro-preview\",\"service_tier\":\"provisioned\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\"},\"finish_reason\":\"tool_calls\",\"native_finish_reason\":\"STOP\"}]}\n\ndata: {\"id\":\"gen-1791169245-MjiWKnEhpgHVKzFcOlS0\",\"object\":\"chat.completion.chunk\",\"created\":1791169245,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[],\"usage\":{\"prompt_tokens\":96,\"completion_tokens\":169,\"total_tokens\":265,\"prompt_tokens_details\":{\"cached_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":152,\"image_tokens\":0,\"audio_tokens\":0}},\"cost\":{\"usd\":0.002775,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"gemini-3-1-pro-preview\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_4908320\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}],\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"**Calculating ZEBRA Conversion**\\n\\nI'm currently processing the calculation involving ZEBRA's conversion rate. My next step is to use the `lookup_rate` tool with the code \\\"ZEBRA\\\" to fetch the necessary value, which will then be used in the full equation.\\n\\n\",\"format\":\"google-gemini-v1\",\"index\":0},{\"type\":\"reasoning.encrypted\",\"data\":\"AY89a19Tkd2zuyuB3m6as2cMeOoFk8xFfcBdsUI+RBkTCE1GVBd5hMIfNsjOj+YTucPL1hYoWodr2oZsMKDnPuYee0AmGYl8jHzVKgQFSXzgIeWEhG+hOMvTEa4BoruFowcHzbLhym48OlBys47Tlo7WF4tK4s8Z7q8cpbqGsA0NkUqPt8P7Uk3ZaRTUJBbIE08+JgNUUwiJkT4AVSO635aMUYTcIkt+8TVbqOLITfSdDtkxhAmrInfn7FqGlNop3RH1TUcb3xnUOsnHXoreWLlAyWTlWNvOa7hjUH8vUwILPmtG6ixKZdf4i/UIgm551Z5tgE05SJBcR/m7ALagyOyEilWqxGkyf+5jvNycUlk/mBkNHLV45amgUG5zhboVEAEVFYPRa+Nnfzxi+DEdM1ntDURrB5dl4Jbotx67627EbsZm4z2sKUZ4jo/eBj9fI3MUqjTYKtMXBSyuen/m/Uw2Ji9iIQIlWUt/G86kOjQUYFY60g6TxEO4BLouwLZJ0fXxWdolvtMnH90+skJ+I7aFQjGrnwdjGsT0oXA0/vG3W8GhRSokdICVQBq14EFvjcVvI1kEgj7NTtKkB/+UWRtRbRhSA5F25/dHvqAT4ioYy/5sRwYFXMwJmM52I8DpLiaBrp8wTidLNjTpD9KlImbd2r89LS9GG5NeqNWksF9XbEQAMannsu19HC9xf+CCz5FBz5PjpR0+pvybIJLmph94u4I0cdLsbycbbdIaihqeIc593sQv3nvm9VYZMJcgnQWIKmXofSlV4zi6p0wRPvmgeiPo+Lv6DrtPTtcaRLkkyGrg8uvkq2Is9H6me8y8HCXGIze3np22MjWM5r2+UYMia+xY+E3neBC1AZrlN+GJarvf0THgHInLLnE78f+w3mJByFgXMy6OOEs4QI0+F8yxF9GembhqebXYKWGWUkuArnLfV6TZ13v8s1J9IiNObPU0AJjq+wmlg2ChAIs082sh8Q==\",\"id\":\"call_4908320\",\"format\":\"google-gemini-v1\",\"index\":0}],\"reasoning_content\":\"**Calculating ZEBRA Conversion**\\n\\nI'm currently processing the calculation involving ZEBRA's conversion rate. My next step is to use the `lookup_rate` tool with the code \\\"ZEBRA\\\" to fetch the necessary value, which will then be used in the full equation.\\n\\n\"},{\"role\":\"tool\",\"tool_call_id\":\"call_4908320\",\"content\":\"{\\\"code\\\":\\\"ZEBRA\\\",\\\"rate\\\":23}\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"tool_choice\":\"none\",\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"gen-1791169249-6wlEwbJv7MicDxVsZViY\",\"object\":\"chat.completion.chunk\",\"created\":1791169249,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"400\",\"role\":\"assistant\"},\"finish_reason\":null,\"native_finish_reason\":null}]}\n\ndata: {\"id\":\"gen-1791169249-6wlEwbJv7MicDxVsZViY\",\"object\":\"chat.completion.chunk\",\"created\":1791169249,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"signature\":\"AY89a1+fQ9YpZF71EoH4pNDO6g5NeqvLRAav/WG6sv9V/5fpifhK6ZDc6m89qgCpOEBhjTJ+a+ux1dFog+eB2nR/G8VVKt1Zr2+2NKXO3Q3ksKE+E51IRRzK/ywpDYpE8AlE6Kb7EG2x/ZVMpy24TOLY+LL8JNsrz8uHBC1PtPtiZe/gP+Kvu0Yqk+VNYv16wAubtiA0oy0c+wyRzd80jRvqCZpBIGPlLAU515MPpjXNGu0A5ft4uu3oGPJHl5G/Ry4Fm5fvWKl759+Jwx9m7d50+vcttr5SpHm//MvNsUTnqjYkraw1S69+9oB57HoBn8d8pwTHpud/6FARun33EjfPW86Xx2fS448QtKc3c9nxSdGyZgTV0TpA63Uz7n0nGd9fRYrghp3lQv5QyoRIgNg+YeBf/WDNzSW2MO6Y2HLFoo3K0vJh1KMfWhjECNxP1Qfjfz+VjwSV7+OzF9CNw23f8R2udRBr1EUYhTu13ckjFLWjCD5fGjvmLhsae3CgmuFV2Rvaxqrf/H79Tz+X9W/Tw8PuQ0E1pCCpiMe1gR1CT+LJPWxjV96DPHQ0r+1lnekrr5NkO7UAZ64HVALHJRpACdJsVhwI1TBi4f89b1by1s7OaWlQTw7thX7CLRV2W3HoMUccJaofszVEfbD8+SaeZtZgyw9mkYvxgYtu3Odxx2YGHgs=\",\"format\":\"google-gemini-v1\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null}]}\n\ndata: {\"id\":\"gen-1791169249-6wlEwbJv7MicDxVsZViY\",\"object\":\"chat.completion.chunk\",\"created\":1791169249,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\"},\"finish_reason\":\"stop\",\"native_finish_reason\":\"STOP\"}]}\n\ndata: {\"id\":\"gen-1791169249-6wlEwbJv7MicDxVsZViY\",\"object\":\"chat.completion.chunk\",\"created\":1791169249,\"model\":\"gemini-3-1-pro-preview\",\"service_tier\":\"provisioned\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\"},\"finish_reason\":\"stop\",\"native_finish_reason\":\"STOP\"}]}\n\ndata: {\"id\":\"gen-1791169249-6wlEwbJv7MicDxVsZViY\",\"object\":\"chat.completion.chunk\",\"created\":1791169249,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[],\"usage\":{\"prompt_tokens\":233,\"completion_tokens\":129,\"total_tokens\":362,\"prompt_tokens_details\":{\"cached_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":126,\"image_tokens\":0,\"audio_tokens\":0}},\"cost\":{\"usd\":0.0025175,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"gemini-3-1-pro-preview\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_4908320\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}],\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"**Calculating ZEBRA Conversion**\\n\\nI'm currently processing the calculation involving ZEBRA's conversion rate. My next step is to use the `lookup_rate` tool with the code \\\"ZEBRA\\\" to fetch the necessary value, which will then be used in the full equation.\\n\\n\",\"format\":\"google-gemini-v1\",\"index\":0},{\"type\":\"reasoning.encrypted\",\"data\":\"AY89a19Tkd2zuyuB3m6as2cMeOoFk8xFfcBdsUI+RBkTCE1GVBd5hMIfNsjOj+YTucPL1hYoWodr2oZsMKDnPuYee0AmGYl8jHzVKgQFSXzgIeWEhG+hOMvTEa4BoruFowcHzbLhym48OlBys47Tlo7WF4tK4s8Z7q8cpbqGsA0NkUqPt8P7Uk3ZaRTUJBbIE08+JgNUUwiJkT4AVSO635aMUYTcIkt+8TVbqOLITfSdDtkxhAmrInfn7FqGlNop3RH1TUcb3xnUOsnHXoreWLlAyWTlWNvOa7hjUH8vUwILPmtG6ixKZdf4i/UIgm551Z5tgE05SJBcR/m7ALagyOyEilWqxGkyf+5jvNycUlk/mBkNHLV45amgUG5zhboVEAEVFYPRa+Nnfzxi+DEdM1ntDURrB5dl4Jbotx67627EbsZm4z2sKUZ4jo/eBj9fI3MUqjTYKtMXBSyuen/m/Uw2Ji9iIQIlWUt/G86kOjQUYFY60g6TxEO4BLouwLZJ0fXxWdolvtMnH90+skJ+I7aFQjGrnwdjGsT0oXA0/vG3W8GhRSokdICVQBq14EFvjcVvI1kEgj7NTtKkB/+UWRtRbRhSA5F25/dHvqAT4ioYy/5sRwYFXMwJmM52I8DpLiaBrp8wTidLNjTpD9KlImbd2r89LS9GG5NeqNWksF9XbEQAMannsu19HC9xf+CCz5FBz5PjpR0+pvybIJLmph94u4I0cdLsbycbbdIaihqeIc593sQv3nvm9VYZMJcgnQWIKmXofSlV4zi6p0wRPvmgeiPo+Lv6DrtPTtcaRLkkyGrg8uvkq2Is9H6me8y8HCXGIze3np22MjWM5r2+UYMia+xY+E3neBC1AZrlN+GJarvf0THgHInLLnE78f+w3mJByFgXMy6OOEs4QI0+F8yxF9GembhqebXYKWGWUkuArnLfV6TZ13v8s1J9IiNObPU0AJjq+wmlg2ChAIs082sh8Q==\",\"id\":\"call_4908320\",\"format\":\"google-gemini-v1\",\"index\":0}],\"reasoning_content\":\"**Calculating ZEBRA Conversion**\\n\\nI'm currently processing the calculation involving ZEBRA's conversion rate. My next step is to use the `lookup_rate` tool with the code \\\"ZEBRA\\\" to fetch the necessary value, which will then be used in the full equation.\\n\\n\"},{\"role\":\"tool\",\"tool_call_id\":\"call_4908320\",\"content\":\"{\\\"code\\\":\\\"ZEBRA\\\",\\\"rate\\\":23}\"},{\"role\":\"assistant\",\"content\":\"400\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"format\":\"google-gemini-v1\",\"index\":0,\"signature\":\"AY89a1+fQ9YpZF71EoH4pNDO6g5NeqvLRAav/WG6sv9V/5fpifhK6ZDc6m89qgCpOEBhjTJ+a+ux1dFog+eB2nR/G8VVKt1Zr2+2NKXO3Q3ksKE+E51IRRzK/ywpDYpE8AlE6Kb7EG2x/ZVMpy24TOLY+LL8JNsrz8uHBC1PtPtiZe/gP+Kvu0Yqk+VNYv16wAubtiA0oy0c+wyRzd80jRvqCZpBIGPlLAU515MPpjXNGu0A5ft4uu3oGPJHl5G/Ry4Fm5fvWKl759+Jwx9m7d50+vcttr5SpHm//MvNsUTnqjYkraw1S69+9oB57HoBn8d8pwTHpud/6FARun33EjfPW86Xx2fS448QtKc3c9nxSdGyZgTV0TpA63Uz7n0nGd9fRYrghp3lQv5QyoRIgNg+YeBf/WDNzSW2MO6Y2HLFoo3K0vJh1KMfWhjECNxP1Qfjfz+VjwSV7+OzF9CNw23f8R2udRBr1EUYhTu13ckjFLWjCD5fGjvmLhsae3CgmuFV2Rvaxqrf/H79Tz+X9W/Tw8PuQ0E1pCCpiMe1gR1CT+LJPWxjV96DPHQ0r+1lnekrr5NkO7UAZ64HVALHJRpACdJsVhwI1TBi4f89b1by1s7OaWlQTw7thX7CLRV2W3HoMUccJaofszVEfbD8+SaeZtZgyw9mkYvxgYtu3Odxx2YGHgs=\"}]},{\"role\":\"user\",\"content\":\"Add 7 to your previous final answer. Reply with just the number.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"tool_choice\":\"none\",\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"gen-1791169254-bvEsScICXWimu8xzJFF1\",\"object\":\"chat.completion.chunk\",\"created\":1791169254,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"407\",\"role\":\"assistant\"},\"finish_reason\":null,\"native_finish_reason\":null}]}\n\ndata: {\"id\":\"gen-1791169254-bvEsScICXWimu8xzJFF1\",\"object\":\"chat.completion.chunk\",\"created\":1791169254,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"signature\":\"AY89a1/t2vneT6Dy8hJmYd66cSC0Fk3bKHK7hJI5vTtBcKe38EQ6JXMwTlxi2K47pfmvruV0B6Ks0CZCF9N7rEOT+fXTleU1WPEAHHJPX7KkncEJK4KNIeJsTzyEjSPn5t8kb/vNruIV2KE2/l0kylycTNOubuO8DGlkKOp478zuwZppB0vFaoLp1byEUtyT/MHdN/KckvvKY99ZB2ksWrc51/5Z7jx7GeXGpTl3jHEKzdLWrfsYYyjPOv4h0ZHN8ANmYMTWpGUm8jqxB0pHQFBVS0U5YhF+fuU6Nk3lUNuLnEydq6UH6VydtTxDjUDALIfHhkasmTRXnL/7X3/z3rLhRXRGhga9lHnSnEhmjdLj9iOn/73wjA4QxnT14P+8F45z4ePO19ZGKr/j5WBvBMem92Yqv9HweDo9IreBa8EbqPwlsnjbXvJB7MuBp2TJd4szb7azQ+zaPU7pf5B3fjKC3K8p26qF0C+TkGd72PezZw662/FMkkC/b88sgDgMfgSK7dMqVvv7swafRzFL1IZzTFoJJ3Ouk/VCKGWCHOx+c2EPtvv+IzGhQ1k9dn44bq953wBamkzDjQWcP46+VKp2PPz5yV9AgGCmdi1SRYNU361FiUGlU40cImBLK1MoIqa/YnYaaXMtK9L7/35uOjyg/hae3REIw5N4Y1fiSx9UCKi7eYviBwrY3kZJYdy4UdsN63ahHb2SO1gfZKAg1G36Gn5TIiYGO4dNWE9c\",\"format\":\"google-gemini-v1\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null}]}\n\ndata: {\"id\":\"gen-1791169254-bvEsScICXWimu8xzJFF1\",\"object\":\"chat.completion.chunk\",\"created\":1791169254,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\"},\"finish_reason\":\"stop\",\"native_finish_reason\":\"STOP\"}]}\n\ndata: {\"id\":\"gen-1791169254-bvEsScICXWimu8xzJFF1\",\"object\":\"chat.completion.chunk\",\"created\":1791169254,\"model\":\"gemini-3-1-pro-preview\",\"service_tier\":\"provisioned\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\",\"role\":\"assistant\"},\"finish_reason\":\"stop\",\"native_finish_reason\":\"STOP\"}]}\n\ndata: {\"id\":\"gen-1791169254-bvEsScICXWimu8xzJFF1\",\"object\":\"chat.completion.chunk\",\"created\":1791169254,\"model\":\"gemini-3-1-pro-preview\",\"choices\":[],\"usage\":{\"prompt_tokens\":99,\"completion_tokens\":119,\"total_tokens\":218,\"prompt_tokens_details\":{\"cached_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":116,\"image_tokens\":0,\"audio_tokens\":0}},\"cost\":{\"usd\":0.0020325,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"tags": [
|
||||
"prefix:venice-chat",
|
||||
"provider:venice",
|
||||
"protocol:venice-chat",
|
||||
"tool",
|
||||
"parallel",
|
||||
"signature"
|
||||
],
|
||||
"name": "venice-chat/gemini-preserves-per-call-signatures-through-parallel-tools",
|
||||
"recordedAt": "2026-10-05T03:21:54.383Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"gemini-3-8-flash\",\"messages\":[{\"role\":\"user\",\"content\":\"Look up private rates for both ZEBRA and MOOSE using two calls to lookup_rate. Then add the rates and multiply by 7. Use parallel calls if possible.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false},\"parallel_tool_calls\":true}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"gcp-1791170510482-itouwq\",\"object\":\"chat.completion.chunk\",\"created\":1791170510,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"tool_calls\":[{\"index\":0,\"id\":\"call_0\",\"type\":\"function\",\"thought_signature\":\"AY89a1/bp+ihzOXpD71E6UhQv6xnBjHTAdPeNHvLEAevtqznKg46D/3qO3e9Qg7wGmccL6IpLV56PwWIT+6pXoeU6ix8JCCk7nlml/Sz2huX/rNFoSRHpB+YAZK07lHP9cbotXy7FPNMaRhsl18sPSJZLlPK0iTGhJa7MmH72r4v/G3/izffMKUPRos6i5qQ52La10FUWSunPigqNnglEvWEC3Yb+d+PnEq5iOPaVCD0awXjhsIk8L0n4+T6jM4epO+whUSSgvH9PGwgmsP197hb7l5YSjQncNX0oF1G4ch3xrFzXyS/noFFy6SlBfzfN0NJmAyP//4oVqjffUJngigTAtboI4HdDwH1fPHuI5FTfmVcUGVVIEjhAEDAAHtS77uW/XdLH4bsSigjYeCzgRTYmHP8bqFb1HjRjl2HK2Pr1y6ch0JSIgtAKv8Kj4R0PM8rIYxxf7LgrsaVWogt4rq2M4HvcUcBi6IhQ/500JUCoqdhlTGMqCFUHkN6P/qAoPGZXmo50OvtNChQ4vXVGYxWp89IRwdcv8vqjIFk75/R6oZG9BsrUaC1JnQN8i3BbYc1bz/lzFCQ1IC/g1Sm+wPhsaPmoVN77101ZAdNMiP4B5Ow7K/UycMunFKWy4xdpaT7Pb+LLNy6GYy9q2TvoRXTq1lJugLH4Q8TQZj5neWZmiDxqzsj0Xvwew7zLwGSMfkpBB4rgx9XWMx5CwqO068qjhmo+0gUkxMug2RHblEGnPO7i0i9fYj9ltDfUpFxN2adDpyk4dwuIeVSlu4N4oHOgjGms5jWLp0MqkyoKFo=\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}]}}]}\n\ndata: {\"id\":\"gcp-1791170510482-itouwq\",\"object\":\"chat.completion.chunk\",\"created\":1791170510,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"id\":\"call_1\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"MOOSE\\\"}\"}}]}}]}\n\ndata: {\"id\":\"gcp-1791170510482-itouwq\",\"object\":\"chat.completion.chunk\",\"created\":1791170510,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"tool_calls\"}]}\n\ndata: {\"id\":\"gcp-1791170510482-itouwq\",\"object\":\"chat.completion.chunk\",\"created\":1791170510,\"model\":\"gemini-3-8-flash\",\"choices\":[],\"usage\":{\"prompt_tokens\":74,\"completion_tokens\":156,\"total_tokens\":230},\"cost\":{\"usd\":0.000800625,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"gemini-3-8-flash\",\"messages\":[{\"role\":\"user\",\"content\":\"Look up private rates for both ZEBRA and MOOSE using two calls to lookup_rate. Then add the rates and multiply by 7. Use parallel calls if possible.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_0\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"},\"thought_signature\":\"AY89a1/bp+ihzOXpD71E6UhQv6xnBjHTAdPeNHvLEAevtqznKg46D/3qO3e9Qg7wGmccL6IpLV56PwWIT+6pXoeU6ix8JCCk7nlml/Sz2huX/rNFoSRHpB+YAZK07lHP9cbotXy7FPNMaRhsl18sPSJZLlPK0iTGhJa7MmH72r4v/G3/izffMKUPRos6i5qQ52La10FUWSunPigqNnglEvWEC3Yb+d+PnEq5iOPaVCD0awXjhsIk8L0n4+T6jM4epO+whUSSgvH9PGwgmsP197hb7l5YSjQncNX0oF1G4ch3xrFzXyS/noFFy6SlBfzfN0NJmAyP//4oVqjffUJngigTAtboI4HdDwH1fPHuI5FTfmVcUGVVIEjhAEDAAHtS77uW/XdLH4bsSigjYeCzgRTYmHP8bqFb1HjRjl2HK2Pr1y6ch0JSIgtAKv8Kj4R0PM8rIYxxf7LgrsaVWogt4rq2M4HvcUcBi6IhQ/500JUCoqdhlTGMqCFUHkN6P/qAoPGZXmo50OvtNChQ4vXVGYxWp89IRwdcv8vqjIFk75/R6oZG9BsrUaC1JnQN8i3BbYc1bz/lzFCQ1IC/g1Sm+wPhsaPmoVN77101ZAdNMiP4B5Ow7K/UycMunFKWy4xdpaT7Pb+LLNy6GYy9q2TvoRXTq1lJugLH4Q8TQZj5neWZmiDxqzsj0Xvwew7zLwGSMfkpBB4rgx9XWMx5CwqO068qjhmo+0gUkxMug2RHblEGnPO7i0i9fYj9ltDfUpFxN2adDpyk4dwuIeVSlu4N4oHOgjGms5jWLp0MqkyoKFo=\"},{\"id\":\"call_1\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"MOOSE\\\"}\"}}]},{\"role\":\"tool\",\"tool_call_id\":\"call_0\",\"content\":\"{\\\"rate\\\":23}\"},{\"role\":\"tool\",\"tool_call_id\":\"call_1\",\"content\":\"{\\\"rate\\\":31}\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"tool_choice\":\"none\",\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false},\"parallel_tool_calls\":true}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"gcp-1791170512529-w6lmsz\",\"object\":\"chat.completion.chunk\",\"created\":1791170512,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"The retrieved rates are:\\n- **\"}}]}\n\ndata: {\"id\":\"gcp-1791170512529-w6lmsz\",\"object\":\"chat.completion.chunk\",\"created\":1791170512,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"ZEBRA:** 23\\n- **MOOSE:** 31\\n\\n### Calculation:\\n1. **Add\"}}]}\n\ndata: {\"id\":\"gcp-1791170512529-w6lmsz\",\"object\":\"chat.completion.chunk\",\"created\":1791170512,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" the rates:** \\n $$23 + 31 = 54$$\\n\\n2. **Multiply by 7:** \"}}]}\n\ndata: {\"id\":\"gcp-1791170512529-w6lmsz\",\"object\":\"chat.completion.chunk\",\"created\":1791170512,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"\\n $$54 \\\\times 7 = 378$$\\n\\nThe final result is **378\"}}]}\n\ndata: {\"id\":\"gcp-1791170512529-w6lmsz\",\"object\":\"chat.completion.chunk\",\"created\":1791170512,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"**.\"}}]}\n\ndata: {\"id\":\"gcp-1791170512529-w6lmsz\",\"object\":\"chat.completion.chunk\",\"created\":1791170512,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"thought_signature\":\"AY89a18wXUWI7m5/5GGqxfoJDqE4MU2X2SR/ZQMCX+JQ/clHQynyEjplK4a8w9tXAi8uuxYPVxYj1ULcb83zUQBsr77tSkJN5R0J2Jgc2HzYtmTW7OYHoFQqmMESnDjvDiO51y3xpXGbVkqRlXwfmap+Tpivfx45hiXlns/hObEQo1gE70NzD7d8CQOseYVz2N7MPMmGDqpAy+5SAHXGAcQ9K2ufHNUdfWM/uUi+sGUcDhGnjPXPlzIuYk7IjUQXNAH9FFqo19dBQPhE106C3aI69QAuMvyZZ/no4ou9XSOUXrstjzQwUM+TOJXsab80F1+C6DghvYm0UZSb827xCKPtj7oCQwtwg+f4sWELhflp42IL3URo2UxpZaDNpt7PYXmmcCvKAN7/PTirCijNWMtlDL0LDbiKj+DfOFEuS2VxVq+yQgWRbKJZF7bl8BCSe7+Qab0bAsu0ZJXKBlxs46ulaXn5cc933y/Yv7O0XGHbVULMzeEpZndzkHqZYs5D+ve+CJFfjWsVk1NKrTdXqt11Ov470+MCpSlHTXdjug7oUd0A0b5AH+bF4yAZAGj4snJ7hi04EQ4Ch7rASB3OB+YB+8SnStAGf0XuimNgY2wzR68qaQ==\"}}]}\n\ndata: {\"id\":\"gcp-1791170512529-w6lmsz\",\"object\":\"chat.completion.chunk\",\"created\":1791170512,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}]}\n\ndata: {\"id\":\"gcp-1791170512529-w6lmsz\",\"object\":\"chat.completion.chunk\",\"created\":1791170512,\"model\":\"gemini-3-8-flash\",\"choices\":[],\"usage\":{\"prompt_tokens\":206,\"completion_tokens\":208,\"total_tokens\":414},\"cost\":{\"usd\":0.001168125,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"gemini-3-8-flash\",\"messages\":[{\"role\":\"user\",\"content\":\"Look up private rates for both ZEBRA and MOOSE using two calls to lookup_rate. Then add the rates and multiply by 7. Use parallel calls if possible.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_0\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"},\"thought_signature\":\"AY89a1/bp+ihzOXpD71E6UhQv6xnBjHTAdPeNHvLEAevtqznKg46D/3qO3e9Qg7wGmccL6IpLV56PwWIT+6pXoeU6ix8JCCk7nlml/Sz2huX/rNFoSRHpB+YAZK07lHP9cbotXy7FPNMaRhsl18sPSJZLlPK0iTGhJa7MmH72r4v/G3/izffMKUPRos6i5qQ52La10FUWSunPigqNnglEvWEC3Yb+d+PnEq5iOPaVCD0awXjhsIk8L0n4+T6jM4epO+whUSSgvH9PGwgmsP197hb7l5YSjQncNX0oF1G4ch3xrFzXyS/noFFy6SlBfzfN0NJmAyP//4oVqjffUJngigTAtboI4HdDwH1fPHuI5FTfmVcUGVVIEjhAEDAAHtS77uW/XdLH4bsSigjYeCzgRTYmHP8bqFb1HjRjl2HK2Pr1y6ch0JSIgtAKv8Kj4R0PM8rIYxxf7LgrsaVWogt4rq2M4HvcUcBi6IhQ/500JUCoqdhlTGMqCFUHkN6P/qAoPGZXmo50OvtNChQ4vXVGYxWp89IRwdcv8vqjIFk75/R6oZG9BsrUaC1JnQN8i3BbYc1bz/lzFCQ1IC/g1Sm+wPhsaPmoVN77101ZAdNMiP4B5Ow7K/UycMunFKWy4xdpaT7Pb+LLNy6GYy9q2TvoRXTq1lJugLH4Q8TQZj5neWZmiDxqzsj0Xvwew7zLwGSMfkpBB4rgx9XWMx5CwqO068qjhmo+0gUkxMug2RHblEGnPO7i0i9fYj9ltDfUpFxN2adDpyk4dwuIeVSlu4N4oHOgjGms5jWLp0MqkyoKFo=\"},{\"id\":\"call_1\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"MOOSE\\\"}\"}}]},{\"role\":\"tool\",\"tool_call_id\":\"call_0\",\"content\":\"{\\\"rate\\\":23}\"},{\"role\":\"tool\",\"tool_call_id\":\"call_1\",\"content\":\"{\\\"rate\\\":31}\"},{\"role\":\"assistant\",\"content\":\"The retrieved rates are:\\n- **ZEBRA:** 23\\n- **MOOSE:** 31\\n\\n### Calculation:\\n1. **Add the rates:** \\n $$23 + 31 = 54$$\\n\\n2. **Multiply by 7:** \\n $$54 \\\\times 7 = 378$$\\n\\nThe final result is **378**.\",\"thought_signature\":\"AY89a18wXUWI7m5/5GGqxfoJDqE4MU2X2SR/ZQMCX+JQ/clHQynyEjplK4a8w9tXAi8uuxYPVxYj1ULcb83zUQBsr77tSkJN5R0J2Jgc2HzYtmTW7OYHoFQqmMESnDjvDiO51y3xpXGbVkqRlXwfmap+Tpivfx45hiXlns/hObEQo1gE70NzD7d8CQOseYVz2N7MPMmGDqpAy+5SAHXGAcQ9K2ufHNUdfWM/uUi+sGUcDhGnjPXPlzIuYk7IjUQXNAH9FFqo19dBQPhE106C3aI69QAuMvyZZ/no4ou9XSOUXrstjzQwUM+TOJXsab80F1+C6DghvYm0UZSb827xCKPtj7oCQwtwg+f4sWELhflp42IL3URo2UxpZaDNpt7PYXmmcCvKAN7/PTirCijNWMtlDL0LDbiKj+DfOFEuS2VxVq+yQgWRbKJZF7bl8BCSe7+Qab0bAsu0ZJXKBlxs46ulaXn5cc933y/Yv7O0XGHbVULMzeEpZndzkHqZYs5D+ve+CJFfjWsVk1NKrTdXqt11Ov470+MCpSlHTXdjug7oUd0A0b5AH+bF4yAZAGj4snJ7hi04EQ4Ch7rASB3OB+YB+8SnStAGf0XuimNgY2wzR68qaQ==\"},{\"role\":\"user\",\"content\":\"Add 7 to your previous final answer. Reply with just the number.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"tool_choice\":\"none\",\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"effort\":\"high\"},\"venice_parameters\":{\"include_venice_system_prompt\":false},\"parallel_tool_calls\":true}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"gcp-1791170514341-j5gh1h\",\"object\":\"chat.completion.chunk\",\"created\":1791170514,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"385\"}}]}\n\ndata: {\"id\":\"gcp-1791170514341-j5gh1h\",\"object\":\"chat.completion.chunk\",\"created\":1791170514,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{\"thought_signature\":\"AY89a1/DMIB/2qixC5QVQQH1tA2QiQFpEsXnIDd7wlCgwuYQXBGWgSsP1bpTZJUJM/yqKdQh96+/c6c28VMbW5iovCDxxeK56KfmSBSBIPtNW8BUHHLxQw9vdsxQvQyHcGW6rLb4W3gElqx6JFmNkTMvijUS9QDgkPlPipirbv7pqLejFyQ040GD4IVhP8ovyR49EJm61W0JvJOPFT30/gVvaKA6RnRgTKGiHrZWVqLxhKVkb0gC7jI9CNNASOYH67uelFQ2trbcf5Qbhx4q93vAErFsBzvzliSuaELDrxZAF9VCNIiWz4AUtEWI1FLCMYxkgNry/K+iNpwcXu8BxABETbNkEb722wjpt1A2EZK/5qhqKQvUOq+WgSCPCLoI1zfUiGN6UV9D/QGtyS2Iyt3AYlvKjZVVzP217ItWSDacGzigLd4t+4MMW7Dvbs7ffBvBV+EzMCP1dnsLkKCxicfvT3e2EgY+liDSaSZG3sE7Lm4WKCYbI4rrBLMupERSaFfAHWdTlea5HeM=\"}}]}\n\ndata: {\"id\":\"gcp-1791170514341-j5gh1h\",\"object\":\"chat.completion.chunk\",\"created\":1791170514,\"model\":\"gemini-3-8-flash\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}]}\n\ndata: {\"id\":\"gcp-1791170514341-j5gh1h\",\"object\":\"chat.completion.chunk\",\"created\":1791170514,\"model\":\"gemini-3-8-flash\",\"choices\":[],\"usage\":{\"prompt_tokens\":429,\"completion_tokens\":83,\"total_tokens\":512},\"cost\":{\"usd\":0.00079125,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"model": "openai-gpt-54-mini",
|
||||
"tags": [
|
||||
"prefix:venice-chat",
|
||||
"provider:venice",
|
||||
"protocol:venice-chat",
|
||||
"reasoning",
|
||||
"tool",
|
||||
"tool-loop",
|
||||
"continuation",
|
||||
"usage",
|
||||
"encrypted"
|
||||
],
|
||||
"name": "venice-chat/openai-gpt-54-mini-preserves-reasoning-through-a-tool-loop-and-follow-up",
|
||||
"recordedAt": "2026-10-05T03:01:10.096Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"openai-gpt-54-mini\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for a code. Only this tool knows the rate.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"string\",\"enum\":[\"ZEBRA\",\"MOOSE\"]}},\"required\":[\"code\"],\"additionalProperties\":false},\"strict\":false}}],\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"**Calculating private data**\\n\\nI\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" need\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" to\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" follow\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" the\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" developer\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"'s\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" instructions\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" and\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" use\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" the\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" provided\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" tool\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" to\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" handle\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" private\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" data\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\".\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312efd07487d28fc51d6572174c85\",\"object\":\"chat.completion.chunk\",\"created\":1791169264,\"model\":\"openai-gpLine truncated
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"openai-gpt-54-mini\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_onp7EArhOgXu0hGRF6Y5WHLu\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}],\"reasoning_details\":[{\"type\":\"reasoning.encrypted\",\"data\":\"gAAAAABqwxLxEN4vtmI2WcZ_aDDttdmPwAHgnV2gLZBo_f_mmTdGm4oZzE2JVzcj72AeXHyABmmo2VQN4nXaZK9GSSUZRlYL8mECMxKTj9AMgL8zlnuN5WDexxU-e9SduGP36RN9nH56-go4dz8eu5DEMvMf_TMoTnxz5AnC_UWbty63Vp8jEgkD-DoRjd0cg9LjthP_FLyMvP2Wj9qMJxEuO7Mw2_Pu4I3YeChnygLvmRfRR2QkamL5vjb9yHkl0Lb502vEGB2DW_czNEpHxisifvwRBjA7vk0mbn2dlhiR80aNHO71hC-QqrtUfPXx2HIbVLfbPdJf0saI0wD7ZuCJSQCBfB7fMCnj2ZLQeXa67lgXwsZDLBg4HmSJFvsMinx1IHIjUk7iebsKvmYx40cjqpXL3wj7htZWk2hO9OyGGUwlRsn5THdhTsgwg2SPbuHxb-sLPQnEFZ7bRp5lsVm31X2dlHDa1uZ7KLJZyy9g2CLIKsBwFFoCK7jY3HBXfL21ac5TAkOzVmz-XKl6OMPSl-PSdByOO15uHHpyOcJvJvuaea5Tj1nihtuDlhUP5EQPi7MiWpJMFo9AhDCafAbaQOEF5W8AQPeb_GXvPTzhySRAC8PxrhraEcZ4fjpjLqkv6mi_A1YHwbHEHHWjcK5VEKc3dadlIM_s6djclFBocVXrvnQQElVhWBDM-RtK9sgR07BFj5LVk6fYvg0b6gQnbDuQH18jhtPoj0SX0lN921XEQ1ebMCWGLANND2ew_wyNShYouJohefLULicWG57xh_yV1KEG1ufBedq2CPvCHA9Hm5UssbeJx5yBriyUA2Yh4D7j2UBT_KDWEHydDLQ4mWEyLTfQn0ZB3ZOqkU79z3HpK2w_VHUnkl5nEYEU2bmF5lsG33B4gtbQIBtZT76-fizXsvVZx__taOWXg96VMi3CD3DY0TS76B4U92KFmAFJ4aeiM8bkPuzf1Qd202EWE39CotUDoxAM6mzQu0NObTDnGQE776P6kzUoIKUmP8sDwYG5xot8ZTuXcBYysvj4-pFC_fvqMhsdfgonbke78SIjHtmePsOkfHBnCjSSUFKEbaM0nm8jJ6nYVwiYFuXBKD31QD462TAC7ORVIn32sWSgV2t3Sd7vq4ws2Yy7nUoILRAt_NYQUEXt7_R8J5YWj1L6Ruagk7Vtt-CAWxT6FhVyU4JhMb6-tJrYHgdmtunYrjpHBiOVdQR25aOmLbc_WlDvpO4azcRazpgkASAjPaaDycYceKcheiyUDBgFrvcSYrS1fJb6YZrTzOKw1Ztd0YsklS4nc3jffLNLrBQVvnkajj0OHjGcW8wkP93TCMJyt8tfIH0Rd5hIZLY5EqUWj9yZgXO7CuDKQZIEI0oZXef3mjfQqH8Q9rZsSgS3DI3mCF3CN003R_ZKKLGWkG8VzwlvdocNxaV_Z-ujp_O0YMyOcmEoTJI-j3JP3nefNboyP7EWND6VWDjJbqg64dvu0PK0EW5L0lnAu0l-WVb2qmXLYao_7bOlD8JLFZOyUgHAWmetmnm0NuxzevJEVBkNUu1jQatPzf2Jzf9SGKM_3bM_z0TM5McCZ2Pikzwp96QlaiEEWV_j2g02PT5Y3td-lfpoKxoFD5tltGNY9TlPzK-4a9Iz0hloiCprxWMLGKw2JzctrPF1xr42PKGNgPE84xAQ3sQ4mQ==\",\"id\":\"rs_014406f0f45e19c6016ac312f01d2487d2a5f2bdb7fbc42f76\",\"format\":\"openai-responses-v1\",\"index\":0}],\"reasoning_content\":\"**Calculating private data**\\n\\nI need to follow the developer's instructions and use the provided tool to handle private data. First, I should look up the rate for \\\"ZEBRA\\\" before I answer. After that, I’ll multiply the rate by 17 and then add 9 to get the required number. It’s important to give only the requested number and avoid making another tool call. I’ll likely use the commentary channel for this tool call.\\n\\n__ENCRYPTED_REASONING__id=rs_014406f0f45e19c6016ac312f01d2487d2a5f2bdb7fbc42f76\\ngAAAAABqwxLxEN4vtmI2WcZ_aDDttdmPwAHgnV2gLZBo_f_mmTdGm4oZzE2JVzcj72AeXHyABmmo2VQN4nXaZK9GSSUZRlYL8mECMxKTj9AMgL8zlnuN5WDexxU-e9SduGP36RN9nH56-go4dz8eu5DEMvMf_TMoTnxz5AnC_UWbty63Vp8jEgkD-DoRjd0cg9LjthP_FLyMvP2Wj9qMJxEuO7Mw2_Pu4I3YeChnygLvmRfRR2QkamL5vjb9yHkl0Lb502vEGB2DW_czNEpHxisifvwRBjA7vk0mbn2dlhiR80aNHO71hC-QqrtUfPXx2HIbVLfbPdJf0saI0wD7ZuCJSQCBfB7fMCnj2ZLQeXa67lgXwsZDLBg4HmSJFvsMinx1IHIjUk7iebsKvmYx40cjqpXL3wj7htZWk2hO9OyGGUwlRsn5THdhTsgwg2SPbuHxb-sLPQnEFZ7bRp5lsVm31X2dlHDa1uZ7KLJZyy9g2CLIKsBwFFoCK7jY3HBXfL21ac5TAkOzVmz-XKl6OMPSl-PSdByOO15uHHpyOcJvJvuaea5Tj1nihtuDlhUP5EQPi7MiWpJMFo9AhDCafAbaQOEF5W8AQPeb_GXvPTzhySRAC8PxrhraEcZ4fjpjLqkv6mi_A1YHwbHEHHWjcK5VEKc3dadlIM_s6djclFBocVXrvnQQElVhWBDM-RtK9sgR07BFj5LVk6fYvg0b6gQnbDuQH18jhtPoj0SX0lN921XEQ1ebMCWGLANND2ew_wyNShYouJohefLULicWG57xh_yV1KEG1ufBedq2CPvCHA9Hm5UssbeJx5yBriyUA2Yh4D7j2UBT_KDWEHydDLQ4mWEyLTfQn0ZB3ZOqkU79z3HpK2w_VHUnkl5nEYEU2bmF5lsG33B4gtbQIBtZT76-fizXsvVZx__taOWXg96VMi3CD3DY0TS76B4U92KFmAFJ4aeiM8bkPuzf1Qd202EWE39CotUDoxAM6mzQu0NObTDnGQE776P6kzUoIKUmP8sDwYG5xot8ZTuXcBYysvj4-pFC_fvqMhsdfgonbke78SIjHtmePsOkfHBnCjSSUFKEbaM0nm8jJ6nYVwiYFuXBKD31QD462TAC7ORVIn32sWSgV2t3Sd7vq4ws2Yy7nUoILRAt_NYQUEXt7_R8J5YWj1L6Ruagk7Vtt-CAWxT6FhVyU4JhMb6-tJrYHgdmtunYrjpHBiOVdQR25aOmLbc_WlDvpO4azcRazpgkASAjPaaDycYceKcheiyUDBgFrvcSYrS1fJb6YZrTzOKw1Ztd0YsklS4nc3jffLNLrBQVvnkajj0OHjGcW8wkP93TCMJyt8tfIH0Rd5hIZLY5EqUWj9yZgXO7CuDKQZIEI0oZXef3mjfQqH8Q9rZsSgS3DI3mCF3CN003R_ZKKLGWkG8VzwlvdocNxaV_Z-ujp_O0YMyOcmEoTJI-j3JP3nefNboyP7EWND6VWDjJbqg64dvu0PK0EW5L0lnAu0l-WVb2qmXLYao_7bOlD8JLFZOyUgHAWmetmnm0NuxzevJEVBkNUu1jQatPzf2Jzf9SGKM_3bM_z0TM5McCZ2Pikzwp96QlaiEEWV_j2g02PT5Y3td-lfpoKxoFD5tltGNY9TlPzK-4a9Iz0hloiCprxWMLGKw2JzctrPF1xr42PKGNgPE84xAQ3sQ4mQ==\"},{\"role\":\"tool\",\"tool_call_id\":\"call_onp7EArhOgXu0hGRF6Y5WHLu\",\"content\":\"{\\\"code\\\":\\\"ZEBRA\\\",\\\"rate\\\":23}\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"description\":\"Retrieve the private conversion rate for aLine truncated
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"**Calculating a simple math problem**\\n\\nI'm\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" working\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" through\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" the\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" math\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\":\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" first\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\",\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" I\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169266,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" multiply\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" 23\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" by\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" 17\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\",\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" and\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" that\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" gives\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" me\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f2137487d2aa3a1f180cbf07eb\",\"object\":\"chat.completion.chunk\",\"created\":1791169267,\"model\":\"openai-gpt-54-mini\"Line truncated
|
||||
}
|
||||
},
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"openai-gpt-54-mini\",\"messages\":[{\"role\":\"system\",\"content\":\"Use the provided tool for private data. After receiving the result, give only the requested number; do not call the tool again.\"},{\"role\":\"user\",\"content\":\"Look up conversion rate for code ZEBRA. Then multiply that rate by 17 and add 9. You must use lookup_rate before answering.\"},{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_onp7EArhOgXu0hGRF6Y5WHLu\",\"type\":\"function\",\"function\":{\"name\":\"lookup_rate\",\"arguments\":\"{\\\"code\\\":\\\"ZEBRA\\\"}\"}}],\"reasoning_details\":[{\"type\":\"reasoning.encrypted\",\"data\":\"gAAAAABqwxLxEN4vtmI2WcZ_aDDttdmPwAHgnV2gLZBo_f_mmTdGm4oZzE2JVzcj72AeXHyABmmo2VQN4nXaZK9GSSUZRlYL8mECMxKTj9AMgL8zlnuN5WDexxU-e9SduGP36RN9nH56-go4dz8eu5DEMvMf_TMoTnxz5AnC_UWbty63Vp8jEgkD-DoRjd0cg9LjthP_FLyMvP2Wj9qMJxEuO7Mw2_Pu4I3YeChnygLvmRfRR2QkamL5vjb9yHkl0Lb502vEGB2DW_czNEpHxisifvwRBjA7vk0mbn2dlhiR80aNHO71hC-QqrtUfPXx2HIbVLfbPdJf0saI0wD7ZuCJSQCBfB7fMCnj2ZLQeXa67lgXwsZDLBg4HmSJFvsMinx1IHIjUk7iebsKvmYx40cjqpXL3wj7htZWk2hO9OyGGUwlRsn5THdhTsgwg2SPbuHxb-sLPQnEFZ7bRp5lsVm31X2dlHDa1uZ7KLJZyy9g2CLIKsBwFFoCK7jY3HBXfL21ac5TAkOzVmz-XKl6OMPSl-PSdByOO15uHHpyOcJvJvuaea5Tj1nihtuDlhUP5EQPi7MiWpJMFo9AhDCafAbaQOEF5W8AQPeb_GXvPTzhySRAC8PxrhraEcZ4fjpjLqkv6mi_A1YHwbHEHHWjcK5VEKc3dadlIM_s6djclFBocVXrvnQQElVhWBDM-RtK9sgR07BFj5LVk6fYvg0b6gQnbDuQH18jhtPoj0SX0lN921XEQ1ebMCWGLANND2ew_wyNShYouJohefLULicWG57xh_yV1KEG1ufBedq2CPvCHA9Hm5UssbeJx5yBriyUA2Yh4D7j2UBT_KDWEHydDLQ4mWEyLTfQn0ZB3ZOqkU79z3HpK2w_VHUnkl5nEYEU2bmF5lsG33B4gtbQIBtZT76-fizXsvVZx__taOWXg96VMi3CD3DY0TS76B4U92KFmAFJ4aeiM8bkPuzf1Qd202EWE39CotUDoxAM6mzQu0NObTDnGQE776P6kzUoIKUmP8sDwYG5xot8ZTuXcBYysvj4-pFC_fvqMhsdfgonbke78SIjHtmePsOkfHBnCjSSUFKEbaM0nm8jJ6nYVwiYFuXBKD31QD462TAC7ORVIn32sWSgV2t3Sd7vq4ws2Yy7nUoILRAt_NYQUEXt7_R8J5YWj1L6Ruagk7Vtt-CAWxT6FhVyU4JhMb6-tJrYHgdmtunYrjpHBiOVdQR25aOmLbc_WlDvpO4azcRazpgkASAjPaaDycYceKcheiyUDBgFrvcSYrS1fJb6YZrTzOKw1Ztd0YsklS4nc3jffLNLrBQVvnkajj0OHjGcW8wkP93TCMJyt8tfIH0Rd5hIZLY5EqUWj9yZgXO7CuDKQZIEI0oZXef3mjfQqH8Q9rZsSgS3DI3mCF3CN003R_ZKKLGWkG8VzwlvdocNxaV_Z-ujp_O0YMyOcmEoTJI-j3JP3nefNboyP7EWND6VWDjJbqg64dvu0PK0EW5L0lnAu0l-WVb2qmXLYao_7bOlD8JLFZOyUgHAWmetmnm0NuxzevJEVBkNUu1jQatPzf2Jzf9SGKM_3bM_z0TM5McCZ2Pikzwp96QlaiEEWV_j2g02PT5Y3td-lfpoKxoFD5tltGNY9TlPzK-4a9Iz0hloiCprxWMLGKw2JzctrPF1xr42PKGNgPE84xAQ3sQ4mQ==\",\"id\":\"rs_014406f0f45e19c6016ac312f01d2487d2a5f2bdb7fbc42f76\",\"format\":\"openai-responses-v1\",\"index\":0}],\"reasoning_content\":\"**Calculating private data**\\n\\nI need to follow the developer's instructions and use the provided tool to handle private data. First, I should look up the rate for \\\"ZEBRA\\\" before I answer. After that, I’ll multiply the rate by 17 and then add 9 to get the required number. It’s important to give only the requested number and avoid making another tool call. I’ll likely use the commentary channel for this tool call.\\n\\n__ENCRYPTED_REASONING__id=rs_014406f0f45e19c6016ac312f01d2487d2a5f2bdb7fbc42f76\\ngAAAAABqwxLxEN4vtmI2WcZ_aDDttdmPwAHgnV2gLZBo_f_mmTdGm4oZzE2JVzcj72AeXHyABmmo2VQN4nXaZK9GSSUZRlYL8mECMxKTj9AMgL8zlnuN5WDexxU-e9SduGP36RN9nH56-go4dz8eu5DEMvMf_TMoTnxz5AnC_UWbty63Vp8jEgkD-DoRjd0cg9LjthP_FLyMvP2Wj9qMJxEuO7Mw2_Pu4I3YeChnygLvmRfRR2QkamL5vjb9yHkl0Lb502vEGB2DW_czNEpHxisifvwRBjA7vk0mbn2dlhiR80aNHO71hC-QqrtUfPXx2HIbVLfbPdJf0saI0wD7ZuCJSQCBfB7fMCnj2ZLQeXa67lgXwsZDLBg4HmSJFvsMinx1IHIjUk7iebsKvmYx40cjqpXL3wj7htZWk2hO9OyGGUwlRsn5THdhTsgwg2SPbuHxb-sLPQnEFZ7bRp5lsVm31X2dlHDa1uZ7KLJZyy9g2CLIKsBwFFoCK7jY3HBXfL21ac5TAkOzVmz-XKl6OMPSl-PSdByOO15uHHpyOcJvJvuaea5Tj1nihtuDlhUP5EQPi7MiWpJMFo9AhDCafAbaQOEF5W8AQPeb_GXvPTzhySRAC8PxrhraEcZ4fjpjLqkv6mi_A1YHwbHEHHWjcK5VEKc3dadlIM_s6djclFBocVXrvnQQElVhWBDM-RtK9sgR07BFj5LVk6fYvg0b6gQnbDuQH18jhtPoj0SX0lN921XEQ1ebMCWGLANND2ew_wyNShYouJohefLULicWG57xh_yV1KEG1ufBedq2CPvCHA9Hm5UssbeJx5yBriyUA2Yh4D7j2UBT_KDWEHydDLQ4mWEyLTfQn0ZB3ZOqkU79z3HpK2w_VHUnkl5nEYEU2bmF5lsG33B4gtbQIBtZT76-fizXsvVZx__taOWXg96VMi3CD3DY0TS76B4U92KFmAFJ4aeiM8bkPuzf1Qd202EWE39CotUDoxAM6mzQu0NObTDnGQE776P6kzUoIKUmP8sDwYG5xot8ZTuXcBYysvj4-pFC_fvqMhsdfgonbke78SIjHtmePsOkfHBnCjSSUFKEbaM0nm8jJ6nYVwiYFuXBKD31QD462TAC7ORVIn32sWSgV2t3Sd7vq4ws2Yy7nUoILRAt_NYQUEXt7_R8J5YWj1L6Ruagk7Vtt-CAWxT6FhVyU4JhMb6-tJrYHgdmtunYrjpHBiOVdQR25aOmLbc_WlDvpO4azcRazpgkASAjPaaDycYceKcheiyUDBgFrvcSYrS1fJb6YZrTzOKw1Ztd0YsklS4nc3jffLNLrBQVvnkajj0OHjGcW8wkP93TCMJyt8tfIH0Rd5hIZLY5EqUWj9yZgXO7CuDKQZIEI0oZXef3mjfQqH8Q9rZsSgS3DI3mCF3CN003R_ZKKLGWkG8VzwlvdocNxaV_Z-ujp_O0YMyOcmEoTJI-j3JP3nefNboyP7EWND6VWDjJbqg64dvu0PK0EW5L0lnAu0l-WVb2qmXLYao_7bOlD8JLFZOyUgHAWmetmnm0NuxzevJEVBkNUu1jQatPzf2Jzf9SGKM_3bM_z0TM5McCZ2Pikzwp96QlaiEEWV_j2g02PT5Y3td-lfpoKxoFD5tltGNY9TlPzK-4a9Iz0hloiCprxWMLGKw2JzctrPF1xr42PKGNgPE84xAQ3sQ4mQ==\"},{\"role\":\"tool\",\"tool_call_id\":\"call_onp7EArhOgXu0hGRF6Y5WHLu\",\"content\":\"{\\\"code\\\":\\\"ZEBRA\\\",\\\"rate\\\":23}\"},{\"role\":\"assistant\",\"content\":\"400\",\"reasoning_details\":[{\"type\":\"reasoning.encrypted\",\"data\":\"gAAAAABqwxL0Nl6Jl5EZuOLine truncated
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\"**Calculating a simple addition**\\n\\nThe\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" user\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" wants\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" me\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" to\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" add\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" 7\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" to\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" the\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" previous\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" final\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" answer\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\",\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" which\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" was\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" 400\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\".\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"choices\":[{\"index\":0,\"delta\":{\"reasoning_content\":\" This\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"resp_014406f0f45e19c6016ac312f49b9c87d2afc60121b8910612\",\"object\":\"chat.completion.chunk\",\"created\":1791169269,\"model\":\"openai-gpt-54-mini\",\"Line truncated
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"tags": [
|
||||
"prefix:venice-chat",
|
||||
"provider:venice",
|
||||
"protocol:venice-chat",
|
||||
"text",
|
||||
"reasoning",
|
||||
"toggle"
|
||||
],
|
||||
"name": "venice-chat/qwen-disables-reasoning",
|
||||
"recordedAt": "2026-10-05T02:59:04.614Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"qwen3-6-27b\",\"messages\":[{\"role\":\"user\",\"content\":\"What is 23 multiplied by 17 plus 9? Reply with just the number.\"}],\"stream\":true,\"stream_options\":{\"include_usage\":true},\"max_completion_tokens\":4096,\"reasoning\":{\"enabled\":false},\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream; charset=utf-8"
|
||||
},
|
||||
"body": "data: {\"service_tier\":null,\"id\":\"chatcmpl-RxYUpStKYw7YgEZcXjsb2dOt\",\"object\":\"chat.completion.chunk\",\"created\":1791169144,\"model\":\"qwen3-6-27b\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RxYUpStKYw7YgEZcXjsb2dOt\",\"object\":\"chat.completion.chunk\",\"created\":1791169144,\"model\":\"qwen3-6-27b\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RxYUpStKYw7YgEZcXjsb2dOt\",\"object\":\"chat.completion.chunk\",\"created\":1791169144,\"model\":\"qwen3-6-27b\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"4\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RxYUpStKYw7YgEZcXjsb2dOt\",\"object\":\"chat.completion.chunk\",\"created\":1791169144,\"model\":\"qwen3-6-27b\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"0\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RxYUpStKYw7YgEZcXjsb2dOt\",\"object\":\"chat.completion.chunk\",\"created\":1791169144,\"model\":\"qwen3-6-27b\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"0\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RxYUpStKYw7YgEZcXjsb2dOt\",\"object\":\"chat.completion.chunk\",\"created\":1791169144,\"model\":\"qwen3-6-27b\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":\"\",\"reasoning_content\":null,\"tool_calls\":null},\"logprobs\":null,\"finish_reason\":\"stop\"}]}\n\ndata: {\"service_tier\":\"default\",\"id\":\"chatcmpl-RxYUpStKYw7YgEZcXjsb2dOt\",\"object\":\"chat.completion.chunk\",\"created\":1791169144,\"model\":\"qwen3-6-27b\",\"choices\":[],\"usage\":{\"prompt_tokens\":32,\"completion_tokens\":4,\"total_tokens\":36},\"cost\":{\"usd\":0.0000234,\"diem\":0}}\n\ndata: [DONE]\n\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"tags": [
|
||||
"prefix:venice-chat",
|
||||
"provider:venice",
|
||||
"protocol:venice-chat",
|
||||
"error"
|
||||
],
|
||||
"name": "venice-chat/surfaces-venice-model-errors",
|
||||
"recordedAt": "2026-10-05T02:59:11.768Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://api.venice.ai/api/v1/chat/completions",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"model\":\"no-such-model-xyz\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}],\"stream\":true,\"stream_options\":{\"include_usage\":true},\"venice_parameters\":{\"include_venice_system_prompt\":false}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 404,
|
||||
"headers": {
|
||||
"content-type": "application/json; charset=utf-8"
|
||||
},
|
||||
"body": "{\"error\":\"Specified model not found: no-such-model-xyz. Did you mean: z-ai-glm-5-3, z-ai-glm-5-3-flash, z-ai-glm-5-turbo?\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect, Layer, Stream } from "effect"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { Image, ImageClient, Media } from "../src/index.js"
|
||||
import { BlackForestLabs, Fal, Google, OpenAI, Replicate, Stability, XAI, ZAI } from "../src/providers.js"
|
||||
import { it } from "./lib/effect.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Effect, Fiber, Layer, Ref } from "effect"
|
||||
import * as TestClock from "effect/testing/TestClock"
|
||||
import { HttpClient, HttpClientError, HttpClientRequest, HttpClientResponse } from "effect/http"
|
||||
import { HttpClient, HttpClientError, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
|
||||
import { LLMClient, RequestExecutor } from "../../src/route.js"
|
||||
import type { Service as LLMClientService } from "../../src/route/client.js"
|
||||
import type { Service as RequestExecutorService } from "../../src/route/executor.js"
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect } from "bun:test"
|
||||
import { NodeFileSystem } from "@effect/platform-node"
|
||||
import { Effect, Ref, Schema } from "effect"
|
||||
import { FileSystem } from "effect"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { AIError, Media, Message } from "../src/index.js"
|
||||
import { it } from "./lib/effect.js"
|
||||
import { dynamicResponse, scriptedResponses } from "./lib/http.js"
|
||||
|
||||
@@ -3,7 +3,7 @@ import { mkdtemp, rm } from "node:fs/promises"
|
||||
import { tmpdir } from "node:os"
|
||||
import { join } from "node:path"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { AIError, LLMEvent, Media, SpeechEvent, TranscriptionEvent } from "../src/index.js"
|
||||
import { RequestExecutor } from "../src/route.js"
|
||||
import { AI } from "../src/promise.js"
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { LLM } from "../../src/index.js"
|
||||
import { Venice } from "../../src/providers.js"
|
||||
|
||||
LLM.request({
|
||||
model: Venice.chat("qwen3-6-27b"),
|
||||
providerOptions: { reasoningEffort: "high", reasoning: { summary: "concise" }, veniceParameters: { includeVeniceSystemPrompt: false } },
|
||||
})
|
||||
LLM.request({
|
||||
model: Venice.configure({ providerOptions: { reasoningEffort: "future-effort" } }).model("future-model"),
|
||||
providerOptions: { reasoning: { enabled: false }, promptCacheRetention: "future-retention", parallelToolCalls: false },
|
||||
})
|
||||
LLM.request({
|
||||
model: Venice.chat("qwen3-6-27b"),
|
||||
// @ts-expect-error Thinking toggles are boolean.
|
||||
providerOptions: { reasoning: { enabled: "false" } },
|
||||
})
|
||||
LLM.request({
|
||||
model: Venice.chat("qwen3-6-27b"),
|
||||
// @ts-expect-error Venice uses nested reasoning, not Anthropic thinking controls.
|
||||
providerOptions: { thinking: { type: "disabled" } },
|
||||
})
|
||||
LLM.request({
|
||||
model: Venice.chat("qwen3-6-27b"),
|
||||
// @ts-expect-error Venice's system-prompt toggle is boolean.
|
||||
providerOptions: { veniceParameters: { includeVeniceSystemPrompt: "false" } },
|
||||
})
|
||||
@@ -7,67 +7,6 @@ const configuration = (provider: string, message: string) =>
|
||||
expect.objectContaining({ _tag: "ProviderConfiguration", provider, message })
|
||||
|
||||
describe("provider package entrypoints", () => {
|
||||
test("semantic API aliases expose the same contract", async () => {
|
||||
const modules = await Promise.all([
|
||||
import("@opencode/ai/providers/openai"),
|
||||
import("@opencode/ai/providers/openai/responses"),
|
||||
import("@opencode/ai/providers/openai/chat"),
|
||||
import("@opencode/ai/providers/anthropic"),
|
||||
import("@opencode/ai/providers/anthropic-compatible"),
|
||||
import("@opencode/ai/providers/openai-compatible"),
|
||||
import("@opencode/ai/providers/openai-compatible/responses"),
|
||||
import("@opencode/ai/providers/amazon-bedrock"),
|
||||
import("@opencode/ai/providers/azure"),
|
||||
import("@opencode/ai/providers/azure/responses"),
|
||||
import("@opencode/ai/providers/azure/chat"),
|
||||
import("@opencode/ai/providers/google"),
|
||||
import("@opencode/ai/providers/google-vertex"),
|
||||
import("@opencode/ai/providers/google-vertex/gemini"),
|
||||
import("@opencode/ai/providers/google-vertex/chat"),
|
||||
import("@opencode/ai/providers/google-vertex/responses"),
|
||||
import("@opencode/ai/providers/google-vertex/messages"),
|
||||
import("@opencode/ai/providers/openrouter"),
|
||||
import("@opencode/ai/providers/xai"),
|
||||
import("@opencode/ai/providers/amazon-bedrock/mantle"),
|
||||
import("@opencode/ai/providers/amazon-bedrock/mantle/chat"),
|
||||
import("@opencode/ai/providers/amazon-bedrock/mantle/responses"),
|
||||
import("@opencode/ai/providers/togetherai"),
|
||||
import("@opencode/ai/providers/cerebras"),
|
||||
import("@opencode/ai/providers/deepinfra"),
|
||||
import("@opencode/ai/providers/groq"),
|
||||
import("@opencode/ai/providers/baseten"),
|
||||
import("@opencode/ai/providers/deepseek"),
|
||||
import("@opencode/ai/providers/fireworks"),
|
||||
import("@opencode/ai/providers/cloudflare-ai-gateway"),
|
||||
import("@opencode/ai/providers/cloudflare-workers-ai"),
|
||||
import("@opencode/ai/providers/minimax"),
|
||||
import("@opencode/ai/providers/minimax/messages"),
|
||||
import("@opencode/ai/providers/minimax/chat"),
|
||||
import("@opencode/ai/providers/minimax/responses"),
|
||||
import("@opencode/ai/providers/moonshot"),
|
||||
import("@opencode/ai/providers/moonshot/chat"),
|
||||
import("@opencode/ai/providers/moonshot/messages"),
|
||||
import("@opencode/ai/providers/moonshot/responses"),
|
||||
import("@opencode/ai/providers/zai"),
|
||||
import("@opencode/ai/providers/zai/chat"),
|
||||
import("@opencode/ai/providers/zai-coding-plan"),
|
||||
import("@opencode/ai/providers/zai-coding-plan/chat"),
|
||||
import("@opencode/ai/providers/zai-coding-plan/messages"),
|
||||
import("@opencode/ai/providers/zai-coding-plan/responses"),
|
||||
import("@opencode/ai/providers/alibaba"),
|
||||
import("@opencode/ai/providers/alibaba/chat"),
|
||||
import("@opencode/ai/providers/alibaba/messages"),
|
||||
import("@opencode/ai/providers/alibaba/responses"),
|
||||
])
|
||||
|
||||
for (const module of modules) expect(module.model).toBeFunction()
|
||||
expect(modules[0].model).toBe(modules[1].model)
|
||||
expect(modules[8].model).toBe(modules[9].model)
|
||||
expect(modules[12].model).toBe(modules[13].model)
|
||||
expect(modules[19].model).toBe(modules[21].model)
|
||||
expect(modules[19].model).not.toBe(modules[20].model)
|
||||
})
|
||||
|
||||
test("maps Alibaba API entrypoints onto explicit regional routes", async () => {
|
||||
const modules = await Promise.all([
|
||||
import("@opencode/ai/providers/alibaba"),
|
||||
@@ -75,7 +14,6 @@ describe("provider package entrypoints", () => {
|
||||
import("@opencode/ai/providers/alibaba/messages"),
|
||||
import("@opencode/ai/providers/alibaba/responses"),
|
||||
])
|
||||
expect(modules[0].model).toBe(modules[1].model)
|
||||
const settings = {
|
||||
region: "eu-central-1",
|
||||
workspaceID: "llm-fixture",
|
||||
@@ -103,7 +41,6 @@ describe("provider package entrypoints", () => {
|
||||
import("@opencode/ai/providers/moonshot/messages"),
|
||||
import("@opencode/ai/providers/moonshot/responses"),
|
||||
])
|
||||
expect(modules[0].model).toBe(modules[1].model)
|
||||
const settings = {
|
||||
apiKey: "fixture",
|
||||
baseURL: "https://gateway.example/v1",
|
||||
@@ -147,7 +84,6 @@ describe("provider package entrypoints", () => {
|
||||
import("@opencode/ai/providers/minimax/chat"),
|
||||
import("@opencode/ai/providers/minimax/responses"),
|
||||
])
|
||||
expect(modules[0].model).toBe(modules[1].model)
|
||||
const settings = {
|
||||
apiKey: "fixture",
|
||||
baseURL: "https://gateway.example/v1",
|
||||
@@ -174,8 +110,6 @@ describe("provider package entrypoints", () => {
|
||||
import("@opencode/ai/providers/zai-coding-plan/messages"),
|
||||
import("@opencode/ai/providers/zai-coding-plan/responses"),
|
||||
])
|
||||
expect(modules[0].model).toBe(modules[1].model)
|
||||
expect(modules[2].model).toBe(modules[3].model)
|
||||
const routes = [
|
||||
"zai-chat",
|
||||
"zai-chat",
|
||||
@@ -458,7 +392,6 @@ describe("provider package entrypoints", () => {
|
||||
|
||||
test("selects Vertex entrypoints with the same model contract", async () => {
|
||||
const GoogleVertex = await import("@opencode/ai/providers/google-vertex")
|
||||
const GoogleVertexGemini = await import("@opencode/ai/providers/google-vertex/gemini")
|
||||
const GoogleVertexChat = await import("@opencode/ai/providers/google-vertex/chat")
|
||||
const GoogleVertexResponses = await import("@opencode/ai/providers/google-vertex/responses")
|
||||
const GoogleVertexMessages = await import("@opencode/ai/providers/google-vertex/messages")
|
||||
@@ -483,7 +416,6 @@ describe("provider package entrypoints", () => {
|
||||
project: "vertex-project",
|
||||
})
|
||||
|
||||
expect(GoogleVertexGemini.model).toBe(GoogleVertex.model)
|
||||
expect(gemini.route.id).toBe("google-vertex-gemini")
|
||||
expect(gemini.route.protocol).toBe("gemini")
|
||||
expect(gemini.route.endpoint.baseURL).toBe("https://aiplatform.googleapis.com/v1/publishers/google")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import { ConfigProvider, Effect } from "effect"
|
||||
import { Headers } from "effect/http"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Auth, LLM, LLMClient, LLMRequest, Message, ReasoningPart, ToolDefinition } from "../../src/index.js"
|
||||
import { Alibaba } from "../../src/providers.js"
|
||||
import { compileRequest } from "../../src/route/client.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import {
|
||||
CacheHint,
|
||||
LLM,
|
||||
@@ -431,42 +431,115 @@ describe("Anthropic Messages route", () => {
|
||||
(yield* compileRequest(
|
||||
LLM.request({
|
||||
model: opus48,
|
||||
messages: [Message.user("Before."), Message.system("One."), Message.system("Two.")],
|
||||
messages: [
|
||||
Message.user("Start."),
|
||||
Message.assistant("One."),
|
||||
Message.system("Update."),
|
||||
Message.assistant("Two."),
|
||||
],
|
||||
cache: "none",
|
||||
}),
|
||||
)).body.messages,
|
||||
).toEqual([
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{ type: "text", text: "Before." },
|
||||
{ type: "text", text: "<system-update>\nOne.\n</system-update>" },
|
||||
{ type: "text", text: "<system-update>\nTwo.\n</system-update>" },
|
||||
],
|
||||
},
|
||||
{ role: "user", content: [{ type: "text", text: "Start." }] },
|
||||
{ role: "assistant", content: [{ type: "text", text: "One." }] },
|
||||
{ role: "user", content: [{ type: "text", text: "<system-update>\nUpdate.\n</system-update>" }] },
|
||||
{ role: "assistant", content: [{ type: "text", text: "Two." }] },
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("keeps a terminal Vertex system update in the tool-result turn", () =>
|
||||
it.effect("moves system updates to the next assistant turn and sends consecutive updates together", () =>
|
||||
Effect.gen(function* () {
|
||||
const lower = (messages: ReadonlyArray<Message>) =>
|
||||
compileRequest(LLM.request({ model: opus48, messages: [...messages], cache: "none" })).pipe(
|
||||
Effect.map((prepared) => prepared.body.messages),
|
||||
)
|
||||
const system = (text: string) => ({ role: "system", content: [{ type: "text", text, cache_control: undefined }] })
|
||||
const user = (text: string) => ({ role: "user", content: [{ type: "text", text }] })
|
||||
const assistant = (text: string) => ({ role: "assistant", content: [{ type: "text", text }] })
|
||||
|
||||
expect(
|
||||
yield* lower([
|
||||
Message.user("Fix it."),
|
||||
Message.assistant("Done."),
|
||||
Message.system("Update."),
|
||||
Message.user("Next."),
|
||||
]),
|
||||
).toEqual([user("Fix it."), assistant("Done."), user("Next."), system("Update.")])
|
||||
expect(yield* lower([Message.user("Before."), Message.system("One."), Message.system("Two.")])).toEqual([
|
||||
user("Before."),
|
||||
system("One."),
|
||||
system("Two."),
|
||||
])
|
||||
expect(
|
||||
yield* lower([
|
||||
Message.user("Fix it."),
|
||||
Message.assistant("Done."),
|
||||
Message.system("One."),
|
||||
Message.user("Next."),
|
||||
Message.system("Two."),
|
||||
Message.assistant("After."),
|
||||
]),
|
||||
).toEqual([
|
||||
user("Fix it."),
|
||||
assistant("Done."),
|
||||
user("Next."),
|
||||
system("One."),
|
||||
system("Two."),
|
||||
assistant("After."),
|
||||
])
|
||||
expect(
|
||||
yield* lower([
|
||||
Message.user("Use the tool."),
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: {} })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: "Done." }),
|
||||
Message.system("Update."),
|
||||
Message.user("Also check tests."),
|
||||
]),
|
||||
).toEqual([
|
||||
user("Use the tool."),
|
||||
{ role: "assistant", content: [{ type: "tool_use", id: "call_1", name: "lookup", input: {} }] },
|
||||
{ role: "user", content: [{ type: "tool_result", tool_use_id: "call_1", content: '"Done."' }] },
|
||||
user("Also check tests."),
|
||||
system("Update."),
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("keeps wrapped system updates in place for models without native system updates", () =>
|
||||
Effect.gen(function* () {
|
||||
const prepared = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: vertexOpus48,
|
||||
model,
|
||||
messages: [
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: {} })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: "Done." }),
|
||||
Message.system("Operator update."),
|
||||
Message.user("Fix it."),
|
||||
Message.assistant("Done."),
|
||||
Message.system("Update."),
|
||||
Message.user("Next."),
|
||||
],
|
||||
cache: "none",
|
||||
}),
|
||||
)
|
||||
|
||||
expect(prepared.body.messages).toEqual([
|
||||
{
|
||||
role: "assistant",
|
||||
content: [{ type: "tool_use", id: "call_1", name: "lookup", input: {} }],
|
||||
},
|
||||
{ role: "user", content: [{ type: "text", text: "Fix it." }] },
|
||||
{ role: "assistant", content: [{ type: "text", text: "Done." }] },
|
||||
{ role: "user", content: [{ type: "text", text: "<system-update>\nUpdate.\n</system-update>" }] },
|
||||
{ role: "user", content: [{ type: "text", text: "Next." }] },
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("sends Vertex system updates after local tool results as native system messages", () =>
|
||||
Effect.gen(function* () {
|
||||
const toolTurn = [
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: {} })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: "Done." }),
|
||||
Message.system("Operator update."),
|
||||
]
|
||||
const lowered = [
|
||||
{ role: "assistant", content: [{ type: "tool_use", id: "call_1", name: "lookup", input: {} }] },
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
@@ -477,55 +550,23 @@ describe("Anthropic Messages route", () => {
|
||||
is_error: undefined,
|
||||
cache_control: undefined,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
text: "<system-update>\nOperator update.\n</system-update>",
|
||||
cache_control: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
}),
|
||||
)
|
||||
{ role: "system", content: [{ type: "text", text: "Operator update.", cache_control: undefined }] },
|
||||
]
|
||||
|
||||
it.effect("preserves folded tool-result system updates across multi-turn Vertex history", () =>
|
||||
Effect.gen(function* () {
|
||||
const prepared = yield* compileRequest(
|
||||
const terminal = yield* compileRequest(LLM.request({ model: vertexOpus48, messages: toolTurn, cache: "none" }))
|
||||
const history = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: vertexOpus48,
|
||||
messages: [
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: {} })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: "Done." }),
|
||||
Message.system("Operator update."),
|
||||
Message.assistant("Acknowledged."),
|
||||
Message.user("Next step."),
|
||||
],
|
||||
messages: [...toolTurn, Message.assistant("Acknowledged."), Message.user("Next step.")],
|
||||
cache: "none",
|
||||
}),
|
||||
)
|
||||
|
||||
expect(prepared.body.messages).toEqual([
|
||||
{
|
||||
role: "assistant",
|
||||
content: [{ type: "tool_use", id: "call_1", name: "lookup", input: {} }],
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "tool_result",
|
||||
tool_use_id: "call_1",
|
||||
content: '"Done."',
|
||||
is_error: undefined,
|
||||
cache_control: undefined,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
text: "<system-update>\nOperator update.\n</system-update>",
|
||||
cache_control: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
expect(terminal.body.messages).toEqual(lowered)
|
||||
expect(history.body.messages).toEqual([
|
||||
...lowered,
|
||||
{ role: "assistant", content: [{ type: "text", text: "Acknowledged." }] },
|
||||
{ role: "user", content: [{ type: "text", text: "Next step." }] },
|
||||
])
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { EventStreamCodec } from "@smithy/eventstream-codec"
|
||||
import { fromUtf8, toUtf8 } from "@smithy/util-utf8"
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect, Ref, Schema, Stream } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { Effect, Encoding, Ref, Schema, Stream } from "effect"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import {
|
||||
Media,
|
||||
CacheHint,
|
||||
@@ -866,7 +865,7 @@ describe("Bedrock Converse route", () => {
|
||||
reason: { _tag: "InvalidProviderOutput", classification: "incomplete-stream" },
|
||||
message: `Incomplete Bedrock Converse event-stream frame: ${partial.length} buffered bytes remain at end of stream`,
|
||||
})
|
||||
expect(error.reason.body).toBe(Base64.encode(partial))
|
||||
expect(error.reason.body).toBe(Encoding.encodeBase64(partial))
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { LLM, Message } from "../../src/index.js"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { LLM, LLMEvent, LLMRequest, Message, ToolDefinition } from "../../src/index.js"
|
||||
import { AmazonBedrockMantle } from "../../src/providers.js"
|
||||
import { model } from "../../src/providers/amazon-bedrock/mantle.js"
|
||||
import { OpenResponses } from "../../src/protocols/open-responses.js"
|
||||
import { compileRequest, LLMClient } from "../../src/route/client.js"
|
||||
import { it } from "../lib/effect.js"
|
||||
@@ -19,14 +18,14 @@ const credentials = {
|
||||
}
|
||||
|
||||
describe("Amazon Bedrock Mantle provider", () => {
|
||||
it.effect("uses Responses by default and exposes Chat explicitly", () =>
|
||||
it.effect("uses Responses by default and exposes Chat and Messages explicitly", () =>
|
||||
Effect.gen(function* () {
|
||||
const provider = AmazonBedrockMantle.configure({ credentials })
|
||||
expect(provider.model).toBe(provider.responses)
|
||||
expect(AmazonBedrockMantle.model).toBe(AmazonBedrockMantle.responsesModel)
|
||||
expect(model).toBe(AmazonBedrockMantle.responsesModel)
|
||||
expect(provider.model("openai.gpt-oss-120b").route.transport).toBe(OpenResponses.httpTransport)
|
||||
const chat = yield* compileRequest(LLM.request({ model: provider.chat("openai.gpt-oss-120b"), prompt: "Hi" }))
|
||||
const messages = yield* compileRequest(
|
||||
LLM.request({ model: provider.messages("anthropic.claude-opus-4-8"), prompt: "Hi", cache: "none" }),
|
||||
)
|
||||
const responses = yield* compileRequest(
|
||||
LLM.request({ model: provider.model("openai.gpt-oss-120b"), prompt: "Hi" }),
|
||||
)
|
||||
@@ -36,6 +35,11 @@ describe("Amazon Bedrock Mantle provider", () => {
|
||||
protocol: "openai-chat",
|
||||
body: { model: "openai.gpt-oss-120b" },
|
||||
})
|
||||
expect(messages).toMatchObject({
|
||||
route: "bedrock-mantle-messages",
|
||||
protocol: "anthropic-messages",
|
||||
body: { model: "anthropic.claude-opus-4-8", stream: true },
|
||||
})
|
||||
expect(responses).toMatchObject({
|
||||
route: "bedrock-mantle-responses",
|
||||
protocol: "open-responses",
|
||||
@@ -43,43 +47,77 @@ describe("Amazon Bedrock Mantle provider", () => {
|
||||
})
|
||||
expect(provider.model("openai.gpt-oss-120b").route.providerMetadataKey).toBe("mantle")
|
||||
expect(provider.chat("openai.gpt-oss-120b").route.providerMetadataKey).toBe("mantle")
|
||||
expect(provider.messages("anthropic.claude-opus-4-8").route.providerMetadataKey).toBe("mantle")
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("preserves configured top-p generation defaults for Chat and Responses", () =>
|
||||
it.effect("preserves configured top-p generation defaults for Chat, Messages, and Responses", () =>
|
||||
Effect.gen(function* () {
|
||||
const settings = { apiKey: "test-key", topP: 0.8 }
|
||||
const chat = yield* compileRequest(
|
||||
LLM.request({ model: AmazonBedrockMantle.chatModel("openai.gpt-oss-safeguard-20b", settings), prompt: "Hi" }),
|
||||
)
|
||||
const messages = yield* compileRequest(
|
||||
LLM.request({ model: AmazonBedrockMantle.messagesModel("anthropic.claude-opus-4-8", settings), prompt: "Hi" }),
|
||||
)
|
||||
const responses = yield* compileRequest(
|
||||
LLM.request({ model: AmazonBedrockMantle.responsesModel("openai.gpt-oss-120b", settings), prompt: "Hi" }),
|
||||
)
|
||||
|
||||
expect(chat.body.top_p).toBe(0.8)
|
||||
expect(messages.body.top_p).toBe(0.8)
|
||||
expect(responses.body.top_p).toBe(0.8)
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("uses the Mantle endpoint and signing service", () =>
|
||||
it.effect("uses the Mantle endpoint and signing service across Responses and Messages", () =>
|
||||
Effect.gen(function* () {
|
||||
const seen: Array<{ readonly url: string; readonly authorization: string | undefined }> = []
|
||||
const model = AmazonBedrockMantle.configure({ credentials, region: "us-west-1" }).responses("openai.gpt-oss-120b")
|
||||
yield* LLMClient.generate(LLM.request({ model, prompt: "Hi" })).pipe(
|
||||
Effect.provide(
|
||||
dynamicResponse((input) =>
|
||||
Effect.gen(function* () {
|
||||
const request = yield* HttpClientRequest.toWeb(input.request)
|
||||
seen.push({ url: request.url, authorization: request.headers.get("authorization") ?? undefined })
|
||||
return input.respond("", { headers: { "content-type": "text/event-stream" } })
|
||||
}),
|
||||
const configured = AmazonBedrockMantle.configure({ credentials, region: "us-west-1" })
|
||||
for (const selected of [
|
||||
configured.responses("openai.gpt-oss-120b"),
|
||||
configured.messages("anthropic.claude-opus-4-8"),
|
||||
]) {
|
||||
yield* LLMClient.generate(LLM.request({ model: selected, prompt: "Hi" })).pipe(
|
||||
Effect.provide(
|
||||
dynamicResponse((input) =>
|
||||
Effect.gen(function* () {
|
||||
const request = yield* HttpClientRequest.toWeb(input.request)
|
||||
seen.push({ url: request.url, authorization: request.headers.get("authorization") ?? undefined })
|
||||
return input.respond("", { headers: { "content-type": "text/event-stream" } })
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
Effect.flip,
|
||||
Effect.flip,
|
||||
)
|
||||
}
|
||||
|
||||
expect(seen.map((item) => item.url)).toEqual([
|
||||
"https://bedrock-mantle.us-west-1.api.aws/v1/responses",
|
||||
"https://bedrock-mantle.us-west-1.api.aws/anthropic/v1/messages",
|
||||
])
|
||||
expect(seen.every((item) => item.authorization?.includes("/us-west-1/bedrock-mantle/aws4_request"))).toBe(true)
|
||||
}).pipe(withProcessEnv({ AWS_BEARER_TOKEN_BEDROCK: undefined })),
|
||||
)
|
||||
|
||||
it.effect("applies inline cache breakpoints on Mantle Messages", () =>
|
||||
Effect.gen(function* () {
|
||||
const model = AmazonBedrockMantle.configure({ apiKey: "test-key" }).messages("anthropic.claude-opus-4-8")
|
||||
const prepared = yield* compileRequest(
|
||||
LLM.request({
|
||||
model,
|
||||
system: "You are concise.",
|
||||
messages: [Message.user("Hello")],
|
||||
cache: "auto",
|
||||
}),
|
||||
)
|
||||
|
||||
expect(seen[0]?.url).toBe("https://bedrock-mantle.us-west-1.api.aws/v1/responses")
|
||||
expect(seen[0]?.authorization).toContain("/us-west-1/bedrock-mantle/aws4_request")
|
||||
expect(prepared.body.system).toEqual([
|
||||
{ type: "text", text: "You are concise.", cache_control: { type: "ephemeral" } },
|
||||
])
|
||||
expect(prepared.body.messages).toEqual([
|
||||
{ role: "user", content: [{ type: "text", text: "Hello", cache_control: { type: "ephemeral" } }] },
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -201,3 +239,198 @@ describe("Amazon Bedrock Mantle recorded", () => {
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
const recordedMessages = recordedTests({
|
||||
prefix: "bedrock-mantle-messages",
|
||||
provider: "amazon-bedrock",
|
||||
protocol: "anthropic-messages",
|
||||
requires: ["AWS_BEARER_TOKEN_BEDROCK"],
|
||||
options: { redact: { allowRequestHeaders: ["anthropic-version", "anthropic-beta"] } },
|
||||
})
|
||||
|
||||
const mantleMessages = (modelID: string) =>
|
||||
AmazonBedrockMantle.configure({
|
||||
apiKey: process.env.AWS_BEARER_TOKEN_BEDROCK ?? "fixture",
|
||||
region: "us-east-1",
|
||||
}).messages(modelID)
|
||||
|
||||
const weatherTool = ToolDefinition.make({
|
||||
name: "get_weather",
|
||||
description: "Get the current weather in a city",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: { city: { type: "string", enum: ["Paris"] } },
|
||||
required: ["city"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
})
|
||||
|
||||
describe("Amazon Bedrock Mantle Messages recorded", () => {
|
||||
recordedMessages.effect.with(
|
||||
"replays signed thinking through a tool loop and native system update",
|
||||
{ tags: ["tool", "tool-loop", "reasoning", "system-update"], metadata: { model: "anthropic.claude-opus-4-8" } },
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const model = mantleMessages("anthropic.claude-opus-4-8")
|
||||
const initial = LLM.request({
|
||||
model,
|
||||
system: "You are a concise assistant.",
|
||||
prompt:
|
||||
"First calculate 37 * 43. Then call get_weather for Paris. After receiving the tool result, state both the product and the weather.",
|
||||
tools: [weatherTool],
|
||||
providerOptions: {
|
||||
thinking: { type: "adaptive", display: "summarized" },
|
||||
effort: "medium",
|
||||
},
|
||||
generation: { maxTokens: 2048 },
|
||||
})
|
||||
const first = yield* LLMClient.generate(initial)
|
||||
expect(first.finishReason.normalized).toBe("tool-calls")
|
||||
expect(first.toolCalls).toMatchObject([{ name: "get_weather", input: { city: "Paris" } }])
|
||||
expect(first.reasoning.length).toBeGreaterThan(0)
|
||||
expect(first.events.some(LLMEvent.is.toolInputDelta)).toBe(true)
|
||||
const reasoningPart = first.message.content.find((part) => part.type === "reasoning")
|
||||
const signature = (reasoningPart?.providerMetadata?.mantle as { readonly signature?: unknown } | undefined)
|
||||
?.signature
|
||||
expect(typeof signature).toBe("string")
|
||||
|
||||
const followUp = LLMRequest.update(initial, {
|
||||
messages: [
|
||||
...initial.messages,
|
||||
first.message,
|
||||
...first.toolCalls.map((call) =>
|
||||
Message.tool({ id: call.id, name: call.name, result: { condition: "sunny", temperatureC: 18 } }),
|
||||
),
|
||||
Message.system("Reply in French in one short sentence."),
|
||||
],
|
||||
})
|
||||
const compiled = yield* compileRequest(followUp)
|
||||
expect(compiled.body.messages[1]?.content[0]).toEqual({
|
||||
type: "thinking",
|
||||
thinking: first.reasoning,
|
||||
signature: signature as string,
|
||||
})
|
||||
expect(compiled.body.messages.at(-1)).toEqual({
|
||||
role: "system",
|
||||
content: [
|
||||
{ type: "text", text: "Reply in French in one short sentence.", cache_control: { type: "ephemeral" } },
|
||||
],
|
||||
})
|
||||
|
||||
const second = yield* LLMClient.generate(followUp)
|
||||
expect(second.finishReason.normalized).toBe("stop")
|
||||
expect(second.text).toContain("1591")
|
||||
expect(second.text).toContain("18")
|
||||
}),
|
||||
120_000,
|
||||
)
|
||||
|
||||
recordedMessages.effect.with(
|
||||
"lowers system updates to wrapped user text on Haiku 4.5 with budget thinking",
|
||||
{ tags: ["reasoning", "system-update"], metadata: { model: "anthropic.claude-haiku-4-5" } },
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const request = LLM.request({
|
||||
model: mantleMessages("anthropic.claude-haiku-4-5"),
|
||||
messages: [Message.user("What is 19 multiplied by 23?"), Message.system("Reply with only the integer.")],
|
||||
providerOptions: {
|
||||
thinking: { type: "enabled", budgetTokens: 1024 },
|
||||
},
|
||||
generation: { maxTokens: 2048 },
|
||||
})
|
||||
const compiled = yield* compileRequest(request)
|
||||
expect(compiled.body.thinking).toEqual({ type: "enabled", budget_tokens: 1024 })
|
||||
expect(compiled.body.messages.some((message) => message.role === "system")).toBe(false)
|
||||
|
||||
const response = yield* LLMClient.generate(request)
|
||||
expect(response.finishReason.normalized).toBe("stop")
|
||||
expect(response.reasoning.length).toBeGreaterThan(0)
|
||||
expect(response.text.trim()).toContain("437")
|
||||
}),
|
||||
120_000,
|
||||
)
|
||||
|
||||
recordedMessages.effect.with(
|
||||
"applies mid-conversation effort updates and thinking block binding on Opus 5.5",
|
||||
{ tags: ["reasoning", "effort-update"], metadata: { model: "anthropic.claude-opus-5-5" } },
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const model = mantleMessages("anthropic.claude-opus-5-5")
|
||||
const firstRequest = LLM.request({
|
||||
model,
|
||||
prompt: "Compute 37 * 43 step by step, then reply with only the integer.",
|
||||
providerOptions: {
|
||||
thinking: { type: "adaptive", display: "summarized" },
|
||||
effort: "high",
|
||||
},
|
||||
generation: { maxTokens: 2048 },
|
||||
})
|
||||
const firstCompiled = yield* compileRequest(firstRequest)
|
||||
expect(firstCompiled.body.thinking).toEqual({
|
||||
type: "adaptive",
|
||||
display: "summarized",
|
||||
block_binding: { prefix_mismatch_behavior: "drop_block" },
|
||||
})
|
||||
|
||||
const first = yield* LLMClient.generate(firstRequest)
|
||||
expect(first.finishReason.normalized).toBe("stop")
|
||||
expect(first.reasoning.length).toBeGreaterThan(0)
|
||||
expect(first.text.replaceAll(",", "")).toContain("1591")
|
||||
|
||||
const secondRequest = LLM.request({
|
||||
model,
|
||||
messages: [
|
||||
...firstRequest.messages,
|
||||
first.message,
|
||||
Message.effort({ effort: "low", previous: "high" }),
|
||||
Message.user("Add 9 to that result. Reply with only the integer."),
|
||||
],
|
||||
providerOptions: {
|
||||
thinking: { type: "adaptive", display: "summarized" },
|
||||
effort: "low",
|
||||
},
|
||||
generation: { maxTokens: 2048 },
|
||||
})
|
||||
const secondCompiled = yield* compileRequest(secondRequest)
|
||||
expect(secondCompiled.body.output_config).toEqual({ effort: "high" })
|
||||
expect(secondCompiled.body.messages.filter((message) => message.role === "system")).toEqual([
|
||||
{ role: "system", content: [], output_config: { effort: "low" } },
|
||||
])
|
||||
|
||||
const second = yield* LLMClient.generate(secondRequest)
|
||||
expect(second.finishReason.normalized).toBe("stop")
|
||||
expect(second.text.replaceAll(",", "")).toContain("1600")
|
||||
}),
|
||||
120_000,
|
||||
)
|
||||
|
||||
recordedMessages.effect.with(
|
||||
"strips unsupported mid-conversation effort updates on Opus 5.0",
|
||||
{ tags: ["reasoning", "effort-update"], metadata: { model: "anthropic.claude-opus-5" } },
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const request = LLM.request({
|
||||
model: mantleMessages("anthropic.claude-opus-5"),
|
||||
messages: [
|
||||
Message.user("What is 12 + 30?"),
|
||||
Message.assistant("42"),
|
||||
Message.effort({ effort: "low", previous: "high" }),
|
||||
Message.user("Add 8 to that result. Reply with only the integer."),
|
||||
],
|
||||
providerOptions: {
|
||||
thinking: { type: "adaptive", display: "summarized" },
|
||||
effort: "low",
|
||||
},
|
||||
generation: { maxTokens: 1024 },
|
||||
})
|
||||
const compiled = yield* compileRequest(request)
|
||||
expect(compiled.body.output_config).toEqual({ effort: "low" })
|
||||
expect(compiled.body.messages.some((message) => message.role === "system")).toBe(false)
|
||||
|
||||
const response = yield* LLMClient.generate(request)
|
||||
expect(response.finishReason.normalized).toBe("stop")
|
||||
expect(response.text.trim()).toContain("50")
|
||||
}),
|
||||
120_000,
|
||||
)
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { ConfigProvider, Effect, Schema } from "effect"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { LLM, LLMEvent } from "../../src/index.js"
|
||||
import { CloudflareAIGateway } from "../../src/providers/cloudflare-ai-gateway.js"
|
||||
import { CloudflareWorkersAI } from "../../src/providers/cloudflare-workers-ai.js"
|
||||
|
||||
Loaded 100 of 702 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user