@linxiraos/pi-ai 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (639) hide show
  1. package/CHANGELOG.md +5066 -0
  2. package/README.md +1195 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth/sqlite-credential-store.d.ts +117 -0
  5. package/dist/types/auth-broker/client.d.ts +93 -0
  6. package/dist/types/auth-broker/discover.d.ts +39 -0
  7. package/dist/types/auth-broker/index.d.ts +7 -0
  8. package/dist/types/auth-broker/refresher.d.ts +25 -0
  9. package/dist/types/auth-broker/remote-store.d.ts +136 -0
  10. package/dist/types/auth-broker/server.d.ts +48 -0
  11. package/dist/types/auth-broker/snapshot-cache.d.ts +17 -0
  12. package/dist/types/auth-broker/types.d.ts +152 -0
  13. package/dist/types/auth-broker/wire-schema-resource.d.ts +53 -0
  14. package/dist/types/auth-broker/wire-schemas.d.ts +5 -0
  15. package/dist/types/auth-gateway/http.d.ts +56 -0
  16. package/dist/types/auth-gateway/index.d.ts +3 -0
  17. package/dist/types/auth-gateway/server.d.ts +36 -0
  18. package/dist/types/auth-gateway/types.d.ts +127 -0
  19. package/dist/types/auth-retry.d.ts +150 -0
  20. package/dist/types/auth-storage.d.ts +1258 -0
  21. package/dist/types/dialect/anthropic.d.ts +15 -0
  22. package/dist/types/dialect/catalog.d.ts +3 -0
  23. package/dist/types/dialect/coercion.d.ts +23 -0
  24. package/dist/types/dialect/deepseek.d.ts +14 -0
  25. package/dist/types/dialect/demotion.d.ts +30 -0
  26. package/dist/types/dialect/examples.d.ts +18 -0
  27. package/dist/types/dialect/factory.d.ts +3 -0
  28. package/dist/types/dialect/fenced-thinking.d.ts +53 -0
  29. package/dist/types/dialect/gemini.d.ts +17 -0
  30. package/dist/types/dialect/gemma.d.ts +15 -0
  31. package/dist/types/dialect/glm.d.ts +9 -0
  32. package/dist/types/dialect/harmony.d.ts +8 -0
  33. package/dist/types/dialect/hermes.d.ts +9 -0
  34. package/dist/types/dialect/history.d.ts +3 -0
  35. package/dist/types/dialect/index.d.ts +11 -0
  36. package/dist/types/dialect/inventory.d.ts +9 -0
  37. package/dist/types/dialect/kimi.d.ts +14 -0
  38. package/dist/types/dialect/minimax.d.ts +3 -0
  39. package/dist/types/dialect/owned-stream.d.ts +4 -0
  40. package/dist/types/dialect/qwen3.d.ts +9 -0
  41. package/dist/types/dialect/rendering.d.ts +54 -0
  42. package/dist/types/dialect/thinking.d.ts +6 -0
  43. package/dist/types/dialect/types.d.ts +68 -0
  44. package/dist/types/dialect/xml.d.ts +9 -0
  45. package/dist/types/error/abort.d.ts +14 -0
  46. package/dist/types/error/auth-classify.d.ts +20 -0
  47. package/dist/types/error/auth.d.ts +27 -0
  48. package/dist/types/error/aws.d.ts +27 -0
  49. package/dist/types/error/classes.d.ts +106 -0
  50. package/dist/types/error/finalize.d.ts +39 -0
  51. package/dist/types/error/flags.d.ts +94 -0
  52. package/dist/types/error/format.d.ts +20 -0
  53. package/dist/types/error/gateway.d.ts +20 -0
  54. package/dist/types/error/index.d.ts +14 -0
  55. package/dist/types/error/oauth.d.ts +43 -0
  56. package/dist/types/error/provider.d.ts +42 -0
  57. package/dist/types/error/rate-limit.d.ts +80 -0
  58. package/dist/types/error/retryable.d.ts +27 -0
  59. package/dist/types/error/validation.d.ts +32 -0
  60. package/dist/types/index.d.ts +51 -0
  61. package/dist/types/provider-details.d.ts +24 -0
  62. package/dist/types/providers/amazon-bedrock.d.ts +39 -0
  63. package/dist/types/providers/anthropic-client.d.ts +106 -0
  64. package/dist/types/providers/anthropic-messages-server-schema.d.ts +937 -0
  65. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  66. package/dist/types/providers/anthropic-wire.d.ts +345 -0
  67. package/dist/types/providers/anthropic.d.ts +261 -0
  68. package/dist/types/providers/aws-credentials.d.ts +48 -0
  69. package/dist/types/providers/aws-eventstream.d.ts +39 -0
  70. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  71. package/dist/types/providers/azure-openai-responses.d.ts +16 -0
  72. package/dist/types/providers/bedrock-mantle.d.ts +13 -0
  73. package/dist/types/providers/claude-code-fingerprint.d.ts +19 -0
  74. package/dist/types/providers/cowork-fetch.d.ts +3 -0
  75. package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
  76. package/dist/types/providers/cursor-pi-args.d.ts +105 -0
  77. package/dist/types/providers/cursor.d.ts +221 -0
  78. package/dist/types/providers/devin.d.ts +12 -0
  79. package/dist/types/providers/error-message.d.ts +25 -0
  80. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  81. package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
  82. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  83. package/dist/types/providers/google-auth.d.ts +24 -0
  84. package/dist/types/providers/google-gemini-cli.d.ts +120 -0
  85. package/dist/types/providers/google-shared.d.ts +203 -0
  86. package/dist/types/providers/google-types.d.ts +155 -0
  87. package/dist/types/providers/google-vertex.d.ts +7 -0
  88. package/dist/types/providers/google.d.ts +4 -0
  89. package/dist/types/providers/grammar.d.ts +1 -0
  90. package/dist/types/providers/kimi.d.ts +27 -0
  91. package/dist/types/providers/mock.d.ts +179 -0
  92. package/dist/types/providers/ollama.d.ts +8 -0
  93. package/dist/types/providers/openai-anthropic-shim.d.ts +35 -0
  94. package/dist/types/providers/openai-chat-server-schema.d.ts +1311 -0
  95. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  96. package/dist/types/providers/openai-chat-wire.d.ts +669 -0
  97. package/dist/types/providers/openai-codex/request-transformer.d.ts +109 -0
  98. package/dist/types/providers/openai-codex/response-handler.d.ts +26 -0
  99. package/dist/types/providers/openai-codex-responses.d.ts +238 -0
  100. package/dist/types/providers/openai-completions.d.ts +48 -0
  101. package/dist/types/providers/openai-reasoning-fallback.d.ts +25 -0
  102. package/dist/types/providers/openai-responses-server-schema.d.ts +1314 -0
  103. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  104. package/dist/types/providers/openai-responses-wire.d.ts +6099 -0
  105. package/dist/types/providers/openai-responses.d.ts +131 -0
  106. package/dist/types/providers/openai-shared.d.ts +624 -0
  107. package/dist/types/providers/pi-native-client.d.ts +13 -0
  108. package/dist/types/providers/pi-native-server.d.ts +69 -0
  109. package/dist/types/providers/register-builtins.d.ts +37 -0
  110. package/dist/types/providers/synthetic.d.ts +26 -0
  111. package/dist/types/providers/transform-messages.d.ts +32 -0
  112. package/dist/types/providers/vision-guard.d.ts +20 -0
  113. package/dist/types/registry/aiand.d.ts +7 -0
  114. package/dist/types/registry/aimlapi.d.ts +4 -0
  115. package/dist/types/registry/alibaba-coding-plan.d.ts +8 -0
  116. package/dist/types/registry/alibaba-token-plan.d.ts +18 -0
  117. package/dist/types/registry/amazon-bedrock.d.ts +5 -0
  118. package/dist/types/registry/anthropic.d.ts +10 -0
  119. package/dist/types/registry/api-key-login.d.ts +42 -0
  120. package/dist/types/registry/api-key-validation.d.ts +43 -0
  121. package/dist/types/registry/aws.d.ts +13 -0
  122. package/dist/types/registry/azure.d.ts +4 -0
  123. package/dist/types/registry/baseten.d.ts +7 -0
  124. package/dist/types/registry/bedrock-mantle.d.ts +22 -0
  125. package/dist/types/registry/cerebras.d.ts +7 -0
  126. package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
  127. package/dist/types/registry/coreweave.d.ts +7 -0
  128. package/dist/types/registry/cursor.d.ts +7 -0
  129. package/dist/types/registry/deepseek.d.ts +8 -0
  130. package/dist/types/registry/derived.d.ts +5 -0
  131. package/dist/types/registry/devin.d.ts +8 -0
  132. package/dist/types/registry/exa.d.ts +8 -0
  133. package/dist/types/registry/firepass.d.ts +16 -0
  134. package/dist/types/registry/fireworks.d.ts +7 -0
  135. package/dist/types/registry/github-copilot.d.ts +7 -0
  136. package/dist/types/registry/gitlab-duo-workflow.d.ts +10 -0
  137. package/dist/types/registry/gitlab-duo.d.ts +9 -0
  138. package/dist/types/registry/gmi-cloud.d.ts +7 -0
  139. package/dist/types/registry/google-antigravity.d.ts +9 -0
  140. package/dist/types/registry/google-gemini-cli.d.ts +9 -0
  141. package/dist/types/registry/google-vertex.d.ts +5 -0
  142. package/dist/types/registry/google.d.ts +4 -0
  143. package/dist/types/registry/groq.d.ts +4 -0
  144. package/dist/types/registry/huggingface.d.ts +7 -0
  145. package/dist/types/registry/index.d.ts +4 -0
  146. package/dist/types/registry/kagi.d.ts +14 -0
  147. package/dist/types/registry/kilo.d.ts +7 -0
  148. package/dist/types/registry/kimi-code.d.ts +7 -0
  149. package/dist/types/registry/litellm.d.ts +13 -0
  150. package/dist/types/registry/llama-cpp.d.ts +8 -0
  151. package/dist/types/registry/lm-studio.d.ts +8 -0
  152. package/dist/types/registry/meta.d.ts +7 -0
  153. package/dist/types/registry/minimax-code-cn.d.ts +6 -0
  154. package/dist/types/registry/minimax-code.d.ts +6 -0
  155. package/dist/types/registry/minimax.d.ts +4 -0
  156. package/dist/types/registry/mistral.d.ts +4 -0
  157. package/dist/types/registry/moonshot.d.ts +7 -0
  158. package/dist/types/registry/nanogpt.d.ts +7 -0
  159. package/dist/types/registry/novita.d.ts +6 -0
  160. package/dist/types/registry/nvidia.d.ts +7 -0
  161. package/dist/types/registry/oauth/anthropic-constants.d.ts +12 -0
  162. package/dist/types/registry/oauth/anthropic.d.ts +24 -0
  163. package/dist/types/registry/oauth/callback-server.d.ts +74 -0
  164. package/dist/types/registry/oauth/cursor.d.ts +16 -0
  165. package/dist/types/registry/oauth/device-code.d.ts +25 -0
  166. package/dist/types/registry/oauth/devin.d.ts +5 -0
  167. package/dist/types/registry/oauth/github-copilot.d.ts +30 -0
  168. package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
  169. package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -0
  170. package/dist/types/registry/oauth/google-antigravity.d.ts +11 -0
  171. package/dist/types/registry/oauth/google-gemini-cli.d.ts +22 -0
  172. package/dist/types/registry/oauth/google-oauth-shared.d.ts +56 -0
  173. package/dist/types/registry/oauth/index.d.ts +45 -0
  174. package/dist/types/registry/oauth/kimi.d.ts +21 -0
  175. package/dist/types/registry/oauth/minimax-code.d.ts +27 -0
  176. package/dist/types/registry/oauth/openai-codex.d.ts +33 -0
  177. package/dist/types/registry/oauth/opencode.d.ts +18 -0
  178. package/dist/types/registry/oauth/perplexity.d.ts +9 -0
  179. package/dist/types/registry/oauth/pkce.d.ts +8 -0
  180. package/dist/types/registry/oauth/types.d.ts +87 -0
  181. package/dist/types/registry/oauth/wafer.d.ts +1 -0
  182. package/dist/types/registry/oauth/xai-oauth.d.ts +46 -0
  183. package/dist/types/registry/oauth/xiaomi.d.ts +25 -0
  184. package/dist/types/registry/oauth/zai.d.ts +25 -0
  185. package/dist/types/registry/ollama-cloud.d.ts +7 -0
  186. package/dist/types/registry/ollama.d.ts +12 -0
  187. package/dist/types/registry/openai-codex-device.d.ts +8 -0
  188. package/dist/types/registry/openai-codex.d.ts +9 -0
  189. package/dist/types/registry/openai.d.ts +4 -0
  190. package/dist/types/registry/opencode-go.d.ts +6 -0
  191. package/dist/types/registry/opencode-zen.d.ts +6 -0
  192. package/dist/types/registry/openrouter.d.ts +13 -0
  193. package/dist/types/registry/parallel.d.ts +14 -0
  194. package/dist/types/registry/perplexity.d.ts +7 -0
  195. package/dist/types/registry/qianfan.d.ts +7 -0
  196. package/dist/types/registry/qwen-portal.d.ts +7 -0
  197. package/dist/types/registry/registry.d.ts +367 -0
  198. package/dist/types/registry/sakana.d.ts +7 -0
  199. package/dist/types/registry/siliconflow-cn.d.ts +7 -0
  200. package/dist/types/registry/siliconflow.d.ts +7 -0
  201. package/dist/types/registry/synthetic.d.ts +6 -0
  202. package/dist/types/registry/tavily.d.ts +14 -0
  203. package/dist/types/registry/together.d.ts +6 -0
  204. package/dist/types/registry/types.d.ts +75 -0
  205. package/dist/types/registry/umans.d.ts +7 -0
  206. package/dist/types/registry/venice.d.ts +13 -0
  207. package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
  208. package/dist/types/registry/vllm.d.ts +7 -0
  209. package/dist/types/registry/wafer-serverless.d.ts +6 -0
  210. package/dist/types/registry/xai-oauth.d.ts +7 -0
  211. package/dist/types/registry/xai.d.ts +7 -0
  212. package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
  213. package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
  214. package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
  215. package/dist/types/registry/xiaomi.d.ts +6 -0
  216. package/dist/types/registry/zai.d.ts +15 -0
  217. package/dist/types/registry/zenmux.d.ts +7 -0
  218. package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
  219. package/dist/types/stream.d.ts +46 -0
  220. package/dist/types/types.d.ts +1064 -0
  221. package/dist/types/usage/alibaba-token-plan.d.ts +3 -0
  222. package/dist/types/usage/claude.d.ts +4 -0
  223. package/dist/types/usage/cursor.d.ts +4 -0
  224. package/dist/types/usage/gemini.d.ts +2 -0
  225. package/dist/types/usage/github-copilot.d.ts +7 -0
  226. package/dist/types/usage/google-antigravity.d.ts +15 -0
  227. package/dist/types/usage/kimi.d.ts +2 -0
  228. package/dist/types/usage/minimax-code.d.ts +3 -0
  229. package/dist/types/usage/ollama.d.ts +5 -0
  230. package/dist/types/usage/openai-codex-base-url.d.ts +18 -0
  231. package/dist/types/usage/openai-codex-reset.d.ts +88 -0
  232. package/dist/types/usage/openai-codex.d.ts +10 -0
  233. package/dist/types/usage/opencode-go.d.ts +2 -0
  234. package/dist/types/usage/shared.d.ts +1 -0
  235. package/dist/types/usage/synthetic.d.ts +2 -0
  236. package/dist/types/usage/umans.d.ts +2 -0
  237. package/dist/types/usage/xai-oauth.d.ts +12 -0
  238. package/dist/types/usage/zai.d.ts +3 -0
  239. package/dist/types/usage.d.ts +527 -0
  240. package/dist/types/utils/abort.d.ts +25 -0
  241. package/dist/types/utils/anthropic-auth.d.ts +35 -0
  242. package/dist/types/utils/aws-profile.d.ts +17 -0
  243. package/dist/types/utils/block-symbols.d.ts +62 -0
  244. package/dist/types/utils/deterministic-id.d.ts +16 -0
  245. package/dist/types/utils/empty-completion-retry.d.ts +21 -0
  246. package/dist/types/utils/event-stream.d.ts +39 -0
  247. package/dist/types/utils/foundry.d.ts +1 -0
  248. package/dist/types/utils/google-validation.d.ts +2 -0
  249. package/dist/types/utils/harmony-leak.d.ts +135 -0
  250. package/dist/types/utils/http-inspector.d.ts +49 -0
  251. package/dist/types/utils/idle-iterator.d.ts +149 -0
  252. package/dist/types/utils/leaked-thinking-stream.d.ts +33 -0
  253. package/dist/types/utils/openai-http.d.ts +48 -0
  254. package/dist/types/utils/openrouter-headers.d.ts +1 -0
  255. package/dist/types/utils/parse-bind.d.ts +23 -0
  256. package/dist/types/utils/provider-response.d.ts +3 -0
  257. package/dist/types/utils/proxy.d.ts +39 -0
  258. package/dist/types/utils/request-debug.d.ts +29 -0
  259. package/dist/types/utils/retry-after.d.ts +4 -0
  260. package/dist/types/utils/retry.d.ts +14 -0
  261. package/dist/types/utils/schema/adapt.d.ts +24 -0
  262. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  263. package/dist/types/utils/schema/dereference.d.ts +11 -0
  264. package/dist/types/utils/schema/draft.d.ts +10 -0
  265. package/dist/types/utils/schema/equality.d.ts +4 -0
  266. package/dist/types/utils/schema/fields.d.ts +54 -0
  267. package/dist/types/utils/schema/index.d.ts +14 -0
  268. package/dist/types/utils/schema/json-schema-validator.d.ts +20 -0
  269. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  270. package/dist/types/utils/schema/normalize.d.ts +153 -0
  271. package/dist/types/utils/schema/spill.d.ts +8 -0
  272. package/dist/types/utils/schema/stamps.d.ts +17 -0
  273. package/dist/types/utils/schema/strict-tool-validation.d.ts +16 -0
  274. package/dist/types/utils/schema/types.d.ts +4 -0
  275. package/dist/types/utils/schema/typescript.d.ts +24 -0
  276. package/dist/types/utils/schema/wire.d.ts +52 -0
  277. package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
  278. package/dist/types/utils/sse-debug.d.ts +5 -0
  279. package/dist/types/utils/stream-markup-healing.d.ts +87 -0
  280. package/dist/types/utils/thinking-loop.d.ts +102 -0
  281. package/dist/types/utils/tool-call-loop-guard.d.ts +26 -0
  282. package/dist/types/utils/tool-choice.d.ts +52 -0
  283. package/dist/types/utils/validation.d.ts +28 -0
  284. package/dist/types/utils.d.ts +57 -0
  285. package/package.json +138 -0
  286. package/src/api-registry.ts +109 -0
  287. package/src/auth/sqlite-credential-store.ts +2066 -0
  288. package/src/auth-broker/client.ts +471 -0
  289. package/src/auth-broker/discover.ts +310 -0
  290. package/src/auth-broker/index.ts +7 -0
  291. package/src/auth-broker/refresher.ts +117 -0
  292. package/src/auth-broker/remote-store.ts +1332 -0
  293. package/src/auth-broker/server.ts +898 -0
  294. package/src/auth-broker/snapshot-cache.ts +200 -0
  295. package/src/auth-broker/types.ts +193 -0
  296. package/src/auth-broker/wire-schema-resource.ts +487 -0
  297. package/src/auth-broker/wire-schemas.ts +43 -0
  298. package/src/auth-gateway/http.ts +227 -0
  299. package/src/auth-gateway/index.ts +3 -0
  300. package/src/auth-gateway/server.ts +836 -0
  301. package/src/auth-gateway/types.ts +153 -0
  302. package/src/auth-retry.ts +401 -0
  303. package/src/auth-storage.ts +6540 -0
  304. package/src/dialect/anthropic.md +31 -0
  305. package/src/dialect/anthropic.ts +608 -0
  306. package/src/dialect/catalog.ts +29 -0
  307. package/src/dialect/coercion.ts +136 -0
  308. package/src/dialect/deepseek.md +24 -0
  309. package/src/dialect/deepseek.ts +609 -0
  310. package/src/dialect/demotion.ts +40 -0
  311. package/src/dialect/examples.ts +71 -0
  312. package/src/dialect/factory.ts +34 -0
  313. package/src/dialect/fenced-thinking.ts +184 -0
  314. package/src/dialect/gemini.md +44 -0
  315. package/src/dialect/gemini.ts +583 -0
  316. package/src/dialect/gemma.md +33 -0
  317. package/src/dialect/gemma.ts +387 -0
  318. package/src/dialect/glm.md +32 -0
  319. package/src/dialect/glm.ts +579 -0
  320. package/src/dialect/harmony.md +31 -0
  321. package/src/dialect/harmony.ts +345 -0
  322. package/src/dialect/hermes.md +25 -0
  323. package/src/dialect/hermes.ts +206 -0
  324. package/src/dialect/history.ts +81 -0
  325. package/src/dialect/index.ts +15 -0
  326. package/src/dialect/inventory.ts +30 -0
  327. package/src/dialect/kimi.md +24 -0
  328. package/src/dialect/kimi.ts +340 -0
  329. package/src/dialect/minimax.md +31 -0
  330. package/src/dialect/minimax.ts +95 -0
  331. package/src/dialect/owned-stream.ts +481 -0
  332. package/src/dialect/prompt-template.md +12 -0
  333. package/src/dialect/qwen3.md +28 -0
  334. package/src/dialect/qwen3.ts +240 -0
  335. package/src/dialect/rendering.ts +304 -0
  336. package/src/dialect/thinking.ts +292 -0
  337. package/src/dialect/types.ts +56 -0
  338. package/src/dialect/xml.md +22 -0
  339. package/src/dialect/xml.ts +90 -0
  340. package/src/error/abort.ts +18 -0
  341. package/src/error/auth-classify.ts +47 -0
  342. package/src/error/auth.ts +48 -0
  343. package/src/error/aws.ts +35 -0
  344. package/src/error/classes.ts +281 -0
  345. package/src/error/finalize.ts +69 -0
  346. package/src/error/flags.ts +602 -0
  347. package/src/error/format.ts +45 -0
  348. package/src/error/gateway.ts +96 -0
  349. package/src/error/index.ts +14 -0
  350. package/src/error/oauth.ts +58 -0
  351. package/src/error/provider.ts +63 -0
  352. package/src/error/rate-limit.ts +303 -0
  353. package/src/error/retryable.ts +70 -0
  354. package/src/error/validation.ts +44 -0
  355. package/src/index.ts +51 -0
  356. package/src/provider-details.ts +90 -0
  357. package/src/providers/amazon-bedrock.ts +1064 -0
  358. package/src/providers/anthropic-client.ts +317 -0
  359. package/src/providers/anthropic-messages-server-schema.ts +252 -0
  360. package/src/providers/anthropic-messages-server.ts +818 -0
  361. package/src/providers/anthropic-wire.ts +359 -0
  362. package/src/providers/anthropic.ts +4539 -0
  363. package/src/providers/aws-credentials.ts +772 -0
  364. package/src/providers/aws-eventstream.ts +181 -0
  365. package/src/providers/aws-sigv4.ts +218 -0
  366. package/src/providers/azure-openai-responses.ts +438 -0
  367. package/src/providers/bedrock-mantle.ts +110 -0
  368. package/src/providers/claude-code-fingerprint.ts +20 -0
  369. package/src/providers/cowork-fetch.ts +201 -0
  370. package/src/providers/cursor/exec-modern.ts +496 -0
  371. package/src/providers/cursor/proto/agent.proto +4533 -0
  372. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  373. package/src/providers/cursor/proto/buf.yaml +17 -0
  374. package/src/providers/cursor-pi-args.ts +165 -0
  375. package/src/providers/cursor.ts +4689 -0
  376. package/src/providers/devin/proto/buf/validate/validate.proto +468 -0
  377. package/src/providers/devin/proto/buf.gen.yaml +33 -0
  378. package/src/providers/devin/proto/buf.yaml +17 -0
  379. package/src/providers/devin/proto/cel/expr/checked.proto +103 -0
  380. package/src/providers/devin/proto/cel/expr/eval.proto +38 -0
  381. package/src/providers/devin/proto/cel/expr/explain.proto +15 -0
  382. package/src/providers/devin/proto/cel/expr/syntax.proto +113 -0
  383. package/src/providers/devin/proto/cel/expr/value.proto +41 -0
  384. package/src/providers/devin/proto/connectext/grpc/status/v1/status.proto +11 -0
  385. package/src/providers/devin/proto/errorspb/errors.proto +56 -0
  386. package/src/providers/devin/proto/errorspb/hintdetail.proto +7 -0
  387. package/src/providers/devin/proto/errorspb/markers.proto +10 -0
  388. package/src/providers/devin/proto/errorspb/tags.proto +12 -0
  389. package/src/providers/devin/proto/errorspb/testing.proto +6 -0
  390. package/src/providers/devin/proto/exa/analytics_pb/analytics.proto +188 -0
  391. package/src/providers/devin/proto/exa/api_server_pb/api_server.proto +2461 -0
  392. package/src/providers/devin/proto/exa/auth_pb/auth.proto +19 -0
  393. package/src/providers/devin/proto/exa/auto_cascade_common_pb/auto_cascade_common.proto +79 -0
  394. package/src/providers/devin/proto/exa/browser_preview_pb/browser_preview.proto +32 -0
  395. package/src/providers/devin/proto/exa/bug_checker_pb/bug_checker.proto +22 -0
  396. package/src/providers/devin/proto/exa/cascade_plugins_pb/cascade_plugins.proto +262 -0
  397. package/src/providers/devin/proto/exa/chat_client_server_pb/chat_client_server.proto +57 -0
  398. package/src/providers/devin/proto/exa/chat_pb/chat.proto +449 -0
  399. package/src/providers/devin/proto/exa/code_edit/code_edit_pb/code_edit.proto +186 -0
  400. package/src/providers/devin/proto/exa/codeium_common_pb/codeium_common.proto +4157 -0
  401. package/src/providers/devin/proto/exa/context_module_pb/context_module.proto +175 -0
  402. package/src/providers/devin/proto/exa/cortex_pb/cortex.proto +3268 -0
  403. package/src/providers/devin/proto/exa/dev_pb/dev.proto +26 -0
  404. package/src/providers/devin/proto/exa/diff_action_pb/diff_action.proto +75 -0
  405. package/src/providers/devin/proto/exa/eval/pr_eval/datasets_pb/datasets.proto +103 -0
  406. package/src/providers/devin/proto/exa/eval_pb/eval.proto +1315 -0
  407. package/src/providers/devin/proto/exa/extension_server_pb/extension_server.proto +556 -0
  408. package/src/providers/devin/proto/exa/file_system_provider_pb/file_system_provider.proto +75 -0
  409. package/src/providers/devin/proto/exa/index_pb/index.proto +461 -0
  410. package/src/providers/devin/proto/exa/knowledge_base_pb/knowledge_base.proto +144 -0
  411. package/src/providers/devin/proto/exa/language_server_pb/language_server.proto +2385 -0
  412. package/src/providers/devin/proto/exa/model_management_pb/model_management.proto +186 -0
  413. package/src/providers/devin/proto/exa/opensearch_clients_pb/opensearch_clients.proto +503 -0
  414. package/src/providers/devin/proto/exa/product_analytics_pb/product_analytics.proto +37 -0
  415. package/src/providers/devin/proto/exa/prompt_pb/prompt.proto +92 -0
  416. package/src/providers/devin/proto/exa/reactive_component_pb/reactive_component.proto +96 -0
  417. package/src/providers/devin/proto/exa/seat_management_pb/seat_management.proto +2680 -0
  418. package/src/providers/devin/proto/exa/tokenizer_pb/tokenizer.proto +37 -0
  419. package/src/providers/devin/proto/exa/trainer_pb/config.proto +647 -0
  420. package/src/providers/devin/proto/exa/tree_sitter/language_data_pb/language_data.proto +14 -0
  421. package/src/providers/devin/proto/exa/trust_pb/trust.proto +157 -0
  422. package/src/providers/devin/proto/exa/user_analytics_pb/user_analytics.proto +519 -0
  423. package/src/providers/devin/proto/google.golang.org/appengine/internal/base/api_base.proto +28 -0
  424. package/src/providers/devin/proto/google.golang.org/appengine/internal/datastore/datastore_v3.proto +484 -0
  425. package/src/providers/devin/proto/google.golang.org/appengine/internal/log/log_service.proto +136 -0
  426. package/src/providers/devin/proto/google.golang.org/appengine/internal/remote_api/remote_api.proto +42 -0
  427. package/src/providers/devin/proto/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +61 -0
  428. package/src/providers/devin/proto/grpc/binlog/v1/binarylog.proto +84 -0
  429. package/src/providers/devin/proto/io/prometheus/client/metrics.proto +98 -0
  430. package/src/providers/devin.ts +679 -0
  431. package/src/providers/error-message.ts +23 -0
  432. package/src/providers/github-copilot-headers.ts +141 -0
  433. package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
  434. package/src/providers/gitlab-duo-workflow.ts +3135 -0
  435. package/src/providers/gitlab-duo.ts +399 -0
  436. package/src/providers/google-auth.ts +330 -0
  437. package/src/providers/google-gemini-cli.ts +1370 -0
  438. package/src/providers/google-shared.ts +1122 -0
  439. package/src/providers/google-types.ts +180 -0
  440. package/src/providers/google-vertex.ts +135 -0
  441. package/src/providers/google.ts +47 -0
  442. package/src/providers/grammar.ts +70 -0
  443. package/src/providers/kimi.ts +51 -0
  444. package/src/providers/mock.ts +514 -0
  445. package/src/providers/ollama.ts +776 -0
  446. package/src/providers/openai-anthropic-shim.ts +166 -0
  447. package/src/providers/openai-chat-server-schema.ts +243 -0
  448. package/src/providers/openai-chat-server.ts +752 -0
  449. package/src/providers/openai-chat-wire.ts +859 -0
  450. package/src/providers/openai-codex/request-transformer.ts +491 -0
  451. package/src/providers/openai-codex/response-handler.ts +102 -0
  452. package/src/providers/openai-codex-responses.ts +4716 -0
  453. package/src/providers/openai-completions.ts +2389 -0
  454. package/src/providers/openai-reasoning-fallback.ts +269 -0
  455. package/src/providers/openai-responses-server-schema.ts +397 -0
  456. package/src/providers/openai-responses-server.ts +1466 -0
  457. package/src/providers/openai-responses-wire.ts +6416 -0
  458. package/src/providers/openai-responses.ts +1393 -0
  459. package/src/providers/openai-shared.ts +3500 -0
  460. package/src/providers/pi-native-client.ts +275 -0
  461. package/src/providers/pi-native-server.ts +245 -0
  462. package/src/providers/register-builtins.ts +503 -0
  463. package/src/providers/synthetic.ts +50 -0
  464. package/src/providers/transform-messages.ts +1083 -0
  465. package/src/providers/vision-guard.ts +54 -0
  466. package/src/registry/aiand.ts +22 -0
  467. package/src/registry/aimlapi.ts +6 -0
  468. package/src/registry/alibaba-coding-plan.ts +104 -0
  469. package/src/registry/alibaba-token-plan.ts +125 -0
  470. package/src/registry/amazon-bedrock.ts +22 -0
  471. package/src/registry/anthropic.ts +26 -0
  472. package/src/registry/api-key-login.ts +115 -0
  473. package/src/registry/api-key-validation.ts +145 -0
  474. package/src/registry/aws.ts +57 -0
  475. package/src/registry/azure.ts +6 -0
  476. package/src/registry/baseten.ts +22 -0
  477. package/src/registry/bedrock-mantle.ts +34 -0
  478. package/src/registry/cerebras.ts +23 -0
  479. package/src/registry/cloudflare-ai-gateway.ts +45 -0
  480. package/src/registry/coreweave.ts +40 -0
  481. package/src/registry/cursor.ts +20 -0
  482. package/src/registry/deepseek.ts +46 -0
  483. package/src/registry/derived.ts +9 -0
  484. package/src/registry/devin.ts +15 -0
  485. package/src/registry/exa.ts +19 -0
  486. package/src/registry/firepass.ts +32 -0
  487. package/src/registry/fireworks.ts +28 -0
  488. package/src/registry/github-copilot.ts +22 -0
  489. package/src/registry/gitlab-duo-workflow.ts +20 -0
  490. package/src/registry/gitlab-duo.ts +19 -0
  491. package/src/registry/gmi-cloud.ts +22 -0
  492. package/src/registry/google-antigravity.ts +22 -0
  493. package/src/registry/google-gemini-cli.ts +22 -0
  494. package/src/registry/google-vertex.ts +38 -0
  495. package/src/registry/google.ts +6 -0
  496. package/src/registry/groq.ts +6 -0
  497. package/src/registry/huggingface.ts +29 -0
  498. package/src/registry/index.ts +4 -0
  499. package/src/registry/kagi.ts +46 -0
  500. package/src/registry/kilo.ts +114 -0
  501. package/src/registry/kimi-code.ts +17 -0
  502. package/src/registry/litellm.ts +45 -0
  503. package/src/registry/llama-cpp.ts +35 -0
  504. package/src/registry/lm-studio.ts +31 -0
  505. package/src/registry/meta.ts +22 -0
  506. package/src/registry/minimax-code-cn.ts +12 -0
  507. package/src/registry/minimax-code.ts +12 -0
  508. package/src/registry/minimax.ts +6 -0
  509. package/src/registry/mistral.ts +6 -0
  510. package/src/registry/moonshot.ts +28 -0
  511. package/src/registry/nanogpt.ts +22 -0
  512. package/src/registry/novita.ts +25 -0
  513. package/src/registry/nvidia.ts +61 -0
  514. package/src/registry/oauth/anthropic-constants.ts +12 -0
  515. package/src/registry/oauth/anthropic.ts +346 -0
  516. package/src/registry/oauth/callback-server.ts +438 -0
  517. package/src/registry/oauth/cursor.ts +187 -0
  518. package/src/registry/oauth/device-code.ts +92 -0
  519. package/src/registry/oauth/devin.ts +124 -0
  520. package/src/registry/oauth/github-copilot.ts +369 -0
  521. package/src/registry/oauth/gitlab-duo-workflow.ts +146 -0
  522. package/src/registry/oauth/gitlab-duo.ts +222 -0
  523. package/src/registry/oauth/google-antigravity.ts +225 -0
  524. package/src/registry/oauth/google-gemini-cli.ts +297 -0
  525. package/src/registry/oauth/google-oauth-shared.ts +211 -0
  526. package/src/registry/oauth/index.ts +187 -0
  527. package/src/registry/oauth/kimi.ts +297 -0
  528. package/src/registry/oauth/minimax-code.ts +53 -0
  529. package/src/registry/oauth/oauth.html +317 -0
  530. package/src/registry/oauth/openai-codex.ts +384 -0
  531. package/src/registry/oauth/opencode.ts +50 -0
  532. package/src/registry/oauth/perplexity.ts +228 -0
  533. package/src/registry/oauth/pkce.ts +18 -0
  534. package/src/registry/oauth/types.ts +96 -0
  535. package/src/registry/oauth/wafer.ts +24 -0
  536. package/src/registry/oauth/xai-oauth.ts +559 -0
  537. package/src/registry/oauth/xiaomi.ts +211 -0
  538. package/src/registry/oauth/zai.ts +285 -0
  539. package/src/registry/ollama-cloud.ts +36 -0
  540. package/src/registry/ollama.ts +43 -0
  541. package/src/registry/openai-codex-device.ts +18 -0
  542. package/src/registry/openai-codex.ts +19 -0
  543. package/src/registry/openai.ts +6 -0
  544. package/src/registry/opencode-go.ts +12 -0
  545. package/src/registry/opencode-zen.ts +12 -0
  546. package/src/registry/openrouter.ts +28 -0
  547. package/src/registry/parallel.ts +45 -0
  548. package/src/registry/perplexity.ts +13 -0
  549. package/src/registry/qianfan.ts +27 -0
  550. package/src/registry/qwen-portal.ts +50 -0
  551. package/src/registry/registry.ts +182 -0
  552. package/src/registry/sakana.ts +22 -0
  553. package/src/registry/siliconflow-cn.ts +22 -0
  554. package/src/registry/siliconflow.ts +22 -0
  555. package/src/registry/synthetic.ts +21 -0
  556. package/src/registry/tavily.ts +45 -0
  557. package/src/registry/together.ts +22 -0
  558. package/src/registry/types.ts +86 -0
  559. package/src/registry/umans.ts +23 -0
  560. package/src/registry/venice.ts +33 -0
  561. package/src/registry/vercel-ai-gateway.ts +38 -0
  562. package/src/registry/vllm.ts +34 -0
  563. package/src/registry/wafer-serverless.ts +12 -0
  564. package/src/registry/xai-oauth.ts +17 -0
  565. package/src/registry/xai.ts +22 -0
  566. package/src/registry/xiaomi-token-plan-ams.ts +12 -0
  567. package/src/registry/xiaomi-token-plan-cn.ts +12 -0
  568. package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
  569. package/src/registry/xiaomi.ts +12 -0
  570. package/src/registry/zai.ts +41 -0
  571. package/src/registry/zenmux.ts +22 -0
  572. package/src/registry/zhipu-coding-plan.ts +27 -0
  573. package/src/stream.ts +1944 -0
  574. package/src/types.ts +1243 -0
  575. package/src/usage/alibaba-token-plan.ts +230 -0
  576. package/src/usage/claude.ts +830 -0
  577. package/src/usage/cursor.ts +335 -0
  578. package/src/usage/gemini.ts +258 -0
  579. package/src/usage/github-copilot.ts +424 -0
  580. package/src/usage/google-antigravity.ts +497 -0
  581. package/src/usage/kimi.ts +277 -0
  582. package/src/usage/minimax-code.ts +291 -0
  583. package/src/usage/ollama.ts +41 -0
  584. package/src/usage/openai-codex-base-url.ts +35 -0
  585. package/src/usage/openai-codex-reset.ts +205 -0
  586. package/src/usage/openai-codex.ts +627 -0
  587. package/src/usage/opencode-go.ts +89 -0
  588. package/src/usage/shared.ts +10 -0
  589. package/src/usage/synthetic.ts +180 -0
  590. package/src/usage/umans.ts +192 -0
  591. package/src/usage/xai-oauth.ts +414 -0
  592. package/src/usage/zai.ts +370 -0
  593. package/src/usage.ts +411 -0
  594. package/src/utils/abort.ts +67 -0
  595. package/src/utils/anthropic-auth.ts +93 -0
  596. package/src/utils/aws-profile.ts +88 -0
  597. package/src/utils/block-symbols.ts +78 -0
  598. package/src/utils/deterministic-id.ts +20 -0
  599. package/src/utils/empty-completion-retry.ts +161 -0
  600. package/src/utils/event-stream.ts +202 -0
  601. package/src/utils/foundry.ts +8 -0
  602. package/src/utils/google-validation.ts +25 -0
  603. package/src/utils/harmony-leak.ts +500 -0
  604. package/src/utils/http-inspector.ts +196 -0
  605. package/src/utils/idle-iterator.ts +531 -0
  606. package/src/utils/leaked-thinking-stream.ts +483 -0
  607. package/src/utils/openai-http.ts +119 -0
  608. package/src/utils/openrouter-headers.ts +12 -0
  609. package/src/utils/parse-bind.ts +56 -0
  610. package/src/utils/provider-response.ts +30 -0
  611. package/src/utils/proxy.ts +314 -0
  612. package/src/utils/request-debug.ts +351 -0
  613. package/src/utils/retry-after.ts +121 -0
  614. package/src/utils/retry.ts +77 -0
  615. package/src/utils/schema/CONSTRAINTS.md +168 -0
  616. package/src/utils/schema/adapt.ts +36 -0
  617. package/src/utils/schema/compatibility.ts +435 -0
  618. package/src/utils/schema/dereference.ts +98 -0
  619. package/src/utils/schema/draft.ts +341 -0
  620. package/src/utils/schema/equality.ts +97 -0
  621. package/src/utils/schema/fields.ts +210 -0
  622. package/src/utils/schema/index.ts +14 -0
  623. package/src/utils/schema/json-schema-validator.ts +595 -0
  624. package/src/utils/schema/meta-validator.ts +167 -0
  625. package/src/utils/schema/normalize.ts +2314 -0
  626. package/src/utils/schema/spill.ts +43 -0
  627. package/src/utils/schema/stamps.ts +109 -0
  628. package/src/utils/schema/strict-tool-validation.ts +117 -0
  629. package/src/utils/schema/types.ts +10 -0
  630. package/src/utils/schema/typescript.ts +212 -0
  631. package/src/utils/schema/wire.ts +662 -0
  632. package/src/utils/sdk-stream-timeout.ts +43 -0
  633. package/src/utils/sse-debug.ts +18 -0
  634. package/src/utils/stream-markup-healing.ts +247 -0
  635. package/src/utils/thinking-loop.ts +552 -0
  636. package/src/utils/tool-call-loop-guard.ts +107 -0
  637. package/src/utils/tool-choice.ts +101 -0
  638. package/src/utils/validation.ts +1932 -0
  639. package/src/utils.ts +492 -0
@@ -0,0 +1,1064 @@
1
+ /**
2
+ * Amazon Bedrock Converse Stream provider.
3
+ *
4
+ * Talks directly to `bedrock-runtime.{region}.amazonaws.com` over HTTPS with
5
+ * SigV4 signing and decodes the `application/vnd.amazon.eventstream` response.
6
+ * No `@aws-sdk/*`, no `@smithy/*`, no `proxy-agent`. Proxies are honored via
7
+ * Bun's native `HTTPS_PROXY` support.
8
+ */
9
+
10
+ import type { Effort } from "@linxiraos/pi-catalog/effort";
11
+ import { mapEffortToAnthropicAdaptiveEffort, requireSupportedEffort } from "@linxiraos/pi-catalog/model-thinking";
12
+ import { calculateCost } from "@linxiraos/pi-catalog/models";
13
+ import { $env, $flag, fetchWithRetry, parseStreamingJson, parseStreamingJsonThrottled } from "@linxiraos/pi-utils";
14
+ import { renderDemotedThinking } from "../dialect/demotion";
15
+ import * as AIError from "../error";
16
+ import type {
17
+ Api,
18
+ AssistantMessage,
19
+ CacheRetention,
20
+ Context,
21
+ Model,
22
+ StopReason,
23
+ StreamFunction,
24
+ StreamOptions,
25
+ TextContent,
26
+ ThinkingBudgets,
27
+ ThinkingContent,
28
+ Tool,
29
+ ToolCall,
30
+ ToolResultMessage,
31
+ } from "../types";
32
+ import { normalizeSystemPrompts, normalizeToolCallId, resolveCacheRetention } from "../utils";
33
+ import {
34
+ clearStreamingPartialJson,
35
+ kStreamingBlockIndex,
36
+ kStreamingLastParseLen,
37
+ kStreamingPartialJson,
38
+ } from "../utils/block-symbols";
39
+ import { AssistantMessageEventStream } from "../utils/event-stream";
40
+ import type { RawHttpRequestDump } from "../utils/http-inspector";
41
+ import { armPreResponseTimeout, getStreamFirstEventTimeoutMs } from "../utils/idle-iterator";
42
+ import { toolWireSchema } from "../utils/schema/wire";
43
+ import { invalidateAwsCredentialCache, resolveAwsCredentials } from "./aws-credentials";
44
+ import { decodeEventStream } from "./aws-eventstream";
45
+ import { signRequest } from "./aws-sigv4";
46
+ import { transformMessages } from "./transform-messages";
47
+
48
+ export type BedrockThinkingDisplay = "summarized" | "omitted";
49
+
50
+ export interface BedrockOptions extends StreamOptions {
51
+ region?: string;
52
+ profile?: string;
53
+ /** Amazon Bedrock API key sent as `Authorization: Bearer`, ahead of SigV4 credential resolution. */
54
+ bearerToken?: string;
55
+ toolChoice?: "auto" | "any" | "none" | { type: "tool"; name: string };
56
+ /* See https://docs.aws.amazon.com/bedrock/latest/userguide/inference-reasoning.html for supported models. */
57
+ reasoning?: Effort;
58
+ /* Custom token budgets per thinking level. Overrides default budgets. */
59
+ thinkingBudgets?: ThinkingBudgets;
60
+ /* Only supported by Claude 4.x models, see https://docs.aws.amazon.com/bedrock/latest/userguide/claude-messages-extended-thinking.html#claude-messages-extended-thinking-tool-use-interleaved */
61
+ interleavedThinking?: boolean;
62
+ /**
63
+ * Controls how Claude returns thinking content in Bedrock responses.
64
+ * - `"summarized"`: thinking blocks include human-readable summaries (default here).
65
+ * - `"omitted"`: thinking content is suppressed; the encrypted signature still
66
+ * travels back for multi-turn continuity.
67
+ *
68
+ * Starting with Claude Opus 4.7 and Claude Fable/Mythos 5 the Anthropic API
69
+ * default is `"omitted"`, which leaves callers waiting on a silent stream during
70
+ * long reasoning runs (issue #1373). We default to `"summarized"` so adaptive-
71
+ * thinking models that accept the field keep producing visible thinking deltas.
72
+ * Older adaptive-thinking models (Opus 4.6, Sonnet 4.6+) reject the field, so
73
+ * we omit it for them.
74
+ */
75
+ thinkingDisplay?: BedrockThinkingDisplay;
76
+ }
77
+ const AUTHENTICATED_API_KEY_SENTINEL = "<authenticated>";
78
+
79
+ function resolveBearerToken(options: BedrockOptions): string | undefined {
80
+ const apiKey = options.apiKey === AUTHENTICATED_API_KEY_SENTINEL ? undefined : options.apiKey;
81
+ return options.bearerToken || apiKey || $env.AWS_BEARER_TOKEN_BEDROCK;
82
+ }
83
+
84
+ function inferRegionFromBedrockArn(modelId: string): string | undefined {
85
+ const parts = modelId.split(":", 6);
86
+ if (parts[0] !== "arn" || parts[2] !== "bedrock") return undefined;
87
+ const region = parts[3];
88
+ return region || undefined;
89
+ }
90
+
91
+ /**
92
+ * Default AWS region for each Bedrock cross-region inference-profile geo prefix.
93
+ * A geo-prefixed profile (e.g. `eu.anthropic.claude-…`) is only servable from
94
+ * regions in its own geo, so routing one to `us-east-1` yields HTTP 400 "The
95
+ * provided model identifier is invalid." `global.` profiles are anchored in the
96
+ * us regions and intentionally absent here (they resolve fine via `us-east-1`).
97
+ */
98
+ const INFERENCE_PROFILE_GEO_DEFAULT_REGION: Record<string, string> = {
99
+ us: "us-east-1",
100
+ "us-gov": "us-gov-west-1",
101
+ eu: "eu-west-1",
102
+ apac: "ap-southeast-1",
103
+ au: "ap-southeast-2",
104
+ jp: "ap-northeast-1",
105
+ };
106
+
107
+ /** Geo prefix of a cross-region inference-profile id, e.g. `eu.anthropic.…` → `eu`. */
108
+ function inferenceProfileGeo(modelId: string): string | undefined {
109
+ const dot = modelId.indexOf(".");
110
+ if (dot <= 0) return undefined;
111
+ const prefix = modelId.slice(0, dot);
112
+ return prefix in INFERENCE_PROFILE_GEO_DEFAULT_REGION ? prefix : undefined;
113
+ }
114
+
115
+ /**
116
+ * Whether a concrete AWS region can serve a given inference-profile geo. The
117
+ * `ap-` regions overlap across `apac`/`au`/`jp` profiles, so the Australia and
118
+ * Japan geos pin their specific source regions rather than matching all `ap-*`.
119
+ */
120
+ function regionServesGeo(region: string, geo: string): boolean {
121
+ switch (geo) {
122
+ case "us-gov":
123
+ return region.startsWith("us-gov-");
124
+ case "us":
125
+ return region.startsWith("us-") && !region.startsWith("us-gov-");
126
+ case "eu":
127
+ return region.startsWith("eu-");
128
+ case "apac":
129
+ return region.startsWith("ap-");
130
+ case "au":
131
+ return region === "ap-southeast-2" || region === "ap-southeast-4";
132
+ case "jp":
133
+ return region === "ap-northeast-1" || region === "ap-northeast-3";
134
+ default:
135
+ return false;
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Resolve the Bedrock runtime region for a request. An explicit per-request
141
+ * region and an ARN-embedded region win outright. Otherwise, for a geo-prefixed
142
+ * cross-region inference profile (`us.`/`eu.`/`apac.`/`au.`/`jp.`/`us-gov.`), an
143
+ * ambient region (`AWS_REGION` / `AWS_DEFAULT_REGION`) is honored only when it
144
+ * can serve the profile's geo; a mismatched or absent ambient region is
145
+ * corrected to the geo default so an `eu.`/`apac.` profile never POSTs to a `us`
146
+ * endpoint (and vice versa). `global.` profiles have no geo entry, so the
147
+ * ambient region (or `us-east-1`) is used unchanged.
148
+ */
149
+ function resolveBedrockRegion(modelId: string, options: BedrockOptions): string {
150
+ const explicit = options.region || inferRegionFromBedrockArn(modelId);
151
+ if (explicit) return explicit;
152
+ const ambient = $env.AWS_REGION || $env.AWS_DEFAULT_REGION;
153
+ const geo = inferenceProfileGeo(modelId);
154
+ if (geo) {
155
+ if (ambient && regionServesGeo(ambient, geo)) return ambient;
156
+ return INFERENCE_PROFILE_GEO_DEFAULT_REGION[geo];
157
+ }
158
+ return ambient || "us-east-1";
159
+ }
160
+
161
+ type Block = (TextContent | ThinkingContent | ToolCall) & {
162
+ [kStreamingBlockIndex]?: number;
163
+ [kStreamingPartialJson]?: string;
164
+ [kStreamingLastParseLen]?: number;
165
+ };
166
+
167
+ // ---------- Bedrock wire-format types ----------
168
+ // Mirrors only what we actually consume from `ConverseStreamRequest` /
169
+ // `ConverseStreamOutput`. Keeps us decoupled from `@aws-sdk/client-bedrock-runtime`.
170
+
171
+ interface CachePoint {
172
+ cachePoint: { type: "default"; ttl?: "5m" | "1h" };
173
+ }
174
+
175
+ interface BedrockPromptCachePolicy {
176
+ remainingCheckpoints: number;
177
+ ttl?: "1h";
178
+ }
179
+ interface TextBlockWire {
180
+ text: string;
181
+ }
182
+ interface ImageBlockWire {
183
+ image: { format: "jpeg" | "png" | "gif" | "webp"; source: { bytes: string } };
184
+ }
185
+ interface ToolUseBlockWire {
186
+ toolUse: { toolUseId: string; name: string; input: unknown };
187
+ }
188
+ interface ToolResultBlockWire {
189
+ toolResult: {
190
+ toolUseId: string;
191
+ content: Array<TextBlockWire | ImageBlockWire>;
192
+ status: "success" | "error";
193
+ };
194
+ }
195
+ interface ReasoningBlockWire {
196
+ reasoningContent: { reasoningText: { text: string; signature?: string } };
197
+ }
198
+
199
+ type UserContent = TextBlockWire | ImageBlockWire | ToolResultBlockWire | CachePoint;
200
+ type AssistantContent = TextBlockWire | ToolUseBlockWire | ReasoningBlockWire;
201
+ type SystemContent = TextBlockWire | CachePoint;
202
+
203
+ interface WireMessage {
204
+ role: "user" | "assistant";
205
+ content: Array<UserContent | AssistantContent>;
206
+ }
207
+
208
+ interface WireToolSpec {
209
+ toolSpec: { name: string; description: string; inputSchema: { json: unknown } };
210
+ }
211
+ interface WireToolChoice {
212
+ auto?: Record<string, never>;
213
+ any?: Record<string, never>;
214
+ tool?: { name: string };
215
+ }
216
+ interface WireToolConfig {
217
+ tools: WireToolSpec[];
218
+ toolChoice?: WireToolChoice;
219
+ }
220
+
221
+ /**
222
+ * Bedrock validates that requests carrying any `toolUse`/`toolResult` history
223
+ * include a `toolConfig`. For no-tool ephemeral turns (`/btw`, IRC auto-replies)
224
+ * we have nothing real to send, so we inject this placeholder. Its presence is
225
+ * tracked by a per-request flag — never the wire name — so callers who happen
226
+ * to register a real tool literally called `__no_tools__` are not affected.
227
+ */
228
+ const NO_TOOLS_SENTINEL_NAME = "__no_tools__";
229
+
230
+ const NO_TOOLS_SENTINEL: WireToolSpec = {
231
+ toolSpec: {
232
+ name: NO_TOOLS_SENTINEL_NAME,
233
+ description: "Placeholder required by Bedrock validation. Do not call; answer with text.",
234
+ inputSchema: { json: { type: "object", properties: {} } },
235
+ },
236
+ };
237
+
238
+ interface BedrockToolPlan {
239
+ toolConfig: WireToolConfig | undefined;
240
+ sentinelInjected: boolean;
241
+ }
242
+
243
+ interface ConverseStreamRequest {
244
+ messages: WireMessage[];
245
+ system?: SystemContent[];
246
+ inferenceConfig?: { maxTokens?: number; temperature?: number; topP?: number };
247
+ toolConfig?: WireToolConfig;
248
+ additionalModelRequestFields?: Record<string, unknown>;
249
+ }
250
+
251
+ // Streaming events (snake_case matches the JSON envelope key, but Bedrock uses camelCase).
252
+ interface MessageStartEvent {
253
+ role: "user" | "assistant";
254
+ }
255
+ interface ContentBlockStartEvent {
256
+ contentBlockIndex: number;
257
+ start?: { toolUse?: { toolUseId?: string; name?: string } };
258
+ }
259
+ interface ContentBlockDeltaEvent {
260
+ contentBlockIndex: number;
261
+ delta?: {
262
+ text?: string;
263
+ toolUse?: { input?: string };
264
+ reasoningContent?: { text?: string; signature?: string };
265
+ };
266
+ }
267
+ interface ContentBlockStopEvent {
268
+ contentBlockIndex: number;
269
+ }
270
+ interface MessageStopEvent {
271
+ stopReason?: string;
272
+ }
273
+ interface MetadataEvent {
274
+ usage?: {
275
+ inputTokens?: number;
276
+ outputTokens?: number;
277
+ cacheReadInputTokens?: number;
278
+ cacheWriteInputTokens?: number;
279
+ totalTokens?: number;
280
+ };
281
+ }
282
+
283
+ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
284
+ model: Model<"bedrock-converse-stream">,
285
+ context: Context,
286
+ options: BedrockOptions,
287
+ ): AssistantMessageEventStream => {
288
+ const stream = new AssistantMessageEventStream();
289
+
290
+ (async () => {
291
+ const startTime = performance.now();
292
+ let firstTokenTime: number | undefined;
293
+
294
+ const output: AssistantMessage = {
295
+ role: "assistant",
296
+ content: [],
297
+ api: "bedrock-converse-stream" as Api,
298
+ provider: model.provider,
299
+ model: model.id,
300
+ usage: {
301
+ input: 0,
302
+ output: 0,
303
+ cacheRead: 0,
304
+ cacheWrite: 0,
305
+ totalTokens: 0,
306
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
307
+ },
308
+ stopReason: "stop",
309
+ timestamp: Date.now(),
310
+ };
311
+
312
+ const blocks = output.content as Block[];
313
+ let rawRequestDump: RawHttpRequestDump | undefined;
314
+ const region = resolveBedrockRegion(model.id, options);
315
+
316
+ try {
317
+ const cacheRetention = resolveCacheRetention(options.cacheRetention);
318
+ const promptCachePolicy = resolvePromptCachePolicy(model, cacheRetention);
319
+ const convertedMessages = convertMessages(context, model, promptCachePolicy);
320
+ const toolPlan = planToolConfig(context.tools, options.toolChoice, convertedMessages);
321
+ const toolConfig = toolPlan.toolConfig;
322
+ const sentinelInjected = toolPlan.sentinelInjected;
323
+ let additionalModelRequestFields = buildAdditionalModelRequestFields(model, options);
324
+
325
+ // Bedrock rejects thinking + forced tool_choice ("any" or specific tool).
326
+ // When tool_choice forces tool use, disable thinking to avoid API errors.
327
+ if (toolConfig?.toolChoice && additionalModelRequestFields) {
328
+ const tc = toolConfig.toolChoice;
329
+ if (tc.any || tc.tool) additionalModelRequestFields = undefined;
330
+ }
331
+
332
+ const commandInput: ConverseStreamRequest = {
333
+ messages: convertedMessages,
334
+ system: buildSystemPrompt(context.systemPrompt, promptCachePolicy),
335
+ inferenceConfig: {
336
+ maxTokens: options.maxTokens,
337
+ temperature: options.temperature,
338
+ topP: options.topP,
339
+ },
340
+ toolConfig,
341
+ additionalModelRequestFields,
342
+ };
343
+ options?.onPayload?.(commandInput, model);
344
+
345
+ const host = `bedrock-runtime.${region}.amazonaws.com`;
346
+ const url = `https://${host}/model/${encodeURIComponent(model.id)}/converse-stream`;
347
+ const urlPath = `/model/${encodeURIComponent(model.id)}/converse-stream`;
348
+ rawRequestDump = {
349
+ provider: model.provider,
350
+ api: output.api,
351
+ model: model.id,
352
+ method: "POST",
353
+ url,
354
+ body: commandInput,
355
+ };
356
+
357
+ const bodyText = JSON.stringify(commandInput);
358
+ const body = new TextEncoder().encode(bodyText);
359
+ const baseHeaders: Record<string, string> = {
360
+ "content-type": "application/json",
361
+ accept: "application/vnd.amazon.eventstream",
362
+ };
363
+
364
+ const bearerToken = resolveBearerToken(options);
365
+ let requestHeaders: Record<string, string>;
366
+ if (bearerToken) {
367
+ requestHeaders = { ...baseHeaders, Authorization: `Bearer ${bearerToken}` };
368
+ } else {
369
+ let credentials: { accessKeyId: string; secretAccessKey: string; sessionToken?: string };
370
+ if ($flag("AWS_BEDROCK_SKIP_AUTH")) {
371
+ credentials = { accessKeyId: "dummy-access-key", secretAccessKey: "dummy-secret-key" };
372
+ } else {
373
+ credentials = await resolveAwsCredentials({
374
+ profile: options.profile,
375
+ region,
376
+ signal: options.signal,
377
+ fetch: options.fetch,
378
+ });
379
+ }
380
+ const signed = await signRequest({
381
+ method: "POST",
382
+ host,
383
+ path: urlPath,
384
+ body,
385
+ region,
386
+ service: "bedrock",
387
+ credentials,
388
+ headers: baseHeaders,
389
+ });
390
+ requestHeaders = { ...baseHeaders, ...signed };
391
+ }
392
+
393
+ // Bun's native fetch ceiling is disabled below (`timeout: false`) so
394
+ // configurable watchdogs govern slow-prefill streams (issue #2422).
395
+ // Direct callers that bypass `register-builtins` (which installs the
396
+ // iterator-level first-event watchdog) still need a pre-response
397
+ // timer, otherwise a Bedrock/proxy that accepts the POST and never
398
+ // sends headers would hang forever.
399
+ const firstEventTimeoutMs = options.streamFirstEventTimeoutMs ?? getStreamFirstEventTimeoutMs();
400
+ // Clear the pre-response timer the instant headers arrive (below): an
401
+ // absolute `AbortSignal.timeout` would keep aborting the actively
402
+ // streaming body, not just a stalled time-to-first-byte (issue #2422).
403
+ const watchdog = armPreResponseTimeout(options.signal, firstEventTimeoutMs);
404
+ let response: Response;
405
+ try {
406
+ response = await fetchWithRetry(url, {
407
+ method: "POST",
408
+ headers: requestHeaders,
409
+ body,
410
+ signal: watchdog.signal,
411
+ fetch: options.fetch,
412
+ timeout: false,
413
+ });
414
+ } finally {
415
+ watchdog.clear();
416
+ }
417
+
418
+ if (!response.ok) {
419
+ if (!bearerToken && (response.status === 401 || response.status === 403)) {
420
+ // Stale cached credentials (e.g. rotated session keys in ~/.aws/credentials) —
421
+ // drop the cache entry so the next attempt re-resolves from scratch.
422
+ invalidateAwsCredentialCache({ profile: options.profile, region });
423
+ }
424
+ const errBody = await response.text().catch(() => "");
425
+ throw new AIError.BedrockApiError(
426
+ `Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}`,
427
+ response.status,
428
+ {
429
+ headers: response.headers,
430
+ },
431
+ );
432
+ }
433
+ if (!response.body) throw new AIError.BedrockApiError("Bedrock response has no body", response.status);
434
+
435
+ // Track first event for the abort/diagnostic path (currently informational).
436
+ for await (const message of decodeEventStream(response.body)) {
437
+ const messageType = message.headers[":message-type"];
438
+ const eventType = message.headers[":event-type"];
439
+
440
+ if (messageType === "exception") {
441
+ const exceptionType = message.headers[":exception-type"] || "Exception";
442
+ const payload = safeParsePayload(message.payload) as { message?: string } | undefined;
443
+ const errorMessage = payload?.message || new TextDecoder().decode(message.payload);
444
+ const text = `${exceptionType}: ${errorMessage}`;
445
+ throw new AIError.BedrockApiError(text, 400, { code: exceptionType });
446
+ }
447
+ if (messageType === "error") {
448
+ const code = message.headers[":error-code"] || "UnknownError";
449
+ const errorMessage = message.headers[":error-message"] || new TextDecoder().decode(message.payload);
450
+ throw new AIError.BedrockApiError(`${code}: ${errorMessage}`, 400, { code });
451
+ }
452
+ if (messageType !== "event") continue;
453
+
454
+ const payload = safeParsePayload(message.payload);
455
+ if (!payload) continue;
456
+
457
+ switch (eventType) {
458
+ case "messageStart": {
459
+ // no-op: first event marker is implicit by stream entry.
460
+ const ev = payload as MessageStartEvent;
461
+ if (ev.role !== "assistant") {
462
+ throw new AIError.BedrockApiError(
463
+ "Unexpected assistant message start but got user message start instead",
464
+ 0,
465
+ );
466
+ }
467
+ stream.push({ type: "start", partial: output });
468
+ break;
469
+ }
470
+ case "contentBlockStart": {
471
+ if (!firstTokenTime) firstTokenTime = performance.now();
472
+ handleContentBlockStart(payload as ContentBlockStartEvent, blocks, output, stream, sentinelInjected);
473
+ break;
474
+ }
475
+ case "contentBlockDelta": {
476
+ if (!firstTokenTime) firstTokenTime = performance.now();
477
+ handleContentBlockDelta(payload as ContentBlockDeltaEvent, blocks, output, stream);
478
+ break;
479
+ }
480
+ case "contentBlockStop": {
481
+ handleContentBlockStop(payload as ContentBlockStopEvent, blocks, output, stream);
482
+ break;
483
+ }
484
+ case "messageStop": {
485
+ const ev = payload as MessageStopEvent;
486
+ // A sentinel-only request must never surface a tool-use stop:
487
+ // no real tool exists for the agent to dispatch.
488
+ output.stopReason =
489
+ sentinelInjected && ev.stopReason === "tool_use" ? "stop" : mapStopReason(ev.stopReason);
490
+ if (output.stopReason === "error") {
491
+ output.errorMessage = `Generation failed with stop reason: ${ev.stopReason ?? "unknown"}`;
492
+ }
493
+ break;
494
+ }
495
+ case "metadata": {
496
+ handleMetadata(payload as MetadataEvent, model, output);
497
+ break;
498
+ }
499
+ default:
500
+ // Unknown event types (Bedrock may add new ones) — ignore.
501
+ break;
502
+ }
503
+ }
504
+
505
+ if (options.signal?.aborted) throw new AIError.AbortError();
506
+
507
+ if (output.stopReason === "error" || output.stopReason === "aborted") {
508
+ throw new AIError.BedrockApiError(output.errorMessage ?? "An unknown error occurred", 0);
509
+ }
510
+
511
+ output.duration = performance.now() - startTime;
512
+ if (firstTokenTime) output.ttft = firstTokenTime - startTime;
513
+ stream.push({ type: "done", reason: output.stopReason, message: output });
514
+ stream.end();
515
+ } catch (error) {
516
+ for (const block of output.content) {
517
+ if (block.type === "toolCall") clearStreamingPartialJson(block);
518
+ }
519
+ let baseMessage: string;
520
+ try {
521
+ baseMessage = error instanceof Error ? error.message : (JSON.stringify(error) ?? String(error));
522
+ } catch {
523
+ baseMessage = String(error);
524
+ }
525
+ // Enrich error with thinking block diagnostics for signature-related failures
526
+ let diagnostics = "";
527
+ if (baseMessage.includes("signature") || baseMessage.includes("thinking")) {
528
+ const thinkingBlocks = context.messages
529
+ .filter((m): m is AssistantMessage => m.role === "assistant")
530
+ .flatMap((m, mi) =>
531
+ m.content
532
+ .filter(b => b.type === "thinking")
533
+ .map((b, bi) => ({
534
+ msg: mi,
535
+ block: bi,
536
+ stop: m.stopReason,
537
+ sigLen: b.thinkingSignature?.length ?? -1,
538
+ thinkLen: b.thinking.length,
539
+ })),
540
+ );
541
+ if (thinkingBlocks.length > 0) {
542
+ diagnostics = `\n[thinking-diag] ${JSON.stringify(thinkingBlocks)}`;
543
+ }
544
+ }
545
+ const result = await AIError.finalize(error, { api: model.api, signal: options.signal, rawRequestDump });
546
+ output.stopReason = result.stopReason;
547
+ output.errorStatus = result.status;
548
+ output.errorId = result.id;
549
+ output.errorMessage = result.message + diagnostics;
550
+ output.duration = performance.now() - startTime;
551
+ if (firstTokenTime) output.ttft = firstTokenTime - startTime;
552
+ stream.push({ type: "error", reason: output.stopReason, error: output });
553
+ stream.end();
554
+ }
555
+ })();
556
+
557
+ return stream;
558
+ };
559
+
560
+ function safeParsePayload(payload: Uint8Array): unknown {
561
+ if (payload.length === 0) return {};
562
+ try {
563
+ return JSON.parse(new TextDecoder().decode(payload));
564
+ } catch {
565
+ return undefined;
566
+ }
567
+ }
568
+
569
+ function handleContentBlockStart(
570
+ event: ContentBlockStartEvent,
571
+ blocks: Block[],
572
+ output: AssistantMessage,
573
+ stream: AssistantMessageEventStream,
574
+ sentinelInjected: boolean,
575
+ ): void {
576
+ const index = event.contentBlockIndex;
577
+ const start = event.start;
578
+
579
+ // Drop the sentinel call only when we injected it ourselves. A caller that
580
+ // registers a real tool named `__no_tools__` would otherwise lose its
581
+ // legitimate tool-use events on normal turns.
582
+ if (sentinelInjected && start?.toolUse?.name === NO_TOOLS_SENTINEL_NAME) return;
583
+
584
+ if (start?.toolUse) {
585
+ const block: Block = {
586
+ type: "toolCall",
587
+ id: normalizeToolCallId(start.toolUse.toolUseId || ""),
588
+ name: start.toolUse.name || "",
589
+ arguments: {},
590
+ [kStreamingPartialJson]: "",
591
+ [kStreamingBlockIndex]: index,
592
+ };
593
+ output.content.push(block);
594
+ stream.push({ type: "toolcall_start", contentIndex: blocks.length - 1, partial: output });
595
+ }
596
+ }
597
+
598
+ function handleContentBlockDelta(
599
+ event: ContentBlockDeltaEvent,
600
+ blocks: Block[],
601
+ output: AssistantMessage,
602
+ stream: AssistantMessageEventStream,
603
+ ): void {
604
+ const contentBlockIndex = event.contentBlockIndex;
605
+ const delta = event.delta;
606
+ let index = blocks.findIndex(b => b[kStreamingBlockIndex] === contentBlockIndex);
607
+ let block = blocks[index];
608
+
609
+ if (delta?.text !== undefined) {
610
+ // If no text block exists yet, create one — `handleContentBlockStart` is not sent for text blocks
611
+ if (!block) {
612
+ const newBlock: Block = { type: "text", text: "", [kStreamingBlockIndex]: contentBlockIndex };
613
+ output.content.push(newBlock);
614
+ index = blocks.length - 1;
615
+ block = blocks[index];
616
+ stream.push({ type: "text_start", contentIndex: index, partial: output });
617
+ }
618
+ if (block.type === "text") {
619
+ block.text += delta.text;
620
+ stream.push({ type: "text_delta", contentIndex: index, delta: delta.text, partial: output });
621
+ }
622
+ } else if (delta?.toolUse && block?.type === "toolCall") {
623
+ block[kStreamingPartialJson] = (block[kStreamingPartialJson] || "") + (delta.toolUse.input || "");
624
+ const throttled = parseStreamingJsonThrottled(block[kStreamingPartialJson], block[kStreamingLastParseLen] ?? 0);
625
+ if (throttled) {
626
+ block.arguments = throttled.value;
627
+ block[kStreamingLastParseLen] = throttled.parsedLen;
628
+ }
629
+ stream.push({ type: "toolcall_delta", contentIndex: index, delta: delta.toolUse.input || "", partial: output });
630
+ } else if (delta?.reasoningContent) {
631
+ let thinkingBlock = block;
632
+ let thinkingIndex = index;
633
+
634
+ if (!thinkingBlock) {
635
+ const newBlock: Block = {
636
+ type: "thinking",
637
+ thinking: "",
638
+ thinkingSignature: "",
639
+ [kStreamingBlockIndex]: contentBlockIndex,
640
+ };
641
+ output.content.push(newBlock);
642
+ thinkingIndex = blocks.length - 1;
643
+ thinkingBlock = blocks[thinkingIndex];
644
+ stream.push({ type: "thinking_start", contentIndex: thinkingIndex, partial: output });
645
+ }
646
+
647
+ if (thinkingBlock?.type === "thinking") {
648
+ if (delta.reasoningContent.text) {
649
+ thinkingBlock.thinking += delta.reasoningContent.text;
650
+ stream.push({
651
+ type: "thinking_delta",
652
+ contentIndex: thinkingIndex,
653
+ delta: delta.reasoningContent.text,
654
+ partial: output,
655
+ });
656
+ }
657
+ if (delta.reasoningContent.signature) {
658
+ thinkingBlock.thinkingSignature =
659
+ (thinkingBlock.thinkingSignature || "") + delta.reasoningContent.signature;
660
+ }
661
+ }
662
+ }
663
+ }
664
+
665
+ function handleMetadata(event: MetadataEvent, model: Model<"bedrock-converse-stream">, output: AssistantMessage): void {
666
+ if (event.usage) {
667
+ output.usage.input = event.usage.inputTokens || 0;
668
+ output.usage.output = event.usage.outputTokens || 0;
669
+ output.usage.cacheRead = event.usage.cacheReadInputTokens || 0;
670
+ output.usage.cacheWrite = event.usage.cacheWriteInputTokens || 0;
671
+ output.usage.totalTokens = event.usage.totalTokens || output.usage.input + output.usage.output;
672
+ calculateCost(model, output.usage);
673
+ }
674
+ }
675
+
676
+ function handleContentBlockStop(
677
+ event: ContentBlockStopEvent,
678
+ blocks: Block[],
679
+ output: AssistantMessage,
680
+ stream: AssistantMessageEventStream,
681
+ ): void {
682
+ const index = blocks.findIndex(b => b[kStreamingBlockIndex] === event.contentBlockIndex);
683
+ const block = blocks[index];
684
+ if (!block) return;
685
+
686
+ switch (block.type) {
687
+ case "text":
688
+ stream.push({ type: "text_end", contentIndex: index, content: block.text, partial: output });
689
+ break;
690
+ case "thinking":
691
+ stream.push({ type: "thinking_end", contentIndex: index, content: block.thinking, partial: output });
692
+ break;
693
+ case "toolCall":
694
+ block.arguments = parseStreamingJson(block[kStreamingPartialJson]);
695
+ clearStreamingPartialJson(block);
696
+ stream.push({ type: "toolcall_end", contentIndex: index, toolCall: block, partial: output });
697
+ break;
698
+ }
699
+ }
700
+
701
+ /**
702
+ * Resolve Bedrock's explicit-cache request policy from the catalog's
703
+ * materialized provider contract. Bedrock enforces each model's minimum
704
+ * prefix-token requirement, so this boundary intentionally does not locally
705
+ * count tokens. The emitter prioritizes the final user boundary, then the
706
+ * system boundary, without exceeding the configured checkpoint maximum.
707
+ *
708
+ * `AWS_BEDROCK_FORCE_CACHE` remains an escape hatch for opaque application
709
+ * inference profiles, defaulting those otherwise-unknown models to the
710
+ * existing two-checkpoint layout without inventing 1h retention.
711
+ */
712
+ function resolvePromptCachePolicy(
713
+ model: Model<"bedrock-converse-stream">,
714
+ cacheRetention: CacheRetention,
715
+ ): BedrockPromptCachePolicy {
716
+ if (cacheRetention === "none" || model.compat.promptCacheMode === "automatic") {
717
+ return { remainingCheckpoints: 0 };
718
+ }
719
+
720
+ const forced = $flag("AWS_BEDROCK_FORCE_CACHE");
721
+ const explicit = model.compat.promptCacheMode === "explicit";
722
+ if (!explicit && !forced) {
723
+ return { remainingCheckpoints: 0 };
724
+ }
725
+
726
+ const configuredMaximum = explicit ? model.compat.promptCacheMaximumCheckpoints : 2;
727
+ if (configuredMaximum <= 0) {
728
+ return { remainingCheckpoints: 0 };
729
+ }
730
+
731
+ return {
732
+ remainingCheckpoints: Math.min(configuredMaximum, 2),
733
+ ...(cacheRetention === "long" && model.compat.supportsLongPromptCacheRetention ? { ttl: "1h" } : {}),
734
+ };
735
+ }
736
+
737
+ function takeCachePoint(policy: BedrockPromptCachePolicy): CachePoint | undefined {
738
+ if (policy.remainingCheckpoints <= 0) return undefined;
739
+ policy.remainingCheckpoints--;
740
+ return { cachePoint: { type: "default", ...(policy.ttl ? { ttl: policy.ttl } : {}) } };
741
+ }
742
+
743
+ /**
744
+ * Check if the model supports thinking signatures in reasoningContent.
745
+ * Only Anthropic Claude models support the signature field.
746
+ * Other models (Nova, Titan, Mistral, Llama, etc.) reject it with:
747
+ * "This model doesn't support the reasoningContent.reasoningText.signature field"
748
+ */
749
+ function supportsThinkingSignature(model: Model<"bedrock-converse-stream">): boolean {
750
+ const id = model.id.toLowerCase();
751
+ return id.includes("anthropic.claude") || id.includes("anthropic/claude");
752
+ }
753
+
754
+ function buildSystemPrompt(
755
+ systemPrompt: readonly string[] | string | undefined,
756
+ promptCachePolicy: BedrockPromptCachePolicy,
757
+ ): SystemContent[] | undefined {
758
+ const prompts = normalizeSystemPrompts(systemPrompt);
759
+ if (prompts.length === 0) return undefined;
760
+
761
+ const blocks: SystemContent[] = prompts.map(prompt => ({ text: prompt }));
762
+
763
+ const cachePoint = takeCachePoint(promptCachePolicy);
764
+ if (cachePoint) blocks.push(cachePoint);
765
+
766
+ return blocks;
767
+ }
768
+
769
+ function convertMessages(
770
+ context: Context,
771
+ model: Model<"bedrock-converse-stream">,
772
+ promptCachePolicy: BedrockPromptCachePolicy,
773
+ ): WireMessage[] {
774
+ const result: WireMessage[] = [];
775
+ const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
776
+
777
+ for (let i = 0; i < transformedMessages.length; i++) {
778
+ const m = transformedMessages[i];
779
+
780
+ switch (m.role) {
781
+ case "developer":
782
+ case "user":
783
+ if (typeof m.content === "string") {
784
+ // Skip empty user messages
785
+ if (!m.content || m.content.trim() === "") continue;
786
+ result.push({ role: "user", content: [{ text: m.content.toWellFormed() }] });
787
+ } else {
788
+ const contentBlocks: UserContent[] = [];
789
+ for (const c of m.content) {
790
+ switch (c.type) {
791
+ case "text": {
792
+ const text = c.text.toWellFormed();
793
+ if (text.trim().length === 0) continue;
794
+ contentBlocks.push({ text });
795
+ break;
796
+ }
797
+ case "image":
798
+ contentBlocks.push({ image: createImageBlock(c.mimeType, c.data) });
799
+ break;
800
+ default:
801
+ throw new AIError.ValidationError("Unknown user content type");
802
+ }
803
+ }
804
+ // Skip message if all blocks filtered out
805
+ if (contentBlocks.length === 0) continue;
806
+ result.push({ role: "user", content: contentBlocks });
807
+ }
808
+ break;
809
+ case "assistant": {
810
+ // Skip assistant messages with empty content (e.g., from aborted requests)
811
+ // Bedrock rejects messages with empty content arrays
812
+ if (m.content.length === 0) continue;
813
+ const contentBlocks: AssistantContent[] = [];
814
+ for (const c of m.content) {
815
+ switch (c.type) {
816
+ case "text":
817
+ // Skip empty text blocks
818
+ if (c.text.trim().length === 0) continue;
819
+ contentBlocks.push({ text: c.text.toWellFormed() });
820
+ break;
821
+ case "toolCall":
822
+ contentBlocks.push({
823
+ toolUse: {
824
+ toolUseId: normalizeToolCallId(c.id),
825
+ name: c.name,
826
+ input: c.arguments,
827
+ },
828
+ });
829
+ break;
830
+ case "thinking":
831
+ // Skip empty thinking blocks
832
+ if (c.thinking.trim().length === 0) continue;
833
+ // A captured signature is authoritative even when the model id is an opaque ARN.
834
+ // Without one, known non-Claude families use unsigned reasoning; known Claude ids demote to text.
835
+ if (c.thinkingSignature) {
836
+ contentBlocks.push({
837
+ reasoningContent: {
838
+ reasoningText: { text: c.thinking.toWellFormed(), signature: c.thinkingSignature },
839
+ },
840
+ });
841
+ } else if (!supportsThinkingSignature(model)) {
842
+ // Model doesn't support signatures at all — send as unsigned reasoning
843
+ contentBlocks.push({
844
+ reasoningContent: { reasoningText: { text: c.thinking.toWellFormed() } },
845
+ });
846
+ } else {
847
+ // Model requires signature but we don't have one — demote to text
848
+ contentBlocks.push({ text: renderDemotedThinking(model.id, c.thinking) });
849
+ }
850
+ break;
851
+ default:
852
+ throw new AIError.ValidationError("Unknown assistant content type");
853
+ }
854
+ }
855
+ // Skip if all content blocks were filtered out
856
+ if (contentBlocks.length === 0) continue;
857
+ result.push({ role: "assistant", content: contentBlocks });
858
+ break;
859
+ }
860
+ case "toolResult": {
861
+ // Collect all consecutive toolResult messages into a single user message —
862
+ // Bedrock requires all tool results to be in one message.
863
+ const toolResults: ToolResultBlockWire[] = [];
864
+ toolResults.push({
865
+ toolResult: {
866
+ toolUseId: normalizeToolCallId(m.toolCallId),
867
+ content: m.content.map(c =>
868
+ c.type === "image"
869
+ ? { image: createImageBlock(c.mimeType, c.data) }
870
+ : { text: c.text.toWellFormed() },
871
+ ),
872
+ status: m.isError ? "error" : "success",
873
+ },
874
+ });
875
+
876
+ let j = i + 1;
877
+ while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
878
+ const nextMsg = transformedMessages[j] as ToolResultMessage;
879
+ toolResults.push({
880
+ toolResult: {
881
+ toolUseId: normalizeToolCallId(nextMsg.toolCallId),
882
+ content: nextMsg.content.map(c =>
883
+ c.type === "image"
884
+ ? { image: createImageBlock(c.mimeType, c.data) }
885
+ : { text: c.text.toWellFormed() },
886
+ ),
887
+ status: nextMsg.isError ? "error" : "success",
888
+ },
889
+ });
890
+ j++;
891
+ }
892
+ i = j - 1;
893
+
894
+ result.push({ role: "user", content: toolResults });
895
+ break;
896
+ }
897
+ default:
898
+ throw new AIError.ValidationError("Unknown message role");
899
+ }
900
+ }
901
+
902
+ // Prioritize the final user checkpoint; buildSystemPrompt consumes any
903
+ // remaining configured capacity afterward.
904
+ if (result.length > 0) {
905
+ const lastMessage = result[result.length - 1];
906
+ if (lastMessage.role === "user" && lastMessage.content) {
907
+ const cachePoint = takeCachePoint(promptCachePolicy);
908
+ if (cachePoint) (lastMessage.content as UserContent[]).push(cachePoint);
909
+ }
910
+ }
911
+
912
+ return result;
913
+ }
914
+
915
+ function messagesHaveToolBlocks(messages: WireMessage[]): boolean {
916
+ for (const message of messages) {
917
+ for (const block of message.content) {
918
+ if ("toolUse" in block || "toolResult" in block) return true;
919
+ }
920
+ }
921
+ return false;
922
+ }
923
+
924
+ function convertToolSpec(tool: Tool): WireToolSpec {
925
+ return {
926
+ toolSpec: {
927
+ name: tool.name,
928
+ description: tool.description || "",
929
+ inputSchema: { json: toolWireSchema(tool) },
930
+ },
931
+ };
932
+ }
933
+
934
+ function planToolConfig(
935
+ tools: Tool[] | undefined,
936
+ toolChoice: BedrockOptions["toolChoice"],
937
+ messages: WireMessage[],
938
+ ): BedrockToolPlan {
939
+ const activeTools = tools ?? [];
940
+ const hasTools = activeTools.length > 0;
941
+ const historyHasToolBlocks = messagesHaveToolBlocks(messages);
942
+
943
+ if (toolChoice === "none") {
944
+ if (!historyHasToolBlocks) return { toolConfig: undefined, sentinelInjected: false };
945
+ if (!hasTools) {
946
+ return {
947
+ toolConfig: { tools: [NO_TOOLS_SENTINEL], toolChoice: { auto: {} } },
948
+ sentinelInjected: true,
949
+ };
950
+ }
951
+ return { toolConfig: { tools: activeTools.map(convertToolSpec) }, sentinelInjected: false };
952
+ }
953
+
954
+ if (!hasTools) return { toolConfig: undefined, sentinelInjected: false };
955
+
956
+ const bedrockTools = activeTools.map(convertToolSpec);
957
+ let bedrockToolChoice: WireToolChoice | undefined;
958
+ switch (toolChoice) {
959
+ case "auto":
960
+ bedrockToolChoice = { auto: {} };
961
+ break;
962
+ case "any":
963
+ bedrockToolChoice = { any: {} };
964
+ break;
965
+ default:
966
+ if (toolChoice?.type === "tool") {
967
+ bedrockToolChoice = { tool: { name: toolChoice.name } };
968
+ }
969
+ }
970
+
971
+ return { toolConfig: { tools: bedrockTools, toolChoice: bedrockToolChoice }, sentinelInjected: false };
972
+ }
973
+
974
+ function mapStopReason(reason: string | undefined): StopReason {
975
+ switch (reason) {
976
+ case "end_turn":
977
+ case "stop_sequence":
978
+ return "stop";
979
+ case "max_tokens":
980
+ case "model_context_window_exceeded":
981
+ return "length";
982
+ case "tool_use":
983
+ return "toolUse";
984
+ default:
985
+ return "error";
986
+ }
987
+ }
988
+
989
+ function buildAdditionalModelRequestFields(
990
+ model: Model<"bedrock-converse-stream">,
991
+ options: BedrockOptions,
992
+ ): Record<string, unknown> | undefined {
993
+ const reasoning = options.reasoning;
994
+ if (!reasoning || !model.reasoning) return undefined;
995
+
996
+ const mode = model.thinking?.mode;
997
+ if (mode === "anthropic-adaptive") {
998
+ const effort = mapEffortToAnthropicAdaptiveEffort(model, reasoning);
999
+ // Starting with Claude Opus 4.7 and Claude Fable/Mythos 5, Anthropic switched
1000
+ // the adaptive-thinking default to "omitted", which silently suppresses
1001
+ // streamed reasoning and can read as a stalled stream during long reasoning
1002
+ // runs (issue #1373). Opt back into "summarized" by default on models that
1003
+ // accept the field.
1004
+ const adaptive: { type: "adaptive"; display?: BedrockThinkingDisplay } = { type: "adaptive" };
1005
+ if (model.thinking?.supportsDisplay) {
1006
+ adaptive.display = options.thinkingDisplay ?? "summarized";
1007
+ }
1008
+ return {
1009
+ thinking: adaptive,
1010
+ output_config: { effort },
1011
+ };
1012
+ }
1013
+
1014
+ const level = requireSupportedEffort(model, reasoning);
1015
+ const defaultBudgets: Record<Effort, number> = {
1016
+ minimal: 1024,
1017
+ low: 2048,
1018
+ medium: 8192,
1019
+ high: 16384,
1020
+ xhigh: 32768,
1021
+ max: 32768,
1022
+ };
1023
+ const budget = options.thinkingBudgets?.[level] ?? defaultBudgets[level];
1024
+
1025
+ const result: Record<string, unknown> = {
1026
+ thinking: {
1027
+ type: "enabled",
1028
+ budget_tokens: budget,
1029
+ display: options.thinkingDisplay ?? "summarized",
1030
+ },
1031
+ };
1032
+
1033
+ if (options.interleavedThinking) {
1034
+ result.anthropic_beta = ["interleaved-thinking-2025-05-14"];
1035
+ }
1036
+
1037
+ return result;
1038
+ }
1039
+
1040
+ /**
1041
+ * Bedrock's wire format expects the image as `{ source: { bytes: <base64-string> }, format }`.
1042
+ * The caller already passes base64-encoded data, so no decode/re-encode round-trip is needed.
1043
+ */
1044
+ function createImageBlock(mimeType: string, data: string): ImageBlockWire["image"] {
1045
+ let format: "jpeg" | "png" | "gif" | "webp";
1046
+ switch (mimeType) {
1047
+ case "image/jpeg":
1048
+ case "image/jpg":
1049
+ format = "jpeg";
1050
+ break;
1051
+ case "image/png":
1052
+ format = "png";
1053
+ break;
1054
+ case "image/gif":
1055
+ format = "gif";
1056
+ break;
1057
+ case "image/webp":
1058
+ format = "webp";
1059
+ break;
1060
+ default:
1061
+ throw new AIError.ValidationError(`Unknown image type: ${mimeType}`);
1062
+ }
1063
+ return { source: { bytes: data }, format };
1064
+ }