@draht/ai 2026.10.20-1 → 2026.10.23-1

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 (269) hide show
  1. package/dist/api/anthropic-messages.d.ts.map +1 -1
  2. package/dist/api/anthropic-messages.js +155 -111
  3. package/dist/api/anthropic-messages.js.map +1 -1
  4. package/dist/api/azure-openai-config.d.ts +15 -0
  5. package/dist/api/azure-openai-config.d.ts.map +1 -0
  6. package/dist/api/azure-openai-config.js +76 -0
  7. package/dist/api/azure-openai-config.js.map +1 -0
  8. package/dist/api/azure-openai-responses.d.ts +3 -6
  9. package/dist/api/azure-openai-responses.d.ts.map +1 -1
  10. package/dist/api/azure-openai-responses.js +19 -83
  11. package/dist/api/azure-openai-responses.js.map +1 -1
  12. package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  13. package/dist/api/bedrock-converse-stream.js +86 -22
  14. package/dist/api/bedrock-converse-stream.js.map +1 -1
  15. package/dist/api/classifier-shared.d.ts +21 -0
  16. package/dist/api/classifier-shared.d.ts.map +1 -0
  17. package/dist/api/classifier-shared.js +99 -0
  18. package/dist/api/classifier-shared.js.map +1 -0
  19. package/dist/api/cloudflare-workers-ai-system-one.d.ts.map +1 -1
  20. package/dist/api/cloudflare-workers-ai-system-one.js +15 -9
  21. package/dist/api/cloudflare-workers-ai-system-one.js.map +1 -1
  22. package/dist/api/google-generative-ai.js +4 -4
  23. package/dist/api/google-generative-ai.js.map +1 -1
  24. package/dist/api/google-shared.d.ts.map +1 -1
  25. package/dist/api/google-shared.js +3 -1
  26. package/dist/api/google-shared.js.map +1 -1
  27. package/dist/api/google-vertex.d.ts.map +1 -1
  28. package/dist/api/google-vertex.js +9 -9
  29. package/dist/api/google-vertex.js.map +1 -1
  30. package/dist/api/lazy.d.ts +7 -2
  31. package/dist/api/lazy.d.ts.map +1 -1
  32. package/dist/api/lazy.js +28 -8
  33. package/dist/api/lazy.js.map +1 -1
  34. package/dist/api/llama-cpp-classify.d.ts.map +1 -1
  35. package/dist/api/llama-cpp-classify.js +4 -1
  36. package/dist/api/llama-cpp-classify.js.map +1 -1
  37. package/dist/api/mistral-conversations.d.ts.map +1 -1
  38. package/dist/api/mistral-conversations.js +38 -18
  39. package/dist/api/mistral-conversations.js.map +1 -1
  40. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  41. package/dist/api/openai-codex-responses.js +21 -13
  42. package/dist/api/openai-codex-responses.js.map +1 -1
  43. package/dist/api/openai-completions.d.ts.map +1 -1
  44. package/dist/api/openai-completions.js +49 -38
  45. package/dist/api/openai-completions.js.map +1 -1
  46. package/dist/api/openai-decisions.d.ts +4 -0
  47. package/dist/api/openai-decisions.d.ts.map +1 -0
  48. package/dist/api/openai-decisions.js +162 -0
  49. package/dist/api/openai-decisions.js.map +1 -0
  50. package/dist/api/openai-decisions.lazy.d.ts +3 -0
  51. package/dist/api/openai-decisions.lazy.d.ts.map +1 -0
  52. package/dist/api/openai-decisions.lazy.js +4 -0
  53. package/dist/api/openai-decisions.lazy.js.map +1 -0
  54. package/dist/api/openai-responses-shared.d.ts +26 -0
  55. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  56. package/dist/api/openai-responses-shared.js +82 -16
  57. package/dist/api/openai-responses-shared.js.map +1 -1
  58. package/dist/api/openai-responses.d.ts.map +1 -1
  59. package/dist/api/openai-responses.js +47 -18
  60. package/dist/api/openai-responses.js.map +1 -1
  61. package/dist/api/openrouter-images.d.ts.map +1 -1
  62. package/dist/api/openrouter-images.js +4 -3
  63. package/dist/api/openrouter-images.js.map +1 -1
  64. package/dist/api/pi-messages.d.ts.map +1 -1
  65. package/dist/api/pi-messages.js +3 -3
  66. package/dist/api/pi-messages.js.map +1 -1
  67. package/dist/api/simple-options.d.ts +2 -1
  68. package/dist/api/simple-options.d.ts.map +1 -1
  69. package/dist/api/simple-options.js +12 -2
  70. package/dist/api/simple-options.js.map +1 -1
  71. package/dist/api/system-one-shared.d.ts +0 -1
  72. package/dist/api/system-one-shared.d.ts.map +1 -1
  73. package/dist/api/system-one-shared.js +5 -89
  74. package/dist/api/system-one-shared.js.map +1 -1
  75. package/dist/api/transform-messages.d.ts +16 -1
  76. package/dist/api/transform-messages.d.ts.map +1 -1
  77. package/dist/api/transform-messages.js +28 -15
  78. package/dist/api/transform-messages.js.map +1 -1
  79. package/dist/api/typesafe-system-one.d.ts.map +1 -1
  80. package/dist/api/typesafe-system-one.js +2 -1
  81. package/dist/api/typesafe-system-one.js.map +1 -1
  82. package/dist/auth/oauth/anthropic.d.ts.map +1 -1
  83. package/dist/auth/oauth/anthropic.js +65 -7
  84. package/dist/auth/oauth/anthropic.js.map +1 -1
  85. package/dist/auth/oauth/load.d.ts +2 -0
  86. package/dist/auth/oauth/load.d.ts.map +1 -1
  87. package/dist/auth/oauth/load.js +5 -0
  88. package/dist/auth/oauth/load.js.map +1 -1
  89. package/dist/auth/oauth/openai-chatgpt.d.ts.map +1 -1
  90. package/dist/auth/oauth/openai-chatgpt.js +11 -14
  91. package/dist/auth/oauth/openai-chatgpt.js.map +1 -1
  92. package/dist/auth/oauth/openai-codex.d.ts.map +1 -1
  93. package/dist/auth/oauth/openai-codex.js +7 -5
  94. package/dist/auth/oauth/openai-codex.js.map +1 -1
  95. package/dist/auth/oauth/opencode-go.d.ts +3 -12
  96. package/dist/auth/oauth/opencode-go.d.ts.map +1 -1
  97. package/dist/auth/oauth/opencode-go.js +229 -34
  98. package/dist/auth/oauth/opencode-go.js.map +1 -1
  99. package/dist/auth/resolve.d.ts +16 -1
  100. package/dist/auth/resolve.d.ts.map +1 -1
  101. package/dist/auth/resolve.js +51 -27
  102. package/dist/auth/resolve.js.map +1 -1
  103. package/dist/auth/types.d.ts +5 -0
  104. package/dist/auth/types.d.ts.map +1 -1
  105. package/dist/auth/types.js.map +1 -1
  106. package/dist/bun-oauth.d.ts.map +1 -1
  107. package/dist/bun-oauth.js +2 -1
  108. package/dist/bun-oauth.js.map +1 -1
  109. package/dist/env-api-keys.js +1 -1
  110. package/dist/env-api-keys.js.map +1 -1
  111. package/dist/index.d.ts +2 -1
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +2 -1
  114. package/dist/index.js.map +1 -1
  115. package/dist/models.d.ts +9 -0
  116. package/dist/models.d.ts.map +1 -1
  117. package/dist/models.generated.d.ts +4 -4
  118. package/dist/models.generated.d.ts.map +1 -1
  119. package/dist/models.generated.js +4 -4
  120. package/dist/models.generated.js.map +1 -1
  121. package/dist/models.js +26 -14
  122. package/dist/models.js.map +1 -1
  123. package/dist/providers/all.js +2 -2
  124. package/dist/providers/all.js.map +1 -1
  125. package/dist/providers/azure.d.ts +3 -0
  126. package/dist/providers/azure.d.ts.map +1 -0
  127. package/dist/providers/azure.js +46 -0
  128. package/dist/providers/azure.js.map +1 -0
  129. package/dist/providers/azure.models.d.ts +6 -0
  130. package/dist/providers/azure.models.d.ts.map +1 -0
  131. package/dist/providers/azure.models.js +8 -0
  132. package/dist/providers/azure.models.js.map +1 -0
  133. package/dist/providers/compat-schema.d.ts +491 -0
  134. package/dist/providers/compat-schema.d.ts.map +1 -0
  135. package/dist/providers/compat-schema.js +386 -0
  136. package/dist/providers/compat-schema.js.map +1 -0
  137. package/dist/providers/data/.manifest.json +1 -1
  138. package/dist/providers/data/amazon-bedrock.json +1 -1
  139. package/dist/providers/data/anthropic.json +1 -1
  140. package/dist/providers/data/azure.json +1 -0
  141. package/dist/providers/data/baseten.json +1 -1
  142. package/dist/providers/data/cerebras.json +1 -1
  143. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  144. package/dist/providers/data/cloudflare-workers-ai.json +1 -1
  145. package/dist/providers/data/fireworks.json +1 -1
  146. package/dist/providers/data/github-copilot.json +1 -1
  147. package/dist/providers/data/google-vertex.json +1 -1
  148. package/dist/providers/data/google.json +1 -1
  149. package/dist/providers/data/groq.json +1 -1
  150. package/dist/providers/data/huggingface.json +1 -1
  151. package/dist/providers/data/kimi-coding.json +1 -1
  152. package/dist/providers/data/meta.json +1 -1
  153. package/dist/providers/data/minimax-cn.json +1 -1
  154. package/dist/providers/data/minimax.json +1 -1
  155. package/dist/providers/data/mistral.json +1 -1
  156. package/dist/providers/data/moonshotai-cn.json +1 -1
  157. package/dist/providers/data/nvidia.json +1 -1
  158. package/dist/providers/data/openai-codex.json +1 -1
  159. package/dist/providers/data/openai.json +1 -1
  160. package/dist/providers/data/opencode-go.json +1 -1
  161. package/dist/providers/data/opencode.json +1 -1
  162. package/dist/providers/data/openrouter.json +1 -1
  163. package/dist/providers/data/qwen-token-plan-cn.json +1 -1
  164. package/dist/providers/data/qwen-token-plan.json +1 -1
  165. package/dist/providers/data/radius.json +1 -1
  166. package/dist/providers/data/together.json +1 -1
  167. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  168. package/dist/providers/data/xai.json +1 -1
  169. package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
  170. package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
  171. package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
  172. package/dist/providers/data/xiaomi.json +1 -1
  173. package/dist/providers/data/zai-coding-cn.json +1 -1
  174. package/dist/providers/faux.d.ts.map +1 -1
  175. package/dist/providers/faux.js +25 -8
  176. package/dist/providers/faux.js.map +1 -1
  177. package/dist/providers/kimi-coding.d.ts +1 -1
  178. package/dist/providers/kimi-coding.js +3 -3
  179. package/dist/providers/kimi-coding.js.map +1 -1
  180. package/dist/providers/model-schema.d.ts +91 -0
  181. package/dist/providers/model-schema.d.ts.map +1 -0
  182. package/dist/providers/model-schema.js +57 -0
  183. package/dist/providers/model-schema.js.map +1 -0
  184. package/dist/providers/openai.d.ts.map +1 -1
  185. package/dist/providers/openai.js +12 -3
  186. package/dist/providers/openai.js.map +1 -1
  187. package/dist/providers/opencode-go.d.ts +3 -1
  188. package/dist/providers/opencode-go.d.ts.map +1 -1
  189. package/dist/providers/opencode-go.js +4 -3
  190. package/dist/providers/opencode-go.js.map +1 -1
  191. package/dist/providers/opencode.d.ts.map +1 -1
  192. package/dist/providers/opencode.js +10 -2
  193. package/dist/providers/opencode.js.map +1 -1
  194. package/dist/providers/openrouter-api.d.ts +40 -0
  195. package/dist/providers/openrouter-api.d.ts.map +1 -0
  196. package/dist/providers/openrouter-api.js +41 -0
  197. package/dist/providers/openrouter-api.js.map +1 -0
  198. package/dist/providers/openrouter.d.ts +11 -1
  199. package/dist/providers/openrouter.d.ts.map +1 -1
  200. package/dist/providers/openrouter.js +52 -1
  201. package/dist/providers/openrouter.js.map +1 -1
  202. package/dist/providers/radius.d.ts.map +1 -1
  203. package/dist/providers/radius.js +4 -12
  204. package/dist/providers/radius.js.map +1 -1
  205. package/dist/telemetry.d.ts +288 -0
  206. package/dist/telemetry.d.ts.map +1 -0
  207. package/dist/telemetry.js +191 -0
  208. package/dist/telemetry.js.map +1 -0
  209. package/dist/types.d.ts +42 -310
  210. package/dist/types.d.ts.map +1 -1
  211. package/dist/types.js.map +1 -1
  212. package/dist/utils/estimate.js +1 -1
  213. package/dist/utils/estimate.js.map +1 -1
  214. package/dist/utils/event-stream.d.ts +10 -1
  215. package/dist/utils/event-stream.d.ts.map +1 -1
  216. package/dist/utils/event-stream.js +25 -0
  217. package/dist/utils/event-stream.js.map +1 -1
  218. package/dist/utils/identity.d.ts +65 -0
  219. package/dist/utils/identity.d.ts.map +1 -0
  220. package/dist/utils/identity.js +145 -0
  221. package/dist/utils/identity.js.map +1 -0
  222. package/dist/utils/json-parse.d.ts +10 -0
  223. package/dist/utils/json-parse.d.ts.map +1 -1
  224. package/dist/utils/json-parse.js +26 -1
  225. package/dist/utils/json-parse.js.map +1 -1
  226. package/dist/utils/model-operations.d.ts +3 -1
  227. package/dist/utils/model-operations.d.ts.map +1 -1
  228. package/dist/utils/model-operations.js +6 -0
  229. package/dist/utils/model-operations.js.map +1 -1
  230. package/dist/utils/overflow.d.ts +1 -0
  231. package/dist/utils/overflow.d.ts.map +1 -1
  232. package/dist/utils/overflow.js +6 -1
  233. package/dist/utils/overflow.js.map +1 -1
  234. package/dist/utils/provider-retry.d.ts +2 -0
  235. package/dist/utils/provider-retry.d.ts.map +1 -1
  236. package/dist/utils/provider-retry.js +2 -0
  237. package/dist/utils/provider-retry.js.map +1 -1
  238. package/dist/utils/retry.d.ts.map +1 -1
  239. package/dist/utils/retry.js +30 -10
  240. package/dist/utils/retry.js.map +1 -1
  241. package/dist/utils/transcript.d.ts +27 -10
  242. package/dist/utils/transcript.d.ts.map +1 -1
  243. package/dist/utils/transcript.js +34 -20
  244. package/dist/utils/transcript.js.map +1 -1
  245. package/dist/utils/validation.d.ts.map +1 -1
  246. package/dist/utils/validation.js +3 -0
  247. package/dist/utils/validation.js.map +1 -1
  248. package/dist/utils/version.d.ts +2 -0
  249. package/dist/utils/version.d.ts.map +1 -0
  250. package/dist/utils/version.js +5 -0
  251. package/dist/utils/version.js.map +1 -0
  252. package/package.json +5 -5
  253. package/dist/providers/azure-openai-responses.d.ts +0 -3
  254. package/dist/providers/azure-openai-responses.d.ts.map +0 -1
  255. package/dist/providers/azure-openai-responses.js +0 -14
  256. package/dist/providers/azure-openai-responses.js.map +0 -1
  257. package/dist/providers/azure-openai-responses.models.d.ts +0 -6
  258. package/dist/providers/azure-openai-responses.models.d.ts.map +0 -1
  259. package/dist/providers/azure-openai-responses.models.js +0 -8
  260. package/dist/providers/azure-openai-responses.models.js.map +0 -1
  261. package/dist/providers/data/azure-openai-responses.json +0 -1
  262. package/dist/utils/assistant-message-frame.d.ts +0 -77
  263. package/dist/utils/assistant-message-frame.d.ts.map +0 -1
  264. package/dist/utils/assistant-message-frame.js +0 -425
  265. package/dist/utils/assistant-message-frame.js.map +0 -1
  266. package/dist/utils/draht-user-agent.d.ts +0 -2
  267. package/dist/utils/draht-user-agent.d.ts.map +0 -1
  268. package/dist/utils/draht-user-agent.js +0 -12
  269. package/dist/utils/draht-user-agent.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../src/api/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,SAAiC,MAAM,mBAAmB,CAAC;AAoBlE,OAAO,KAAK,EASX,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAMb,MAAM,aAAa,CAAC;AAqJrB,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AA2ChE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;AAwRD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,gBAAgB,CA0UzE,CAAC;AA2BF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CAgDlF,CAAC"}
1
+ {"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../src/api/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,SAAiC,MAAM,mBAAmB,CAAC;AAoBlE,OAAO,KAAK,EASX,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAMb,MAAM,aAAa,CAAC;AAuJrB,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AA2ChE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;AAoRD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,gBAAgB,CA2WzE,CAAC;AA2BF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CAgDlF,CAAC"}
@@ -2,19 +2,19 @@ import Anthropic, {} from "@anthropic-ai/sdk";
2
2
  import { ANTHROPIC_FEDERATION_RULE_ID_ENV, ANTHROPIC_IDENTITY_TOKEN_FILE_ENV, ANTHROPIC_ORGANIZATION_ID_ENV, ANTHROPIC_SERVICE_ACCOUNT_ID_ENV, ANTHROPIC_WORKSPACE_ID_ENV, } from "../env-api-keys.js";
3
3
  import { calculateCost } from "../models.js";
4
4
  import { appendAssistantMessageDiagnostic } from "../utils/diagnostics.js";
5
- import { getDrahtUserAgent } from "../utils/draht-user-agent.js";
6
5
  import { AssistantMessageEventStream } from "../utils/event-stream.js";
7
6
  import { headersToRecord } from "../utils/headers.js";
8
- import { parseJsonWithRepair, parseStreamingJson } from "../utils/json-parse.js";
7
+ import { getIdentityHeaders } from "../utils/identity.js";
8
+ import { parseJsonWithRepair, parseStreamingJson, parseToolCallArguments } from "../utils/json-parse.js";
9
9
  import { getProviderEnvValue } from "../utils/provider-env.js";
10
10
  import { retryProviderRequest } from "../utils/provider-retry.js";
11
11
  import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
12
12
  import { getSystemMessageText, renderSystemMessageUpdate } from "../utils/text.js";
13
- import { getCurrentTools, getDeclaredTools, getInitialSystemMessage, hasToolRedefinitions, resolveTranscript, } from "../utils/transcript.js";
13
+ import { getCurrentTools, getInitialSystemMessage, resolveTranscript, } from "../utils/transcript.js";
14
14
  import { getJsonSchemaToolParameters, resolveJsonSchemaStrictSampling, } from "./constrained-sampling.js";
15
15
  import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
16
16
  import { adjustMaxTokensForThinking, buildBaseOptions, clampMaxTokensToContext } from "./simple-options.js";
17
- import { transformMessages } from "./transform-messages.js";
17
+ import { splitErrorToolResultImages, transformMessages } from "./transform-messages.js";
18
18
  /**
19
19
  * Resolve cache retention preference.
20
20
  * Defaults to "short" and uses DRAHT_CACHE_RETENTION for backward compatibility.
@@ -75,6 +75,16 @@ const fromClaudeCodeName = (name, tools) => {
75
75
  }
76
76
  return name;
77
77
  };
78
+ function convertImageBlock(image) {
79
+ return {
80
+ type: "image",
81
+ source: {
82
+ type: "base64",
83
+ media_type: image.mimeType,
84
+ data: image.data,
85
+ },
86
+ };
87
+ }
78
88
  /**
79
89
  * Convert content blocks to Anthropic API format
80
90
  */
@@ -92,14 +102,7 @@ function convertContentBlocks(content) {
92
102
  text: sanitizeSurrogates(block.text),
93
103
  };
94
104
  }
95
- return {
96
- type: "image",
97
- source: {
98
- type: "base64",
99
- media_type: block.mimeType,
100
- data: block.data,
101
- },
102
- };
105
+ return convertImageBlock(block);
103
106
  });
104
107
  // If only images (no text), add placeholder text block
105
108
  const hasText = blocks.some((b) => b.type === "text");
@@ -116,16 +119,16 @@ const INTERLEAVED_THINKING_BETA = "interleaved-thinking-2025-05-14";
116
119
  const SERVER_SIDE_FALLBACK_BETA = "server-side-fallback-2026-07-01";
117
120
  const MID_CONVERSATION_OUTPUT_CONFIG_BETA = "mid-conversation-output-config-2026-07-01";
118
121
  const THINKING_BINDING_CONTROLS_BETA = "thinking-binding-controls-2026-08-01";
119
- const MID_CONVERSATION_TOOL_CHANGES_BETA = "mid-conversation-tool-changes-2026-07-01";
122
+ const INLINE_TOOLS_BETA = "inline-tools-2026-09-15";
120
123
  /**
121
124
  * Stable deferred tool declared whenever native tool changes are in use. Anthropic adds
122
- * hidden prompt scaffolding as soon as any tool has `defer_loading`; declaring this
123
- * placeholder from the first request keeps that scaffolding in the cached prefix, so the
124
- * first real late tool does not invalidate the cache (measured: full miss without it).
125
- * It is never activated and the model cannot see it.
125
+ * hidden prompt scaffolding for mid-conversation tool changes; declaring this placeholder
126
+ * from the first request keeps that scaffolding in the cached prefix, so the first tool
127
+ * change does not invalidate the cache (measured: full miss without it). It is never
128
+ * activated and the model cannot see it.
126
129
  */
127
130
  const DEFERRED_TOOL_PLACEHOLDER = {
128
- name: "__pi_deferred_placeholder__",
131
+ name: "__draht_deferred_placeholder__",
129
132
  description: "Reserved placeholder. Never available. Never call this.",
130
133
  input_schema: { type: "object", properties: {}, required: [] },
131
134
  defer_loading: true,
@@ -157,9 +160,6 @@ function mergeHeaders(...headerSources) {
157
160
  }
158
161
  return merged;
159
162
  }
160
- function mergeClientHeaders(...headerSources) {
161
- return mergeHeaders({ "User-Agent": getDrahtUserAgent() }, ...headerSources);
162
- }
163
163
  function hasHeader(headers, name) {
164
164
  if (!headers)
165
165
  return false;
@@ -378,14 +378,12 @@ export const stream = (model, context, options) => {
378
378
  const normalizedContext = resolveTranscript(context, getAnthropicCompat(model).supportsMidConvoSystemMessages);
379
379
  const currentTools = getCurrentTools(normalizedContext.messages);
380
380
  (async () => {
381
- const providerThinkingLevel = model.compat?.supportsMidConvoEffort ? (options?.effort ?? "high") : undefined;
382
381
  const output = {
383
382
  role: "assistant",
384
383
  content: [],
385
384
  api: model.api,
386
385
  provider: model.provider,
387
386
  model: model.id,
388
- ...(providerThinkingLevel === undefined ? {} : { providerThinkingLevel }),
389
387
  usage: {
390
388
  input: 0,
391
389
  output: 0,
@@ -421,25 +419,59 @@ export const stream = (model, context, options) => {
421
419
  }
422
420
  const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
423
421
  const cacheSessionId = cacheRetention === "none" ? undefined : options?.sessionId;
424
- const created = createClient(model, apiKey, options?.headers, options?.fetch, copilotDynamicHeaders, cacheSessionId, federation);
422
+ const created = createClient(model, apiKey, options?.headers, options?.fetch, copilotDynamicHeaders, cacheSessionId, federation, options?.identity);
425
423
  client = created.client;
426
424
  isOAuth = created.isOAuthToken;
427
425
  }
428
- let params = buildParams(model, normalizedContext, isOAuth, options);
429
- const nextParams = await options?.onPayload?.(params, model);
430
- if (nextParams !== undefined) {
431
- params = { ...nextParams, stream: true };
432
- }
433
426
  const requestOptions = {
434
427
  ...(options?.signal ? { signal: options.signal } : {}),
435
428
  ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
436
429
  maxRetries: 0,
437
430
  };
438
- const response = await retryProviderRequest(() => client.beta.messages.create(params, requestOptions).asResponse(), {
439
- maxRetries: options?.maxRetries,
440
- maxRetryDelayMs: options?.maxRetryDelayMs,
441
- signal: options?.signal,
442
- });
431
+ let disablePreferredStrictTools = false;
432
+ let response;
433
+ for (;;) {
434
+ options?.signal?.throwIfAborted();
435
+ const built = buildParams(model, normalizedContext, isOAuth, options, disablePreferredStrictTools);
436
+ if (built.providerThinkingLevel)
437
+ output.providerThinkingLevel = built.providerThinkingLevel;
438
+ let params = built.params;
439
+ const nextParams = await options?.onPayload?.(params, model);
440
+ if (nextParams !== undefined) {
441
+ params = { ...nextParams, stream: true };
442
+ }
443
+ try {
444
+ response = await retryProviderRequest(() => client.beta.messages.create(params, requestOptions).asResponse(), {
445
+ maxRetries: options?.maxRetries,
446
+ maxRetryDelayMs: options?.maxRetryDelayMs,
447
+ signal: options?.signal,
448
+ });
449
+ break;
450
+ }
451
+ catch (error) {
452
+ // Only downgrade a rejected request, never an already-started stream.
453
+ if (options?.signal?.aborted ||
454
+ disablePreferredStrictTools ||
455
+ !built.hasPreferredStrictTools ||
456
+ !(error instanceof Anthropic.APIError) ||
457
+ error.status !== 400 ||
458
+ error.type !== "invalid_request_error" ||
459
+ ![
460
+ "The compiled grammar is too large",
461
+ "Too many strict tools (",
462
+ "Schemas contains too many parameters with union types (",
463
+ ].some((message) => error.message.includes(message))) {
464
+ throw error;
465
+ }
466
+ disablePreferredStrictTools = true;
467
+ appendAssistantMessageDiagnostic(output, {
468
+ type: "anthropic_strict_tools_fallback",
469
+ timestamp: Date.now(),
470
+ error: { message: error.message },
471
+ details: { reason: "strict_tool_limits_exceeded" },
472
+ });
473
+ }
474
+ }
443
475
  await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
444
476
  stream.push({ type: "start", partial: output });
445
477
  const blocks = output.content;
@@ -593,7 +625,7 @@ export const stream = (model, context, options) => {
593
625
  });
594
626
  }
595
627
  else if (block.type === "toolCall") {
596
- block.arguments = parseStreamingJson(block.partialJson);
628
+ Object.assign(block, parseToolCallArguments(block.partialJson));
597
629
  // Finalize in-place and strip the scratch buffer so replay only
598
630
  // carries parsed arguments.
599
631
  delete block.partialJson;
@@ -748,7 +780,7 @@ export const streamSimple = (model, context, options) => {
748
780
  function isOAuthToken(apiKey) {
749
781
  return apiKey.includes("sk-ant-oat");
750
782
  }
751
- function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sessionId, federation) {
783
+ function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sessionId, federation, identity) {
752
784
  // Copilot: Bearer auth.
753
785
  if (model.provider === "github-copilot") {
754
786
  const client = new PiAnthropic({
@@ -757,14 +789,14 @@ function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sess
757
789
  baseURL: model.baseUrl,
758
790
  dangerouslyAllowBrowser: true,
759
791
  fetch,
760
- defaultHeaders: mergeClientHeaders({
792
+ defaultHeaders: mergeHeaders(getIdentityHeaders(model, identity), {
761
793
  accept: "application/json",
762
794
  "anthropic-dangerous-direct-browser-access": "true",
763
795
  }, model.headers, dynamicHeaders, optionsHeaders),
764
796
  });
765
797
  return { client, isOAuthToken: false };
766
798
  }
767
- // OAuth: Bearer auth, Claude Code identity headers
799
+ // OAuth: Bearer auth, Claude Code identity headers instead of the client identity.
768
800
  if (apiKey && isOAuthToken(apiKey)) {
769
801
  const client = new PiAnthropic({
770
802
  apiKey: null,
@@ -772,7 +804,7 @@ function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sess
772
804
  baseURL: model.baseUrl,
773
805
  dangerouslyAllowBrowser: true,
774
806
  fetch,
775
- defaultHeaders: mergeClientHeaders({
807
+ defaultHeaders: mergeHeaders({
776
808
  accept: "application/json",
777
809
  "anthropic-dangerous-direct-browser-access": "true",
778
810
  "user-agent": `claude-cli/${claudeCodeVersion}`,
@@ -788,7 +820,7 @@ function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sess
788
820
  const header = compat.sessionAffinityFormat === "openrouter" ? "x-session-id" : "x-session-affinity";
789
821
  sessionAffinityHeaders[header] = sessionId;
790
822
  }
791
- const defaultHeaders = mergeClientHeaders({
823
+ const defaultHeaders = mergeHeaders(getIdentityHeaders(model, identity), {
792
824
  accept: "application/json",
793
825
  "anthropic-dangerous-direct-browser-access": "true",
794
826
  }, sessionAffinityHeaders, model.headers, optionsHeaders);
@@ -852,32 +884,42 @@ function getBetaFeatures(model, context, isOAuthToken, nativeToolChanges, option
852
884
  features.push(MID_CONVERSATION_OUTPUT_CONFIG_BETA, THINKING_BINDING_CONTROLS_BETA);
853
885
  }
854
886
  if (nativeToolChanges)
855
- features.push(MID_CONVERSATION_TOOL_CHANGES_BETA);
887
+ features.push(INLINE_TOOLS_BETA);
856
888
  return [...new Set(features)];
857
889
  }
858
- function buildParams(model, context, isOAuthToken, options) {
890
+ function buildParams(model, context, isOAuthToken, options, disablePreferredStrictTools = false) {
859
891
  const { cacheControl } = getCacheControl(model, options?.cacheRetention, options?.env);
860
892
  const compat = getAnthropicCompat(model);
861
893
  const initialSystemMessage = getInitialSystemMessage(context.messages);
862
894
  const initialSystemText = initialSystemMessage ? getSystemMessageText(initialSystemMessage) : "";
863
895
  const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
864
896
  const conversationMessages = initialSystemMessage ? transformedMessages.slice(1) : transformedMessages;
865
- // Native tool changes reference tools by name, so a redefined name cannot be expressed,
866
- // and Anthropic rejects a tool list where every tool is deferred, so there must be an
867
- // initial active tool to anchor the deferred ones. Otherwise the current tool list is sent.
897
+ // Native tool changes keep the request-level tool list fixed and define every later tool
898
+ // by value in a `tool_addition` block, which also expresses same-name redefinitions.
899
+ // Anthropic rejects a tool list where every tool is deferred, so there must be an initial
900
+ // active tool to anchor the placeholder. Otherwise the current tool list is sent.
901
+ let hasPreferredStrictTools = false;
902
+ const convertToolDefinitions = (tools, toolCacheControl) => {
903
+ const definitions = convertTools(tools, isOAuthToken, compat.supportsEagerToolInputStreaming, compat.supportsStrictTools, toolCacheControl, disablePreferredStrictTools);
904
+ if (definitions.some((definition, index) => {
905
+ const config = tools[index].constrainedSampling;
906
+ return definition.strict === true && config && config.type === "json_schema" && config.strict === "prefer";
907
+ })) {
908
+ hasPreferredStrictTools = true;
909
+ }
910
+ return definitions;
911
+ };
868
912
  const initialTools = initialSystemMessage?.toolsAdded ?? [];
869
- const nativeToolChanges = compat.supportsMidConvoSystemMessages &&
870
- compat.supportsMidConvoToolChanges &&
871
- initialTools.length > 0 &&
872
- !hasToolRedefinitions(context.messages);
873
- const converted = convertMessages(conversationMessages, isOAuthToken, cacheControl, compat.allowEmptySignature, model.compat?.supportsMidConvoEffort === true ? model.provider : undefined, nativeToolChanges);
913
+ const nativeToolChanges = compat.supportsMidConvoSystemMessages && compat.supportsMidConvoToolChanges && initialTools.length > 0;
914
+ const thinkingDisabled = model.reasoning && options?.thinkingEnabled === false && model.thinkingLevelMap?.off !== null;
915
+ // Effort cannot change between messages while thinking is disabled, so "off" sends no effort markers.
916
+ const effortMessages = model.compat?.supportsMidConvoEffort === true && !thinkingDisabled;
917
+ const converted = convertMessages(conversationMessages, isOAuthToken, cacheControl, compat.allowEmptySignature, effortMessages ? model.provider : undefined, nativeToolChanges ? convertToolDefinitions : undefined);
874
918
  const activeEffort = options?.effort ?? "high";
875
919
  const betaFeatures = getBetaFeatures(model, context, isOAuthToken, nativeToolChanges, options);
876
920
  const params = {
877
921
  model: model.id,
878
- messages: model.compat?.supportsMidConvoEffort === true
879
- ? insertThinkingLevelMessages(converted, activeEffort)
880
- : converted.messages,
922
+ messages: effortMessages ? insertThinkingLevelMessages(converted, activeEffort) : converted.messages,
881
923
  max_tokens: options?.maxTokens ?? model.maxTokens,
882
924
  stream: true,
883
925
  ...(betaFeatures.length > 0 ? { betas: betaFeatures } : {}),
@@ -918,27 +960,26 @@ function buildParams(model, context, isOAuthToken, options) {
918
960
  }
919
961
  const toolCacheControl = compat.supportsCacheControlOnTools ? cacheControl : undefined;
920
962
  if (nativeToolChanges) {
921
- // Initial tools stay active with the cache breakpoint on the last one. Every later
922
- // declaration is deferred and only surfaced by its `tool_addition` block; removed
923
- // tools stay declared and are withdrawn by `tool_removal`. The request-level list
924
- // therefore only grows, keeping the cached prefix intact across tool changes.
925
- const initialNames = new Set(initialTools.map((tool) => tool.name));
926
- const laterTools = getDeclaredTools(context.messages).filter((tool) => !initialNames.has(tool.name));
927
- params.tools = [
928
- ...convertTools(initialTools, isOAuthToken, compat.supportsEagerToolInputStreaming, compat.supportsStrictTools, toolCacheControl),
929
- DEFERRED_TOOL_PLACEHOLDER,
930
- ...convertTools(laterTools, isOAuthToken, compat.supportsEagerToolInputStreaming, compat.supportsStrictTools).map((tool) => ({ ...tool, defer_loading: true })),
931
- ];
963
+ // Initial tools stay active with the cache breakpoint on the last one, followed by the
964
+ // placeholder. The list never changes afterwards: later tools are defined by value in
965
+ // `tool_addition` blocks and withdrawn by `tool_removal`, so the cached prefix survives
966
+ // every tool change.
967
+ params.tools = [...convertToolDefinitions(initialTools, toolCacheControl), DEFERRED_TOOL_PLACEHOLDER];
932
968
  }
933
969
  else {
934
970
  const tools = getCurrentTools(context.messages);
935
971
  if (tools.length > 0) {
936
- params.tools = convertTools(tools, isOAuthToken, compat.supportsEagerToolInputStreaming, compat.supportsStrictTools, toolCacheControl);
972
+ params.tools = convertToolDefinitions(tools, toolCacheControl);
937
973
  }
938
974
  }
939
- // Managed effort models always use adaptive thinking so prefix mismatches can
940
- // be dropped instead of surfacing as persistent 400 responses.
941
- if (model.compat?.supportsMidConvoEffort === true) {
975
+ if (thinkingDisabled) {
976
+ // No effort is sent, so the model default applies. Anthropic rejects `block_binding`
977
+ // with disabled thinking.
978
+ params.thinking = { type: "disabled" };
979
+ }
980
+ else if (effortMessages) {
981
+ // Managed effort models use adaptive thinking so prefix mismatches can
982
+ // be dropped instead of surfacing as persistent 400 responses.
942
983
  params.thinking = {
943
984
  type: "adaptive",
944
985
  display: options?.thinkingDisplay ?? "summarized",
@@ -946,29 +987,24 @@ function buildParams(model, context, isOAuthToken, options) {
946
987
  };
947
988
  params.output_config = { effort: "high" };
948
989
  }
949
- else if (model.reasoning) {
950
- if (options?.thinkingEnabled) {
951
- // Default to "summarized" so Opus 4.7 and Mythos Preview behave like
952
- // older Claude 4 models (whose API default is also "summarized").
953
- const display = options.thinkingDisplay ?? "summarized";
954
- if (model.compat?.forceAdaptiveThinking === true) {
955
- // Adaptive thinking: Claude decides when and how much to think.
956
- params.thinking = { type: "adaptive", display };
957
- if (options.effort) {
958
- params.output_config = { effort: options.effort };
959
- }
960
- }
961
- else {
962
- // Budget-based thinking for older models
963
- params.thinking = {
964
- type: "enabled",
965
- budget_tokens: options.thinkingBudgetTokens || 1024,
966
- display,
967
- };
990
+ else if (model.reasoning && options?.thinkingEnabled) {
991
+ // Default to "summarized" so Opus 4.7 and Mythos Preview behave like
992
+ // older Claude 4 models (whose API default is also "summarized").
993
+ const display = options.thinkingDisplay ?? "summarized";
994
+ if (model.compat?.forceAdaptiveThinking === true) {
995
+ // Adaptive thinking: Claude decides when and how much to think.
996
+ params.thinking = { type: "adaptive", display };
997
+ if (options.effort) {
998
+ params.output_config = { effort: options.effort };
968
999
  }
969
1000
  }
970
- else if (options?.thinkingEnabled === false && model.thinkingLevelMap?.off !== null) {
971
- params.thinking = { type: "disabled" };
1001
+ else {
1002
+ // Budget-based thinking for older models
1003
+ params.thinking = {
1004
+ type: "enabled",
1005
+ budget_tokens: options.thinkingBudgetTokens || 1024,
1006
+ display,
1007
+ };
972
1008
  }
973
1009
  }
974
1010
  if (options?.metadata) {
@@ -989,21 +1025,23 @@ function buildParams(model, context, isOAuthToken, options) {
989
1025
  if (allowedFallbackModels && allowedFallbackModels.length > 0) {
990
1026
  params.fallbacks = allowedFallbackModels.map((fallback) => ({ model: fallback.model }));
991
1027
  }
992
- return params;
1028
+ return { params, hasPreferredStrictTools, providerThinkingLevel: effortMessages ? activeEffort : undefined };
993
1029
  }
994
1030
  // Normalize tool call IDs to match Anthropic's required pattern and length
995
1031
  function normalizeToolCallId(id) {
996
1032
  return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
997
1033
  }
998
- function convertToolResult(msg) {
1034
+ function convertToolResult(msg, content = msg.content) {
999
1035
  return {
1000
1036
  type: "tool_result",
1001
1037
  tool_use_id: msg.toolCallId,
1002
- content: convertContentBlocks(msg.content),
1038
+ content: convertContentBlocks(content),
1003
1039
  is_error: msg.isError,
1004
1040
  };
1005
1041
  }
1006
- function convertMessages(transformedMessages, isOAuthToken, cacheControl, allowEmptySignature = false, managedProvider, nativeToolChanges = false) {
1042
+ function convertMessages(transformedMessages, isOAuthToken, cacheControl, allowEmptySignature = false, managedProvider,
1043
+ /** Converts tool definitions for native `tool_addition` blocks; undefined when tool changes are not native. */
1044
+ convertToolDefinitions) {
1007
1045
  const params = [];
1008
1046
  const assistantLevels = new Map();
1009
1047
  // Later system messages are held back and emitted directly before the next assistant
@@ -1025,18 +1063,20 @@ function convertMessages(transformedMessages, isOAuthToken, cacheControl, allowE
1025
1063
  const blocks = [];
1026
1064
  if (text.length > 0)
1027
1065
  blocks.push({ type: "text", text: sanitizeSurrogates(text) });
1028
- if (nativeToolChanges) {
1066
+ if (convertToolDefinitions) {
1067
+ const added = msg.toolsAdded ?? [];
1068
+ const redefined = new Set(added.map((tool) => tool.name));
1029
1069
  for (const tool of msg.toolsRemoved ?? []) {
1070
+ // A new definition under the same name replaces the old one, so no removal is needed.
1071
+ if (redefined.has(tool.name))
1072
+ continue;
1030
1073
  blocks.push({
1031
1074
  type: "tool_removal",
1032
1075
  tool: { type: "tool_reference", name: isOAuthToken ? toClaudeCodeName(tool.name) : tool.name },
1033
1076
  });
1034
1077
  }
1035
- for (const tool of msg.toolsAdded ?? []) {
1036
- blocks.push({
1037
- type: "tool_addition",
1038
- tool: { type: "tool_reference", name: isOAuthToken ? toClaudeCodeName(tool.name) : tool.name },
1039
- });
1078
+ for (const definition of convertToolDefinitions(added)) {
1079
+ blocks.push({ type: "tool_addition", tool: { type: "tool_definition", definition } });
1040
1080
  }
1041
1081
  }
1042
1082
  if (blocks.length > 0)
@@ -1060,14 +1100,7 @@ function convertMessages(transformedMessages, isOAuthToken, cacheControl, allowE
1060
1100
  };
1061
1101
  }
1062
1102
  else {
1063
- return {
1064
- type: "image",
1065
- source: {
1066
- type: "base64",
1067
- media_type: item.mimeType,
1068
- data: item.data,
1069
- },
1070
- };
1103
+ return convertImageBlock(item);
1071
1104
  }
1072
1105
  });
1073
1106
  const filteredBlocks = blocks.filter((b) => {
@@ -1158,16 +1191,24 @@ function convertMessages(transformedMessages, isOAuthToken, cacheControl, allowE
1158
1191
  else if (msg.role === "toolResult") {
1159
1192
  // Collect all consecutive toolResult messages, needed for z.ai Anthropic endpoint.
1160
1193
  const toolResults = [];
1194
+ // Anthropic rejects error tool results that contain anything but text, so their images follow
1195
+ // all tool results of the turn, which must come first in the user message (#10794).
1196
+ const errorImages = [];
1161
1197
  let j = i;
1162
1198
  while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
1163
- toolResults.push(convertToolResult(transformedMessages[j]));
1199
+ const toolMsg = transformedMessages[j];
1200
+ const split = splitErrorToolResultImages(toolMsg);
1201
+ toolResults.push(convertToolResult(toolMsg, split?.content));
1202
+ if (split) {
1203
+ errorImages.push({ type: "text", text: split.caption }, ...split.images.map(convertImageBlock));
1204
+ }
1164
1205
  j++;
1165
1206
  }
1166
1207
  // Skip the messages we've already processed.
1167
1208
  i = j - 1;
1168
1209
  params.push({
1169
1210
  role: "user",
1170
- content: toolResults,
1211
+ content: [...toolResults, ...errorImages],
1171
1212
  });
1172
1213
  }
1173
1214
  }
@@ -1254,11 +1295,14 @@ const isAnthropicStrictUnsupportedKeyword = (key, value) => {
1254
1295
  return typeof value !== "string" || !ANTHROPIC_STRICT_STRING_FORMATS.has(value);
1255
1296
  return false;
1256
1297
  };
1257
- function convertTools(tools, isOAuthToken, supportsEagerToolInputStreaming, supportsStrictTools, cacheControl) {
1298
+ function convertTools(tools, isOAuthToken, supportsEagerToolInputStreaming, supportsStrictTools, cacheControl, disablePreferredStrictTools = false) {
1258
1299
  if (!tools)
1259
1300
  return [];
1260
1301
  return tools.map((tool, index) => {
1261
- const strict = resolveJsonSchemaStrictSampling(tool, supportsStrictTools, isAnthropicStrictUnsupportedKeyword);
1302
+ const config = tool.constrainedSampling;
1303
+ const strict = disablePreferredStrictTools && config && config.type === "json_schema" && config.strict === "prefer"
1304
+ ? undefined
1305
+ : resolveJsonSchemaStrictSampling(tool, supportsStrictTools, isAnthropicStrictUnsupportedKeyword);
1262
1306
  const parameters = getJsonSchemaToolParameters(tool, strict);
1263
1307
  const schema = parameters;
1264
1308
  const legacyInputSchema = {