@code-yeongyu/senpi 2026.8.23 → 2026.8.25

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 (563) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/dist/cli/args.d.ts.map +1 -1
  3. package/dist/cli/args.js +24 -9
  4. package/dist/cli/args.js.map +1 -1
  5. package/dist/cli/file-processor.d.ts.map +1 -1
  6. package/dist/cli/file-processor.js +2 -1
  7. package/dist/cli/file-processor.js.map +1 -1
  8. package/dist/config.d.ts +6 -3
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +24 -14
  11. package/dist/config.js.map +1 -1
  12. package/dist/core/agent-abort-provenance.d.ts +5 -5
  13. package/dist/core/agent-abort-provenance.d.ts.map +1 -1
  14. package/dist/core/agent-abort-provenance.js +8 -1
  15. package/dist/core/agent-abort-provenance.js.map +1 -1
  16. package/dist/core/agent-session.d.ts +14 -0
  17. package/dist/core/agent-session.d.ts.map +1 -1
  18. package/dist/core/agent-session.js +129 -29
  19. package/dist/core/agent-session.js.map +1 -1
  20. package/dist/core/auth-storage.d.ts +4 -0
  21. package/dist/core/auth-storage.d.ts.map +1 -1
  22. package/dist/core/auth-storage.js +35 -8
  23. package/dist/core/auth-storage.js.map +1 -1
  24. package/dist/core/brand.d.ts +2 -0
  25. package/dist/core/brand.d.ts.map +1 -1
  26. package/dist/core/brand.js +1 -0
  27. package/dist/core/brand.js.map +1 -1
  28. package/dist/core/compaction/compaction.d.ts +1 -0
  29. package/dist/core/compaction/compaction.d.ts.map +1 -1
  30. package/dist/core/compaction/compaction.js +24 -8
  31. package/dist/core/compaction/compaction.js.map +1 -1
  32. package/dist/core/defaults.d.ts +1 -0
  33. package/dist/core/defaults.d.ts.map +1 -1
  34. package/dist/core/defaults.js +9 -0
  35. package/dist/core/defaults.js.map +1 -1
  36. package/dist/core/extensions/builtin/goal/agent-end-continuation.d.ts.map +1 -1
  37. package/dist/core/extensions/builtin/goal/agent-end-continuation.js +10 -0
  38. package/dist/core/extensions/builtin/goal/agent-end-continuation.js.map +1 -1
  39. package/dist/core/extensions/builtin/goal/continuation.d.ts +1 -1
  40. package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
  41. package/dist/core/extensions/builtin/goal/continuation.js +1 -1
  42. package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
  43. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  44. package/dist/core/extensions/builtin/goal/index.js +0 -8
  45. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  46. package/dist/core/extensions/builtin/goal/monitor-continuation-types.d.ts +1 -0
  47. package/dist/core/extensions/builtin/goal/monitor-continuation-types.d.ts.map +1 -1
  48. package/dist/core/extensions/builtin/goal/monitor-continuation-types.js.map +1 -1
  49. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts +2 -1
  50. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  51. package/dist/core/extensions/builtin/goal/monitor-continuation.js +31 -3
  52. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  53. package/dist/core/extensions/builtin/goal/terminal-provider-error.js +1 -1
  54. package/dist/core/extensions/builtin/goal/terminal-provider-error.js.map +1 -1
  55. package/dist/core/extensions/builtin/goal/wait-ticker.d.ts.map +1 -1
  56. package/dist/core/extensions/builtin/goal/wait-ticker.js +14 -9
  57. package/dist/core/extensions/builtin/goal/wait-ticker.js.map +1 -1
  58. package/dist/core/extensions/builtin/loop-guard/notice.d.ts.map +1 -1
  59. package/dist/core/extensions/builtin/loop-guard/notice.js +5 -1
  60. package/dist/core/extensions/builtin/loop-guard/notice.js.map +1 -1
  61. package/dist/core/extensions/builtin/mcp/config-schema.d.ts +2 -2
  62. package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
  63. package/dist/core/extensions/builtin/ttsr/index.js +6 -6
  64. package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
  65. package/dist/core/extensions/builtin/ttsr/message-update.d.ts +10 -0
  66. package/dist/core/extensions/builtin/ttsr/message-update.d.ts.map +1 -0
  67. package/dist/core/extensions/builtin/ttsr/message-update.js +38 -0
  68. package/dist/core/extensions/builtin/ttsr/message-update.js.map +1 -0
  69. package/dist/core/extensions/builtin/ttsr/remediation.d.ts +5 -10
  70. package/dist/core/extensions/builtin/ttsr/remediation.d.ts.map +1 -1
  71. package/dist/core/extensions/builtin/ttsr/remediation.js +19 -3
  72. package/dist/core/extensions/builtin/ttsr/remediation.js.map +1 -1
  73. package/dist/core/extensions/builtin/ttsr/stream-remediation.d.ts +1 -1
  74. package/dist/core/extensions/builtin/ttsr/stream-remediation.d.ts.map +1 -1
  75. package/dist/core/extensions/builtin/ttsr/stream-remediation.js.map +1 -1
  76. package/dist/core/extensions/builtin/ttsr/types.d.ts +1 -1
  77. package/dist/core/extensions/builtin/ttsr/types.d.ts.map +1 -1
  78. package/dist/core/extensions/builtin/ttsr/types.js.map +1 -1
  79. package/dist/core/extensions/builtin/ttsr/watch.d.ts +1 -1
  80. package/dist/core/extensions/builtin/ttsr/watch.d.ts.map +1 -1
  81. package/dist/core/extensions/builtin/ttsr/watch.js +2 -2
  82. package/dist/core/extensions/builtin/ttsr/watch.js.map +1 -1
  83. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.d.ts.map +1 -1
  84. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js +5 -23
  85. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js.map +1 -1
  86. package/dist/core/extensions/builtin/webfetch/webfetch/response-body.d.ts +11 -0
  87. package/dist/core/extensions/builtin/webfetch/webfetch/response-body.d.ts.map +1 -0
  88. package/dist/core/extensions/builtin/webfetch/webfetch/response-body.js +54 -0
  89. package/dist/core/extensions/builtin/webfetch/webfetch/response-body.js.map +1 -0
  90. package/dist/core/extensions/index.d.ts +2 -2
  91. package/dist/core/extensions/index.d.ts.map +1 -1
  92. package/dist/core/extensions/index.js +1 -1
  93. package/dist/core/extensions/index.js.map +1 -1
  94. package/dist/core/extensions/loader.d.ts.map +1 -1
  95. package/dist/core/extensions/loader.js +107 -45
  96. package/dist/core/extensions/loader.js.map +1 -1
  97. package/dist/core/extensions/types.d.ts +17 -6
  98. package/dist/core/extensions/types.d.ts.map +1 -1
  99. package/dist/core/extensions/types.js +3 -0
  100. package/dist/core/extensions/types.js.map +1 -1
  101. package/dist/core/footer-data-provider.d.ts +1 -1
  102. package/dist/core/footer-data-provider.js +1 -1
  103. package/dist/core/footer-data-provider.js.map +1 -1
  104. package/dist/core/keybindings.d.ts +20 -19
  105. package/dist/core/keybindings.d.ts.map +1 -1
  106. package/dist/core/keybindings.js +26 -5
  107. package/dist/core/keybindings.js.map +1 -1
  108. package/dist/core/model-config-schema.d.ts +17 -5
  109. package/dist/core/model-config-schema.d.ts.map +1 -1
  110. package/dist/core/model-config-schema.js +1 -1
  111. package/dist/core/model-config-schema.js.map +1 -1
  112. package/dist/core/model-config.d.ts.map +1 -1
  113. package/dist/core/model-config.js +7 -5
  114. package/dist/core/model-config.js.map +1 -1
  115. package/dist/core/model-resolver.d.ts +3 -2
  116. package/dist/core/model-resolver.d.ts.map +1 -1
  117. package/dist/core/model-resolver.js +3 -2
  118. package/dist/core/model-resolver.js.map +1 -1
  119. package/dist/core/model-runtime.d.ts +0 -1
  120. package/dist/core/model-runtime.d.ts.map +1 -1
  121. package/dist/core/model-runtime.js +0 -18
  122. package/dist/core/model-runtime.js.map +1 -1
  123. package/dist/core/models-store.d.ts.map +1 -1
  124. package/dist/core/models-store.js +2 -1
  125. package/dist/core/models-store.js.map +1 -1
  126. package/dist/core/package-manager.d.ts.map +1 -1
  127. package/dist/core/package-manager.js +14 -10
  128. package/dist/core/package-manager.js.map +1 -1
  129. package/dist/core/pi-manifest.d.ts.map +1 -1
  130. package/dist/core/pi-manifest.js +2 -1
  131. package/dist/core/pi-manifest.js.map +1 -1
  132. package/dist/core/provider-composer.d.ts +2 -0
  133. package/dist/core/provider-composer.d.ts.map +1 -1
  134. package/dist/core/provider-composer.js +3 -6
  135. package/dist/core/provider-composer.js.map +1 -1
  136. package/dist/core/provider-display-names.d.ts.map +1 -1
  137. package/dist/core/provider-display-names.js +0 -1
  138. package/dist/core/provider-display-names.js.map +1 -1
  139. package/dist/core/provider-timeout-retry.d.ts.map +1 -1
  140. package/dist/core/provider-timeout-retry.js +8 -12
  141. package/dist/core/provider-timeout-retry.js.map +1 -1
  142. package/dist/core/resource-loader.d.ts.map +1 -1
  143. package/dist/core/resource-loader.js +3 -2
  144. package/dist/core/resource-loader.js.map +1 -1
  145. package/dist/core/retry-fallback/profile-override.d.ts +24 -0
  146. package/dist/core/retry-fallback/profile-override.d.ts.map +1 -0
  147. package/dist/core/retry-fallback/profile-override.js +138 -0
  148. package/dist/core/retry-fallback/profile-override.js.map +1 -0
  149. package/dist/core/retry-fallback/settings.d.ts +1 -0
  150. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  151. package/dist/core/retry-fallback/settings.js.map +1 -1
  152. package/dist/core/sdk.d.ts +2 -2
  153. package/dist/core/sdk.d.ts.map +1 -1
  154. package/dist/core/sdk.js +20 -5
  155. package/dist/core/sdk.js.map +1 -1
  156. package/dist/core/session-export.d.ts +4 -0
  157. package/dist/core/session-export.d.ts.map +1 -0
  158. package/dist/core/session-export.js +32 -0
  159. package/dist/core/session-export.js.map +1 -0
  160. package/dist/core/session-manager.d.ts.map +1 -1
  161. package/dist/core/session-manager.js +2 -1
  162. package/dist/core/session-manager.js.map +1 -1
  163. package/dist/core/settings-diagnostics.d.ts +9 -0
  164. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  165. package/dist/core/settings-diagnostics.js +21 -0
  166. package/dist/core/settings-diagnostics.js.map +1 -0
  167. package/dist/core/settings-manager.d.ts +18 -0
  168. package/dist/core/settings-manager.d.ts.map +1 -1
  169. package/dist/core/settings-manager.js +88 -7
  170. package/dist/core/settings-manager.js.map +1 -1
  171. package/dist/core/slash-commands.d.ts.map +1 -1
  172. package/dist/core/slash-commands.js +2 -1
  173. package/dist/core/slash-commands.js.map +1 -1
  174. package/dist/core/system-prompt.d.ts.map +1 -1
  175. package/dist/core/system-prompt.js +11 -2
  176. package/dist/core/system-prompt.js.map +1 -1
  177. package/dist/core/tools/bash.d.ts +14 -1
  178. package/dist/core/tools/bash.d.ts.map +1 -1
  179. package/dist/core/tools/bash.js +35 -19
  180. package/dist/core/tools/bash.js.map +1 -1
  181. package/dist/core/tools/edit-diff.d.ts +0 -5
  182. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  183. package/dist/core/tools/edit-diff.js +2 -5
  184. package/dist/core/tools/edit-diff.js.map +1 -1
  185. package/dist/core/tools/edit.d.ts.map +1 -1
  186. package/dist/core/tools/edit.js +3 -2
  187. package/dist/core/tools/edit.js.map +1 -1
  188. package/dist/core/tools/index.d.ts +4 -1
  189. package/dist/core/tools/index.d.ts.map +1 -1
  190. package/dist/core/tools/index.js +13 -1
  191. package/dist/core/tools/index.js.map +1 -1
  192. package/dist/core/tools/powershell.d.ts +16 -0
  193. package/dist/core/tools/powershell.d.ts.map +1 -0
  194. package/dist/core/tools/powershell.js +39 -0
  195. package/dist/core/tools/powershell.js.map +1 -0
  196. package/dist/core/tools/read.d.ts.map +1 -1
  197. package/dist/core/tools/read.js +5 -0
  198. package/dist/core/tools/read.js.map +1 -1
  199. package/dist/core/trust-manager.d.ts.map +1 -1
  200. package/dist/core/trust-manager.js +2 -1
  201. package/dist/core/trust-manager.js.map +1 -1
  202. package/dist/extensions/llama/client.d.ts +6 -0
  203. package/dist/extensions/llama/client.d.ts.map +1 -1
  204. package/dist/extensions/llama/client.js +7 -0
  205. package/dist/extensions/llama/client.js.map +1 -1
  206. package/dist/extensions/llama/provider.d.ts +3 -1
  207. package/dist/extensions/llama/provider.d.ts.map +1 -1
  208. package/dist/extensions/llama/provider.js +27 -6
  209. package/dist/extensions/llama/provider.js.map +1 -1
  210. package/dist/index.d.ts +5 -4
  211. package/dist/index.d.ts.map +1 -1
  212. package/dist/index.js +4 -3
  213. package/dist/index.js.map +1 -1
  214. package/dist/main.d.ts.map +1 -1
  215. package/dist/main.js +13 -2
  216. package/dist/main.js.map +1 -1
  217. package/dist/migrations.d.ts.map +1 -1
  218. package/dist/migrations.js +4 -3
  219. package/dist/migrations.js.map +1 -1
  220. package/dist/modes/app-server/daemon/probe.js +1 -1
  221. package/dist/modes/app-server/daemon/probe.js.map +1 -1
  222. package/dist/modes/app-server/daemon.js +13 -2
  223. package/dist/modes/app-server/daemon.js.map +1 -1
  224. package/dist/modes/app-server/transports/websocket-connection-handler.d.ts.map +1 -1
  225. package/dist/modes/app-server/transports/websocket-connection-handler.js +4 -0
  226. package/dist/modes/app-server/transports/websocket-connection-handler.js.map +1 -1
  227. package/dist/modes/interactive/aborted-error-label.d.ts +4 -1
  228. package/dist/modes/interactive/aborted-error-label.d.ts.map +1 -1
  229. package/dist/modes/interactive/aborted-error-label.js +27 -5
  230. package/dist/modes/interactive/aborted-error-label.js.map +1 -1
  231. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  232. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  233. package/dist/modes/interactive/components/thinking-selector.js +68 -17
  234. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  235. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  236. package/dist/modes/interactive/external-editor.js +2 -1
  237. package/dist/modes/interactive/external-editor.js.map +1 -1
  238. package/dist/modes/interactive/interactive-mode.d.ts +6 -0
  239. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  240. package/dist/modes/interactive/interactive-mode.js +28 -13
  241. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  242. package/dist/modes/interactive/streaming-reveal.d.ts +8 -0
  243. package/dist/modes/interactive/streaming-reveal.d.ts.map +1 -1
  244. package/dist/modes/interactive/streaming-reveal.js +12 -0
  245. package/dist/modes/interactive/streaming-reveal.js.map +1 -1
  246. package/dist/modes/json-event.d.ts +16 -13
  247. package/dist/modes/json-event.d.ts.map +1 -1
  248. package/dist/modes/json-event.js +20 -6
  249. package/dist/modes/json-event.js.map +1 -1
  250. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  251. package/dist/modes/rpc/connection-handler.js +3 -0
  252. package/dist/modes/rpc/connection-handler.js.map +1 -1
  253. package/dist/modes/rpc/rpc-client.d.ts +7 -0
  254. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  255. package/dist/modes/rpc/rpc-client.js +7 -0
  256. package/dist/modes/rpc/rpc-client.js.map +1 -1
  257. package/dist/modes/rpc/rpc-types.d.ts +12 -0
  258. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  259. package/dist/modes/rpc/rpc-types.js.map +1 -1
  260. package/dist/package-manager-cli.d.ts +1 -0
  261. package/dist/package-manager-cli.d.ts.map +1 -1
  262. package/dist/package-manager-cli.js +186 -2
  263. package/dist/package-manager-cli.js.map +1 -1
  264. package/dist/utils/frontmatter.d.ts.map +1 -1
  265. package/dist/utils/frontmatter.js +2 -1
  266. package/dist/utils/frontmatter.js.map +1 -1
  267. package/dist/utils/shell.d.ts +3 -0
  268. package/dist/utils/shell.d.ts.map +1 -1
  269. package/dist/utils/shell.js +17 -5
  270. package/dist/utils/shell.js.map +1 -1
  271. package/dist/utils/syntax-highlight.d.ts +1 -0
  272. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  273. package/dist/utils/syntax-highlight.js +60 -1
  274. package/dist/utils/syntax-highlight.js.map +1 -1
  275. package/dist/utils/text.d.ts +8 -0
  276. package/dist/utils/text.d.ts.map +1 -0
  277. package/dist/utils/text.js +9 -0
  278. package/dist/utils/text.js.map +1 -0
  279. package/docs/AGENTS.md +3 -1
  280. package/docs/compaction.md +0 -2
  281. package/docs/custom-provider.md +6 -6
  282. package/docs/environment-variables.md +8 -8
  283. package/docs/extensions.md +6 -5
  284. package/docs/json.md +7 -2
  285. package/docs/keybindings.md +1 -1
  286. package/docs/packages.md +2 -2
  287. package/docs/rpc.md +32 -3
  288. package/docs/sdk.md +7 -2
  289. package/docs/settings.md +9 -1
  290. package/docs/terminal-setup.md +11 -9
  291. package/docs/usage.md +4 -1
  292. package/docs/windows.md +24 -2
  293. package/examples/AGENTS.md +21 -6
  294. package/examples/extensions/AGENTS.md +50 -0
  295. package/node_modules/@anthropic-ai/claude-agent-sdk/bridge.mjs +90 -88
  296. package/node_modules/@anthropic-ai/claude-agent-sdk/browser-sdk.js +40 -40
  297. package/node_modules/@anthropic-ai/claude-agent-sdk/manifest.json +20 -21
  298. package/node_modules/@anthropic-ai/claude-agent-sdk/manifest.zst.json +24 -25
  299. package/node_modules/@anthropic-ai/claude-agent-sdk/package.json +2 -2
  300. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk-tools.d.ts +102 -5
  301. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk.d.ts +31 -15
  302. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs +80 -78
  303. package/node_modules/@aws-sdk/client-bedrock-runtime/dist-cjs/index.js +1 -1
  304. package/node_modules/@aws-sdk/client-bedrock-runtime/package.json +13 -13
  305. package/node_modules/@aws-sdk/core/package.json +5 -5
  306. package/node_modules/@aws-sdk/credential-provider-env/package.json +5 -5
  307. package/node_modules/@aws-sdk/credential-provider-http/package.json +7 -7
  308. package/node_modules/@aws-sdk/credential-provider-ini/package.json +12 -12
  309. package/node_modules/@aws-sdk/credential-provider-login/package.json +6 -6
  310. package/node_modules/@aws-sdk/credential-provider-node/package.json +10 -10
  311. package/node_modules/@aws-sdk/credential-provider-process/package.json +5 -5
  312. package/node_modules/@aws-sdk/credential-provider-sso/package.json +7 -7
  313. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +6 -6
  314. package/node_modules/@aws-sdk/eventstream-handler-node/package.json +4 -4
  315. package/node_modules/@aws-sdk/middleware-eventstream/package.json +4 -4
  316. package/node_modules/@aws-sdk/middleware-websocket/package.json +6 -6
  317. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +1 -1
  318. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +1 -1
  319. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +1 -1
  320. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +1 -1
  321. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +1 -1
  322. package/node_modules/@aws-sdk/nested-clients/package.json +8 -8
  323. package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +3 -3
  324. package/node_modules/@aws-sdk/token-providers/package.json +6 -6
  325. package/node_modules/@aws-sdk/types/package.json +2 -2
  326. package/node_modules/@aws-sdk/xml-builder/package.json +2 -2
  327. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +26 -0
  328. package/node_modules/@code-yeongyu/senpi-codemode/package.json +5 -5
  329. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager-proxy.ts +39 -5
  330. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/AGENTS.md +40 -0
  331. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/AGENTS.md +40 -0
  332. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +1 -1
  333. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-notification.ts +3 -8
  334. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-notification-queue.ts +2 -6
  335. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  336. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +7 -4
  337. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  338. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +2 -3
  339. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  340. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +7 -6
  341. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  342. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts +4 -0
  343. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts.map +1 -1
  344. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js +8 -0
  345. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js.map +1 -1
  346. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts +1 -0
  347. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts.map +1 -1
  348. package/node_modules/@earendil-works/pi-agent-core/dist/index.js +1 -0
  349. package/node_modules/@earendil-works/pi-agent-core/dist/index.js.map +1 -1
  350. package/node_modules/@earendil-works/pi-agent-core/package.json +6 -6
  351. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts +1 -5
  352. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  353. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +25 -13
  354. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  355. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.d.ts.map +1 -1
  356. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js +2 -1
  357. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js.map +1 -1
  358. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  359. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +91 -5
  360. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
  361. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.d.ts.map +1 -1
  362. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js +4 -2
  363. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js.map +1 -1
  364. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.d.ts.map +1 -1
  365. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js +4 -2
  366. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js.map +1 -1
  367. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.d.ts.map +1 -1
  368. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.js +2 -0
  369. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.js.map +1 -1
  370. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  371. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +93 -54
  372. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  373. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +2 -5
  374. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  375. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +1 -1
  376. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
  377. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts.map +1 -1
  378. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js +97 -46
  379. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js.map +1 -1
  380. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
  381. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +1 -14
  382. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js.map +1 -1
  383. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +50 -0
  384. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -0
  385. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +129 -0
  386. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -0
  387. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
  388. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +3 -1
  389. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
  390. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +8 -1
  391. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  392. package/node_modules/@earendil-works/pi-ai/dist/models.js +16 -3
  393. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  394. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.d.ts +3 -1
  395. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -1
  396. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.js +10 -1
  397. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.js.map +1 -1
  398. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  399. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
  400. package/node_modules/@earendil-works/pi-ai/dist/providers/data/azure-openai-responses.json +1 -1
  401. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  402. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  403. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
  404. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  405. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  406. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  407. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  408. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
  409. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
  410. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts +1 -0
  411. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts.map +1 -1
  412. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js +1 -0
  413. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js.map +1 -1
  414. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.d.ts.map +1 -1
  415. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js +4 -0
  416. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js.map +1 -1
  417. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +8 -1
  418. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  419. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  420. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +16 -0
  421. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  422. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +17 -1
  423. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  424. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/backoff.d.ts +14 -0
  425. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/backoff.d.ts.map +1 -0
  426. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/backoff.js +24 -0
  427. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/backoff.js.map +1 -0
  428. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.d.ts +36 -0
  429. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.d.ts.map +1 -0
  430. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.js +109 -0
  431. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.js.map +1 -0
  432. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/failure.d.ts +12 -0
  433. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/failure.d.ts.map +1 -0
  434. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/failure.js +109 -0
  435. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/failure.js.map +1 -0
  436. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/index.d.ts +9 -0
  437. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/index.d.ts.map +1 -0
  438. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/index.js +6 -0
  439. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/index.js.map +1 -0
  440. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/planner.d.ts +46 -0
  441. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/planner.d.ts.map +1 -0
  442. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/planner.js +41 -0
  443. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/planner.js.map +1 -0
  444. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.d.ts +4 -0
  445. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.d.ts.map +1 -0
  446. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.js +93 -0
  447. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.js.map +1 -0
  448. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/types.d.ts +121 -0
  449. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/types.d.ts.map +1 -0
  450. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/types.js +11 -0
  451. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/types.js.map +1 -0
  452. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +12 -0
  453. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  454. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +25 -5
  455. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  456. package/node_modules/@earendil-works/pi-ai/dist/utils/sleep.d.ts +2 -0
  457. package/node_modules/@earendil-works/pi-ai/dist/utils/sleep.d.ts.map +1 -0
  458. package/node_modules/@earendil-works/pi-ai/dist/utils/sleep.js +15 -0
  459. package/node_modules/@earendil-works/pi-ai/dist/utils/sleep.js.map +1 -0
  460. package/node_modules/@earendil-works/pi-ai/package.json +22 -18
  461. package/node_modules/@earendil-works/pi-pty/dist/index.d.ts +1 -0
  462. package/node_modules/@earendil-works/pi-pty/dist/index.d.ts.map +1 -1
  463. package/node_modules/@earendil-works/pi-pty/dist/index.js +1 -0
  464. package/node_modules/@earendil-works/pi-pty/dist/index.js.map +1 -1
  465. package/node_modules/@earendil-works/pi-pty/dist/session-bun.d.ts +30 -0
  466. package/node_modules/@earendil-works/pi-pty/dist/session-bun.d.ts.map +1 -0
  467. package/node_modules/@earendil-works/pi-pty/dist/session-bun.js +76 -0
  468. package/node_modules/@earendil-works/pi-pty/dist/session-bun.js.map +1 -0
  469. package/node_modules/@earendil-works/pi-pty/dist/session-types.d.ts +3 -1
  470. package/node_modules/@earendil-works/pi-pty/dist/session-types.d.ts.map +1 -1
  471. package/node_modules/@earendil-works/pi-pty/dist/session-types.js.map +1 -1
  472. package/node_modules/@earendil-works/pi-pty/dist/session.d.ts +2 -0
  473. package/node_modules/@earendil-works/pi-pty/dist/session.d.ts.map +1 -1
  474. package/node_modules/@earendil-works/pi-pty/dist/session.js +19 -9
  475. package/node_modules/@earendil-works/pi-pty/dist/session.js.map +1 -1
  476. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  477. package/node_modules/@earendil-works/pi-telemetry/package.json +3 -3
  478. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts.map +1 -1
  479. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +9 -4
  480. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js.map +1 -1
  481. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.d.ts +8 -2
  482. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.d.ts.map +1 -1
  483. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.js +24 -4
  484. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.js.map +1 -1
  485. package/node_modules/@earendil-works/pi-tui/dist/keybindings.d.ts +2 -2
  486. package/node_modules/@earendil-works/pi-tui/dist/keybindings.js +2 -2
  487. package/node_modules/@earendil-works/pi-tui/dist/keybindings.js.map +1 -1
  488. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts.map +1 -1
  489. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +2 -8
  490. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js.map +1 -1
  491. package/node_modules/@earendil-works/pi-tui/dist/native-module-path.d.ts +7 -0
  492. package/node_modules/@earendil-works/pi-tui/dist/native-module-path.d.ts.map +1 -0
  493. package/node_modules/@earendil-works/pi-tui/dist/native-module-path.js +19 -0
  494. package/node_modules/@earendil-works/pi-tui/dist/native-module-path.js.map +1 -0
  495. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  496. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +11 -14
  497. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  498. package/node_modules/@earendil-works/pi-tui/package.json +5 -5
  499. package/node_modules/@smithy/signature-v4/dist-cjs/index.js +19 -7
  500. package/node_modules/@smithy/signature-v4/dist-es/HeaderFormatter.js +4 -1
  501. package/node_modules/@smithy/signature-v4/dist-es/getCanonicalQuery.js +4 -1
  502. package/node_modules/@smithy/signature-v4/dist-es/getPayloadHash.js +4 -1
  503. package/node_modules/@smithy/signature-v4/dist-es/headerUtil.js +10 -3
  504. package/node_modules/@smithy/signature-v4/dist-es/moveHeadersToQuery.js +4 -1
  505. package/node_modules/@smithy/signature-v4/dist-es/prepareRequest.js +4 -1
  506. package/node_modules/@smithy/signature-v4/package.json +2 -2
  507. package/node_modules/typebox/build/format/email.mjs +1 -1
  508. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
  509. package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
  510. package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
  511. package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
  512. package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
  513. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  514. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  515. package/node_modules/typebox/build/system/memory/assign.mjs +2 -1
  516. package/node_modules/typebox/build/system/memory/create.mjs +3 -4
  517. package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
  518. package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
  519. package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
  520. package/node_modules/typebox/build/system/memory/update.mjs +3 -2
  521. package/node_modules/typebox/package.json +1 -1
  522. package/package.json +110 -108
  523. package/dist/core/radius.d.ts +0 -2
  524. package/dist/core/radius.d.ts.map +0 -1
  525. package/dist/core/radius.js +0 -2
  526. package/dist/core/radius.js.map +0 -1
  527. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/LICENSE +0 -201
  528. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/README.md +0 -62
  529. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-cjs/index.js +0 -154
  530. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/constants.js +0 -2
  531. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromEnvSigningName.js +0 -16
  532. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromSso.js +0 -80
  533. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromStatic.js +0 -8
  534. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/getNewSsoOidcToken.js +0 -11
  535. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/getSsoOidcClient.js +0 -10
  536. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/index.js +0 -4
  537. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/nodeProvider.js +0 -5
  538. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/validateTokenExpiry.js +0 -7
  539. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/validateTokenKey.js +0 -7
  540. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/writeSSOTokenToFile.js +0 -8
  541. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/constants.d.ts +0 -8
  542. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/fromEnvSigningName.d.ts +0 -18
  543. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/fromSso.d.ts +0 -12
  544. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/fromStatic.d.ts +0 -9
  545. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/getNewSsoOidcToken.d.ts +0 -8
  546. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/getSsoOidcClient.d.ts +0 -7
  547. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/index.d.ts +0 -7
  548. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/nodeProvider.d.ts +0 -18
  549. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/constants.d.ts +0 -3
  550. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/fromEnvSigningName.d.ts +0 -8
  551. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/fromSso.d.ts +0 -10
  552. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/fromStatic.d.ts +0 -5
  553. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/getNewSsoOidcToken.d.ts +0 -9
  554. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/getSsoOidcClient.d.ts +0 -7
  555. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/index.d.ts +0 -7
  556. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/nodeProvider.d.ts +0 -3
  557. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/validateTokenExpiry.d.ts +0 -2
  558. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/validateTokenKey.d.ts +0 -1
  559. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/writeSSOTokenToFile.d.ts +0 -2
  560. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/validateTokenExpiry.d.ts +0 -5
  561. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/validateTokenKey.d.ts +0 -4
  562. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/writeSSOTokenToFile.d.ts +0 -5
  563. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/package.json +0 -69
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAybA,sFAAsF;AACtF,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC/C,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AACpD,CAAC","sourcesContent":["import type { TelemetryContext } from \"@earendil-works/pi-telemetry\";\nimport type { AnthropicOptions } from \"./api/anthropic-messages.ts\";\nimport type { AzureOpenAIResponsesOptions } from \"./api/azure-openai-responses.ts\";\nimport type { BedrockOptions } from \"./api/bedrock-converse-stream.ts\";\nimport type { CursorAgentOptions } from \"./api/cursor-agent/types.ts\";\nimport type { GoogleOptions } from \"./api/google-generative-ai.ts\";\nimport type { GoogleVertexOptions } from \"./api/google-vertex.ts\";\nimport type { MistralOptions } from \"./api/mistral-conversations.ts\";\nimport type { OpenAICodexResponsesOptions } from \"./api/openai-codex-responses.ts\";\nimport type { OpenAICompletionsOptions } from \"./api/openai-completions.ts\";\nimport type { OpenAIResponsesOptions } from \"./api/openai-responses.ts\";\nimport type { PiMessagesOptions } from \"./api/pi-messages.ts\";\nimport type { Model } from \"./model.ts\";\nimport type {\n\tOpenAIResponsesCompat as BaseOpenAIResponsesCompat,\n\tSessionAffinityFormat,\n} from \"./openai-responses-compat.ts\";\nimport type { AssistantMessageDiagnostic } from \"./utils/diagnostics.ts\";\nimport type { AssistantMessageEventStream } from \"./utils/event-stream.ts\";\n\nexport type { Model } from \"./model.ts\";\nexport type { SessionAffinityFormat } from \"./openai-responses-compat.ts\";\nexport type OpenAIResponsesCompat = BaseOpenAIResponsesCompat & {\n\t/** Whether the model supports message-anchored `additional_tools` input items. Default: false. */\n\tsupportsAdditionalTools?: boolean;\n};\nexport type { AssistantMessageEventStream } from \"./utils/event-stream.ts\";\n\nexport type KnownApi =\n\t| \"openai-completions\"\n\t| \"mistral-conversations\"\n\t| \"openai-responses\"\n\t| \"azure-openai-responses\"\n\t| \"openai-codex-responses\"\n\t| \"cursor-agent\"\n\t| \"anthropic-messages\"\n\t| \"bedrock-converse-stream\"\n\t| \"google-generative-ai\"\n\t| \"google-vertex\"\n\t| \"pi-messages\";\n\nexport type Api = KnownApi | (string & {});\n\nexport type KnownImagesApi = \"openrouter-images\" | \"openai-images\";\n\nexport type ImagesApi = KnownImagesApi | (string & {});\n\nexport type KnownProvider =\n\t| \"alibaba-token-plan\"\n\t| \"amazon-bedrock\"\n\t| \"ant-ling\"\n\t| \"anthropic\"\n\t| \"google\"\n\t| \"google-vertex\"\n\t| \"openai\"\n\t| \"azure-openai-responses\"\n\t| \"openai-codex\"\n\t| \"ollama\"\n\t| \"cursor\"\n\t| \"radius\"\n\t| \"nvidia\"\n\t| \"deepseek\"\n\t| \"github-copilot\"\n\t| \"xai\"\n\t| \"groq\"\n\t| \"cerebras\"\n\t| \"openrouter\"\n\t| \"vercel-ai-gateway\"\n\t| \"opengateway\"\n\t| \"zai\"\n\t| \"zai-coding-cn\"\n\t| \"mistral\"\n\t| \"minimax\"\n\t| \"minimax-cn\"\n\t| \"moonshotai\"\n\t| \"moonshotai-cn\"\n\t| \"huggingface\"\n\t| \"fireworks\"\n\t| \"together\"\n\t| \"baseten\"\n\t| \"opencode\"\n\t| \"opencode-go\"\n\t| \"kimi-coding\"\n\t| \"cloudflare-workers-ai\"\n\t| \"cloudflare-ai-gateway\"\n\t| \"qwen-token-plan\"\n\t| \"qwen-token-plan-cn\"\n\t| \"qwen-token-plan-individual\"\n\t| \"xiaomi\"\n\t| \"xiaomi-token-plan-cn\"\n\t| \"xiaomi-token-plan-ams\"\n\t| \"xiaomi-token-plan-sgp\";\nexport type ProviderId = KnownProvider | string;\n\nexport type KnownImagesProvider = \"openrouter\";\n\nexport type ImagesProviderId = KnownImagesProvider | string;\n\nexport type ToolChoice = \"auto\" | \"none\";\nexport type ThinkingLevel = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\nexport type ModelThinkingLevel = \"off\" | ThinkingLevel;\n\n/**\n * Provenance-bearing thinking selection. Distinct from the always-materialized\n * effective level: a selection exists only when the user (or a legacy variant\n * alias) explicitly chose a level. See .omo/plans/cursor-reasoning-levels.md §4.1.\n */\nexport interface ThinkingSelection {\n\treadonly level: ModelThinkingLevel;\n\treadonly source: \"explicit\" | \"legacy-variant\";\n\t/** Required when source is \"legacy-variant\": the exact allowlisted original variant id. */\n\treadonly legacyVariantId?: string;\n}\nexport type ThinkingLevelMap = Partial<Record<ModelThinkingLevel, string | null>>;\nexport type ChatTemplateKwargValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| {\n\t\t\t$var: \"thinking.enabled\" | \"thinking.effort\" | \"thinking.budget\";\n\t\t\tomitWhenOff?: boolean;\n\t };\n\n/** Top-level request field used to cap reasoning tokens on OpenAI-compatible servers. */\nexport type ThinkingTokenBudgetField = \"thinking_token_budget\" | \"thinking_budget\" | \"thinking_budget_tokens\";\n\n/** Token budgets for each thinking level (token-based providers only) */\nexport interface ThinkingBudgets {\n\tminimal?: number;\n\tlow?: number;\n\tmedium?: number;\n\thigh?: number;\n\tmax?: number;\n}\n\n// Base options all providers share\nexport type CacheRetention = \"none\" | \"short\" | \"long\";\n\nexport type Transport = \"sse\" | \"websocket\" | \"websocket-cached\" | \"auto\";\n\n/** Provider-scoped environment overrides. Values take precedence over process.env. */\nexport type ProviderEnv = Record<string, string>;\nexport type ProviderHeaders = Record<string, string | null>;\n/** Effective model and fully transformed headers for a request payload hook. */\nexport type ProviderRequestMetadata = {\n\tmodel: Model<Api>;\n\theaders: ProviderHeaders;\n};\nexport type FetchFunction = typeof globalThis.fetch;\n\nexport interface ProviderResponse {\n\tstatus: number;\n\theaders: Record<string, string>;\n}\n\n/** Authentication, HTTP transport, and lifecycle callbacks shared by provider requests. */\nexport interface ProviderRequestOptions<TModel = Model<Api>> {\n\tsignal?: AbortSignal;\n\t/**\n\t * Abort the request when the provider reports that a safety classifier\n\t * declined the requested model and a substitute model served the turn\n\t * instead (Anthropic `server-side-fallback-*` betas). The substitute's output\n\t * is billed but was never requested, so aborting keeps model selection with\n\t * the caller. Providers without server-side fallback ignore this.\n\t * Default: undefined (honor the substituted response).\n\t */\n\tabortServerSideFallback?: boolean;\n\t/** Explicit parent context for telemetry produced by this logical request. */\n\ttelemetryContext?: TelemetryContext;\n\tapiKey?: string;\n\t/**\n\t * Stable identity of the originating session for account-affinity providers,\n\t * preserved across auxiliary calls that replace `sessionId` (for example\n\t * compaction). Providers without account affinity ignore this.\n\t */\n\taffinitySessionId?: string;\n\t/**\n\t * Identifies whether the stream belongs to the main agent loop or an auxiliary request.\n\t * An absent value must be treated as auxiliary as a fail-safe.\n\t */\n\tstreamKind?: \"main\" | \"auxiliary\";\n\t/**\n\t * Optional fetch implementation for provider HTTP requests.\n\t * Defaults to `globalThis.fetch`. Provider adapters that cannot inject a custom implementation may reject it.\n\t * This does not affect WebSocket transports.\n\t */\n\tfetch?: FetchFunction;\n\t/**\n\t * Provider-scoped environment values. These take precedence over process.env for\n\t * provider configuration such as regional settings, endpoint placeholders, and\n\t * proxy variables.\n\t */\n\tenv?: ProviderEnv;\n\t/**\n\t * Optional callback for inspecting or replacing provider payloads before sending.\n\t * Return undefined to keep the payload unchanged.\n\t */\n\tonPayload?: (\n\t\tpayload: unknown,\n\t\tmodel: TModel,\n\t\trequest?: ProviderRequestMetadata,\n\t) => unknown | undefined | Promise<unknown | undefined>;\n\t/**\n\t * Optional callback invoked after an HTTP response is received.\n\t */\n\tonResponse?: (response: ProviderResponse, model: TModel) => void | Promise<void>;\n\t/**\n\t * Optional custom HTTP headers to include in API requests.\n\t * Merged with provider defaults; caller values override default headers.\n\t * On AWS Bedrock these are injected via a Smithy `build`-step middleware so\n\t * they are covered by SigV4 signing; reserved headers (`x-amz-*`,\n\t * `authorization`, `host`) are silently ignored to preserve SigV4 / bearer auth.\n\t * A null value suppresses a provider/API default header with the same name.\n\t */\n\theaders?: ProviderHeaders;\n\t/**\n\t * HTTP request timeout in milliseconds for providers/SDKs that support it.\n\t * For example, OpenAI and Anthropic SDK clients default to 10 minutes.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum retry attempts for providers/SDKs that support client-side retries.\n\t * For example, OpenAI and Anthropic SDK clients default to 2.\n\t */\n\tmaxRetries?: number;\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately\n\t * with an error containing the requested delay, allowing higher-level retry logic\n\t * to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n}\n\nexport interface StreamOptions extends ProviderRequestOptions<Model<Api>> {\n\ttemperature?: number;\n\t/**\n\t * Arbitrary sampling parameters merged into the request body as-is, after the named request\n\t * fields, so keys here override them. Lets custom OpenAI-compatible servers (llama.cpp, vLLM,\n\t * SGLang, ...) receive parameters pi does not model, e.g. `top_p`, `top_k`, `min_p`,\n\t * `repetition_penalty`. Merged over `Model.samplingParams` per key. Only applied by\n\t * OpenAI-compatible adapters (completions, responses, Azure responses); other APIs ignore it.\n\t */\n\tsamplingParams?: Record<string, unknown>;\n\tmaxTokens?: number;\n\t/**\n\t * Preferred transport for providers that support multiple transports.\n\t * Providers that do not support this option ignore it.\n\t */\n\ttransport?: Transport;\n\t/**\n\t * Prompt cache retention preference. Providers map this to their supported values.\n\t * Default: \"short\".\n\t */\n\tcacheRetention?: CacheRetention;\n\t/**\n\t * Optional session identifier for providers that support session-based caching.\n\t * Providers can use this to enable prompt caching, request routing, or other\n\t * session-aware features. Ignored by providers that don't support it.\n\t */\n\tsessionId?: string;\n\t/**\n\t * Optional custom fields to merge into the outgoing provider request body.\n\t * Applied before `onPayload` so `onPayload` can observe/override them.\n\t * Provider-managed fields (e.g. `model`, `messages`, `stream`) are preserved\n\t * and cannot be overridden to avoid breaking core request semantics.\n\t */\n\textraBody?: Record<string, unknown>;\n\t/**\n\t * WebSocket connect timeout in milliseconds for providers that support\n\t * WebSocket transports. This covers the connection/open handshake only;\n\t * stream idleness after connection uses timeoutMs.\n\t */\n\twebsocketConnectTimeoutMs?: number;\n\t/**\n\t * Optional metadata to include in API requests.\n\t * Providers extract the fields they understand and ignore the rest.\n\t * For example, Anthropic uses `user_id` for abuse tracking and rate limiting.\n\t */\n\tmetadata?: Record<string, unknown>;\n}\n\nexport type ProviderStreamOptions = StreamOptions & Record<string, unknown>;\n\nexport interface DeferredFetchOptions extends ProviderRequestOptions<Model<Api>> {\n\t/**\n\t * Maximum provider long-poll duration in milliseconds.\n\t * Defaults to 0, which performs one status check.\n\t */\n\twait?: number;\n}\n\n/** Request options for best-effort deferred-response cancellation. */\nexport type DeferredCancelOptions = ProviderRequestOptions<Model<Api>>;\n\n/**\n * Maps known APIs to their full provider-specific stream option types.\n * Type-only imports from API implementation modules are erased at emit, so\n * this is tree-shake safe.\n */\nexport interface ApiOptionsMap {\n\t\"anthropic-messages\": AnthropicOptions;\n\t\"openai-completions\": OpenAICompletionsOptions;\n\t\"openai-responses\": OpenAIResponsesOptions;\n\t\"openai-codex-responses\": OpenAICodexResponsesOptions;\n\t\"cursor-agent\": CursorAgentOptions;\n\t\"azure-openai-responses\": AzureOpenAIResponsesOptions;\n\t\"google-generative-ai\": GoogleOptions;\n\t\"google-vertex\": GoogleVertexOptions;\n\t\"mistral-conversations\": MistralOptions;\n\t\"bedrock-converse-stream\": BedrockOptions;\n\t\"pi-messages\": PiMessagesOptions;\n}\n\n/**\n * Full stream options for an API. Known APIs resolve to their concrete option\n * type; custom API strings fall back to the generic shape.\n */\nexport type ApiStreamOptions<TApi extends Api> = TApi extends keyof ApiOptionsMap\n\t? ApiOptionsMap[TApi]\n\t: StreamOptions & Record<string, unknown>;\n\n/**\n * The uniform stream contract of an API implementation module: every module\n * under `src/api/` exports `stream` and `streamSimple`; capable modules may also\n * export deferred-response methods. Lazy wrappers (`lazyApi()`) and provider\n * factories pass these around as values. This is the untyped dispatch shape;\n * per-API option typing lives on the implementation modules themselves and on\n * `Provider.stream()` via `ApiStreamOptions`.\n */\nexport interface ProviderStreams {\n\tstream(model: Model<Api>, context: Context, options?: StreamOptions): AssistantMessageEventStream;\n\tstreamSimple(model: Model<Api>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;\n\tfetchDeferred?(\n\t\tmodel: Model<Api>,\n\t\thandle: DeferredHandle,\n\t\toptions?: DeferredFetchOptions,\n\t): AssistantMessageEventStream;\n\tcancelDeferred?(model: Model<Api>, handle: DeferredHandle, options?: DeferredCancelOptions): Promise<void>;\n}\n\n/**\n * The uniform contract of an image-generation API implementation module:\n * every image API module under `src/api/` exports exactly `generateImages`,\n * so the module itself satisfies this interface. Lazy wrappers and image\n * provider factories pass these around as values.\n */\nexport interface ProviderImages {\n\tgenerateImages(\n\t\tmodel: ImagesModel<ImagesApi>,\n\t\tcontext: ImagesContext,\n\t\toptions?: ImagesOptions,\n\t): Promise<AssistantImages>;\n}\n\nexport interface ImagesOptions extends ProviderRequestOptions<ImagesModel<ImagesApi>> {\n\t/**\n\t * Optional metadata to include in API requests.\n\t * Providers extract the fields they understand and ignore the rest.\n\t */\n\tmetadata?: Record<string, unknown>;\n}\n\nexport type ProviderImagesOptions = ImagesOptions & Record<string, unknown>;\n\nexport type AnthropicRefusalFallback = \"default\" | readonly { model: string }[];\n\n// Unified options with reasoning passed to streamSimple() and completeSimple()\nexport interface SimpleStreamOptions extends StreamOptions {\n\t/** Provider-neutral tool selection for simple requests. Default: \"auto\". */\n\ttoolChoice?: ToolChoice;\n\treasoning?: ThinkingLevel;\n\t/**\n\t * Provenance-bearing thinking selection. Providers that need to distinguish\n\t * an explicit user choice from the always-materialized effective level read\n\t * this; `reasoning` remains the normalized effective level for everyone.\n\t */\n\tthinkingSelection?: ThinkingSelection;\n\t/** Anthropic server-side fallback for eligible refusal stop reasons. Anthropic providers only. */\n\trefusalFallbacks?: AnthropicRefusalFallback;\n\t/** Ask a capable provider to return a durable handle and continue the request asynchronously. */\n\tdeferred?: boolean | { window?: \"15m\" | \"1h\" | \"24h\" };\n\t/** Custom token budgets for thinking levels (token-based providers only) */\n\tthinkingBudgets?: ThinkingBudgets;\n}\n\n// Generic StreamFunction with typed options.\n//\n// Contract:\n// - Must return an AssistantMessageEventStream.\n// - Once invoked, request/model/runtime failures should be encoded in the\n// returned stream, not thrown.\n// - Error termination must produce an AssistantMessage with stopReason\n// \"error\" or \"aborted\" and errorMessage, emitted via the stream protocol.\nexport type StreamFunction<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> = (\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: TOptions,\n) => AssistantMessageEventStream;\n\nexport type ImagesFunction<TApi extends ImagesApi = ImagesApi, TOptions extends ImagesOptions = ImagesOptions> = (\n\tmodel: ImagesModel<TApi>,\n\tcontext: ImagesContext,\n\toptions?: TOptions,\n) => Promise<AssistantImages>;\n\nexport interface TextSignatureV1 {\n\tv: 1;\n\tid: string;\n\tphase?: \"commentary\" | \"final_answer\";\n}\n\nexport interface TextContent {\n\ttype: \"text\";\n\ttext: string;\n\ttextSignature?: string; // e.g., for OpenAI responses, message metadata (legacy id string or TextSignatureV1 JSON)\n}\n\nexport interface ThinkingContent {\n\ttype: \"thinking\";\n\tthinking: string;\n\t/** Epoch ms, stamped by the agent loop at stream-event receipt, best-effort. */\n\tstartedAt?: number;\n\t/** Epoch ms, stamped by the agent loop at stream-event receipt, best-effort. */\n\tendedAt?: number;\n\tthinkingSignature?: string; // e.g., for OpenAI responses, the reasoning item ID\n\t/** When true, the thinking content was redacted by safety filters. The opaque\n\t * encrypted payload is stored in `thinkingSignature` so it can be passed back\n\t * to the API for multi-turn continuity. */\n\tredacted?: boolean;\n}\n\nexport interface ImageContent {\n\ttype: \"image\";\n\tdata: string; // base64 encoded image data\n\tmimeType: string; // e.g., \"image/jpeg\", \"image/png\". Video payloads (e.g. \"video/mp4\") ride this\n\t// same block for models that declare the \"video\" input modality; use isVideoMimeType() to branch.\n}\n\n/** True when an ImageContent block actually carries video data (e.g. \"video/mp4\"). */\nexport function isVideoMimeType(mimeType: string): boolean {\n\treturn mimeType.toLowerCase().startsWith(\"video/\");\n}\n\nexport interface ToolCall {\n\ttype: \"toolCall\";\n\tid: string;\n\tname: string;\n\targuments: Record<string, any>;\n\t/** Set by text tool-call middleware when a truncated call could not be recovered. Carriers of `incomplete` MUST NOT be executed. */\n\tincomplete?: true;\n\t/** Error explaining why an incomplete tool call could not be recovered. */\n\terrorMessage?: string;\n\tthoughtSignature?: string; // Google-specific: opaque signature for reusing thought context\n\t/** OpenAI Responses namespace for calls to dynamically loaded or namespaced tools. */\n\tnamespace?: string;\n}\n\n/**\n * Provider-emitted content block whose semantics are owned by the originating\n * provider. Surfaces server-side tool invocations (web_search), server-side\n * tool results (web_search_tool_result), code execution traces, grounding\n * metadata fragments, and any other vendor-specific block the core does not\n * normalize.\n *\n * `subtype` mirrors the provider's wire `type` discriminator (e.g.\n * \"server_tool_use\", \"web_search_tool_result\", \"executableCode\"). `raw` is\n * the verbatim wire payload — extensions interpret it per provider+subtype.\n *\n * The owning provider id lives on the parent `AssistantMessage.provider`, not\n * here, to avoid drift on replay.\n *\n * On replay across providers, `convertMessages` implementations MUST drop\n * these blocks (they are not portable). This mirrors the existing\n * `redacted_thinking` skip pattern.\n */\nexport interface ProviderNativeContent {\n\ttype: \"providerNative\";\n\tsubtype: string;\n\traw: unknown;\n}\n\nexport interface Usage {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\t/** Subset of `cacheWrite` written with 1h retention. Only Anthropic reports this split. */\n\tcacheWrite1h?: number;\n\t/**\n\t * Reasoning/thinking tokens, when the provider reports them. This is a subset of\n\t * `output`: `output` already includes these tokens. Set to a number (possibly 0) by\n\t * providers that expose a reasoning breakdown; left undefined by providers that don't.\n\t */\n\treasoning?: number;\n\ttotalTokens: number;\n\tcost: {\n\t\tinput: number;\n\t\toutput: number;\n\t\tcacheRead: number;\n\t\tcacheWrite: number;\n\t\ttotal: number;\n\t};\n}\n\nexport type StopReason = \"pending\" | \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\" | \"deferred\";\n\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\n\nexport interface DeferredHandle {\n\tprovider: string;\n\tmodelId: string;\n\tapi: string;\n\t/** Provider token, such as a response id or batch id plus row id. */\n\tid: string;\n\texpiresAt?: number;\n\tpollAfterMs?: number;\n\t/** Provider conversion data required to reconstruct the final assistant message. */\n\tdata?: JsonValue;\n}\n\nexport type AssistantStopDetails = { type: \"refusal\"; explanation?: string } | { type: \"sensitive\" };\n\nexport interface UserMessage {\n\trole: \"user\";\n\tcontent: string | (TextContent | ImageContent)[];\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport interface AssistantMessage {\n\trole: \"assistant\";\n\tcontent: (TextContent | ThinkingContent | ToolCall | ProviderNativeContent)[];\n\tapi: Api;\n\tprovider: ProviderId;\n\tmodel: string;\n\tresponseModel?: string; // Concrete `chunk.model` when different from the requested `model` (e.g. OpenRouter `auto` -> `anthropic/...`)\n\tresponseId?: string; // Provider-specific response/message identifier when the upstream API exposes one\n\tdiagnostics?: AssistantMessageDiagnostic[]; // Redacted provider/runtime diagnostics for failures and recoveries.\n\tusage: Usage;\n\tstopReason: StopReason;\n\tstopDetails?: AssistantStopDetails;\n\tdeferred?: DeferredHandle;\n\terrorMessage?: string;\n\trawStopReason?: string;\n\t/**\n\t * Provider indication of whether the model explicitly ended its turn.\n\t * Preserved for debugging and does not currently affect agent control flow.\n\t */\n\tendTurn?: boolean;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport interface ToolResultMessage<TDetails = any> {\n\trole: \"toolResult\";\n\ttoolCallId: string;\n\ttoolName: string;\n\tcontent: (TextContent | ImageContent)[]; // Supports text and images\n\tdetails?: TDetails;\n\t/** Usage from the tool execution itself, if available. Not part of main LLM context accounting. */\n\tusage?: Usage;\n\t/**\n\t * Names from `Context.tools` that became available after this result.\n\t * Providers with native deferred tool loading use this as the load point;\n\t * other providers ignore it and use `Context.tools` normally.\n\t */\n\taddedToolNames?: string[];\n\tisError: boolean;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport type Message = UserMessage | AssistantMessage | ToolResultMessage;\n\nexport type ImagesInputContent = TextContent | ImageContent;\nexport type ImagesOutputContent = TextContent | ImageContent;\n\nexport interface ImagesContext {\n\tinput: ImagesInputContent[];\n}\n\nexport type ImagesStopReason = \"stop\" | \"error\" | \"aborted\";\n\nexport interface AssistantImages {\n\tapi: ImagesApi;\n\tprovider: ImagesProviderId;\n\tmodel: string;\n\toutput: ImagesOutputContent[];\n\tresponseId?: string;\n\tusage?: Usage;\n\tstopReason: ImagesStopReason;\n\terrorMessage?: string;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nimport type { TSchema } from \"typebox\";\n\nexport interface FreeformToolFormat {\n\ttype: \"grammar\";\n\tsyntax: \"lark\";\n\tdefinition: string;\n}\n\n/** OpenAI grammar variants for constrained sampling. */\nexport type GrammarFormat = \"openai_lark\" | \"openai_regex\";\n\nexport type GrammarVariants = Partial<Record<GrammarFormat, string>>;\n\n/**\n * Optional provider-side constrained sampling configs for a tool.\n *\n * The `json_schema` value roughly maps to the concept of `strict` in APIs which is\n * implemented as json-schema constrained sampling by APIs. Grammar variants let\n * callers provide provider-specific encodings of the same intended language.\n */\nexport type ConstrainedSamplingConfig =\n\t| {\n\t\t\ttype: \"json_schema\";\n\t\t\tstrict: \"prefer\" | \"require\";\n\t }\n\t| {\n\t\t\ttype: \"grammar\";\n\t\t\tvariants: GrammarVariants;\n\t };\nexport interface Tool<TParameters extends TSchema = TSchema> {\n\tname: string;\n\tdescription: string;\n\tparameters: TParameters;\n\tfreeform?: FreeformToolFormat;\n\tconstrainedSampling?: false | ConstrainedSamplingConfig;\n}\n\nexport interface Context {\n\tsystemPrompt?: string;\n\tmessages: Message[];\n\ttools?: Tool[];\n}\n\n/**\n * Event protocol for AssistantMessageEventStream.\n *\n * Streams should emit `start` before partial updates, then terminate with either:\n * - `done` carrying the final successful AssistantMessage, or\n * - `error` carrying the final AssistantMessage with stopReason \"error\" or \"aborted\"\n * and errorMessage.\n */\nexport type AssistantMessageEvent =\n\t| { type: \"start\"; partial: AssistantMessage }\n\t| { type: \"text_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| { type: \"text_end\"; contentIndex: number; content: string; partial: AssistantMessage }\n\t| { type: \"thinking_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| { type: \"thinking_end\"; contentIndex: number; content: string; partial: AssistantMessage }\n\t| { type: \"toolcall_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t/** Finalized - executable iff `incomplete !== true` on `toolCall`. */\n\t| { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall; partial: AssistantMessage }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<StopReason, \"stop\" | \"length\" | \"toolUse\" | \"deferred\">;\n\t\t\tmessage: AssistantMessage;\n\t }\n\t| { type: \"error\"; reason: Extract<StopReason, \"aborted\" | \"error\">; error: AssistantMessage };\n\n/**\n * Compatibility settings for OpenAI-compatible completions APIs.\n * Use this to override URL-based auto-detection for custom providers.\n */\nexport interface OpenAICompletionsCompat {\n\t/** Whether the provider supports the `store` field. Default: auto-detected from URL. */\n\tsupportsStore?: boolean;\n\t/** Whether the provider supports the `developer` role (vs `system`). Default: auto-detected from URL. */\n\tsupportsDeveloperRole?: boolean;\n\t/** Whether the provider supports `reasoning_effort`. Default: auto-detected from URL. */\n\tsupportsReasoningEffort?: boolean;\n\t/** Whether the provider supports `stream_options: { include_usage: true }` for token usage in streaming responses. Default: true. */\n\tsupportsUsageInStreaming?: boolean;\n\t/** Whether streamed responses include `finish_reason`. When false, pi infers `stop` or `toolUse` when the stream ends. Default: true. */\n\tsupportsFinishReason?: boolean;\n\t/** Which field to use for max tokens. Default: auto-detected from URL. */\n\tmaxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n\t/** Whether tool results require the `name` field. Default: auto-detected from URL. */\n\trequiresToolResultName?: boolean;\n\t/** Whether a user message after tool results requires an assistant message in between. Default: auto-detected from URL. */\n\trequiresAssistantAfterToolResult?: boolean;\n\t/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */\n\trequiresThinkingAsText?: boolean;\n\t/** Whether all replayed assistant messages must include an empty reasoning_content field when reasoning is enabled. Default: auto-detected from URL. */\n\trequiresReasoningContentOnAssistantMessages?: boolean;\n\t/** Format for reasoning/thinking parameter. \"openai\" uses reasoning_effort, \"openrouter\" uses reasoning: { effort }, \"deepseek\" uses thinking: { type } plus reasoning_effort when supported, \"together\" uses reasoning: { enabled } plus reasoning_effort when supported, \"baseten\" uses configurable chat_template_args plus reasoning_effort when supported, \"zai\" uses thinking: { type }, \"qwen\" uses top-level enable_thinking: boolean, \"qwen-chat-template\" uses chat_template_kwargs.enable_thinking and preserve_thinking, \"chat-template\" uses configurable chat_template_kwargs, \"string-thinking\" uses top-level thinking: string, and \"ant-ling\" uses reasoning: { effort } only when the mapped effort is non-null. Default: \"openai\". */\n\tthinkingFormat?:\n\t\t| \"openai\"\n\t\t| \"openrouter\"\n\t\t| \"deepseek\"\n\t\t| \"together\"\n\t\t| \"baseten\"\n\t\t| \"zai\"\n\t\t| \"qwen\"\n\t\t| \"chat-template\"\n\t\t| \"qwen-chat-template\"\n\t\t| \"string-thinking\"\n\t\t| \"ant-ling\";\n\t/** Whether the provider accepts explicit disabled-thinking markers when thinking is off. Default: true. */\n\tsupportsDisabledThinking?: boolean;\n\t/** Kwargs to send as `chat_template_kwargs` when `thinkingFormat` is `chat-template`. Use `{ \"$var\": \"thinking.enabled\" }`, `{ \"$var\": \"thinking.effort\" }`, or `{ \"$var\": \"thinking.budget\" }` for pi-controlled thinking values. */\n\tchatTemplateKwargs?: Record<string, ChatTemplateKwargValue>;\n\t/** Arguments to send as `chat_template_args` when `thinkingFormat` is `baseten`. Use `{ \"$var\": \"thinking.enabled\" }`, `{ \"$var\": \"thinking.effort\" }`, or `{ \"$var\": \"thinking.budget\" }` for pi-controlled thinking values. */\n\tchatTemplateArgs?: Record<string, ChatTemplateKwargValue>;\n\t/** OpenRouter-compatible routing preferences sent as the `provider` request field. */\n\topenRouterRouting?: OpenRouterRouting;\n\t/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */\n\tvercelGatewayRouting?: VercelGatewayRouting;\n\t/** Whether z.ai supports top-level `tool_stream: true` for streaming tool call deltas. Default: false. */\n\tzaiToolStream?: boolean;\n\t/**\n\t * Top-level request field used to cap reasoning tokens from `thinkingBudgets`.\n\t * Reasoning and the answer share `max_tokens` on these endpoints, so without a budget a\n\t * reasoning-heavy turn can consume the whole response and emit no answer.\n\t * `\"thinking_token_budget\"` is vLLM, `\"thinking_budget\"` is Qwen/DashScope/SGLang,\n\t * `\"thinking_budget_tokens\"` is llama.cpp. Off by default; not set on the generated catalog.\n\t */\n\tthinkingTokenBudgetField?: ThinkingTokenBudgetField;\n\t/** Alias for `thinkingTokenBudgetField: \"thinking_token_budget\"` (vLLM). Prefer `thinkingTokenBudgetField`. Default: false. */\n\tsupportsThinkingTokenBudget?: boolean;\n\t/** Whether the provider supports OpenAI custom tools with Lark/regex grammar formats. When false, grammar-constrained tools fall back to normal function tools. Default: false; the generated model catalog enables it for capable models. */\n\tsupportsOpenAIGrammarTools?: boolean;\n\t/** Whether the provider supports the `strict` field in tool definitions. Default: true. */\n\tsupportsStrictMode?: boolean;\n\t/**\n\t * Provider-specific JSON Schema flavor for tool parameters. `\"moonshot-mfjs\"`\n\t * normalizes schemas for Moonshot / Kimi backends that enforce a stricter subset.\n\t */\n\ttoolSchemaFlavor?: \"moonshot-mfjs\";\n\t/**\n\t * Tool call format for models that don't natively support tool calling.\n\t * When set, the middleware will intercept tool calls and format them as text.\n\t * Supported values: \"hermes\", \"morph-xml\", \"xml\" (deprecated alias for \"morph-xml\"), \"yaml-xml\", \"gemma4-delimiter\", \"anthropic-xml\", \"antml\", \"kimi-xtml\"\n\t */\n\ttoolCallFormat?: string;\n\t/** Cache control convention for prompt caching. \"anthropic\" applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user, assistant, or tool-result text content. */\n\tcacheControlFormat?: \"anthropic\";\n\t/** Whether to send session-affinity data from `options.sessionId`. Default: false. */\n\tsendSessionAffinityHeaders?: boolean;\n\t/** Provider-specific deferred tool serialization mode. */\n\tdeferredToolsMode?: \"kimi\";\n\t/** Session-affinity header format: `openai` sends `session_id`, `x-client-request-id`, and `x-session-affinity`; `openai-nosession` sends `x-client-request-id` and `x-session-affinity`; `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param, which is governed by cache retention. Default: auto-detected. */\n\tsessionAffinityFormat?: SessionAffinityFormat;\n\t/** Whether the provider accepts the `prompt_cache_key` request field. Default: auto-detected. */\n\tsupportsPromptCacheKey?: boolean;\n\t/** Whether the provider supports long prompt cache retention (`prompt_cache_retention: \"24h\"` or Anthropic-style `cache_control.ttl: \"1h\"`, depending on format). Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n}\n\n/** Compatibility settings for Anthropic Messages-compatible APIs. */\nexport interface AnthropicMessagesCompat {\n\t/**\n\t * Whether the provider accepts per-tool `eager_input_streaming`.\n\t * When false, the Anthropic provider omits `tools[].eager_input_streaming`\n\t * and sends the legacy `fine-grained-tool-streaming-2025-05-14` beta header\n\t * for tool-enabled requests.\n\t * Default: true.\n\t */\n\tsupportsEagerToolInputStreaming?: boolean;\n\t/** Whether the provider supports Anthropic long cache retention (`cache_control.ttl: \"1h\"`). Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n\t/**\n\t * Whether to send the `x-session-affinity` header from `options.sessionId`\n\t * when caching is enabled. Required for providers like Fireworks that use\n\t * session affinity for prompt cache routing (requests to the same replica\n\t * maximize cache hits).\n\t * Default: false.\n\t */\n\tsendSessionAffinityHeaders?: boolean;\n\t/**\n\t * Whether the provider supports Anthropic-style `cache_control` markers on\n\t * tool definitions. When false, `cache_control` is omitted from tool params.\n\t * Some Anthropic-compatible providers (e.g., Fireworks) do not support this\n\t * field on tools and may reject or ignore it.\n\t * Default: true.\n\t */\n\tsupportsCacheControlOnTools?: boolean;\n\t/**\n\t * Whether the provider accepts `thinking: { type: \"disabled\" }` when\n\t * extended thinking is off. Some Anthropic-compatible providers support\n\t * thinking but reject Anthropic's explicit disabled marker.\n\t * Default: true.\n\t */\n\tsupportsDisabledThinking?: boolean;\n\t/**\n\t * Whether the model accepts the Anthropic `temperature` request field.\n\t * Claude Opus 4.7+ rejects non-default temperature values.\n\t * Default: true.\n\t */\n\tsupportsTemperature?: boolean;\n\t/** Whether the model accepts Anthropic `tool_choice`. Default: true. */\n\tsupportsToolChoice?: boolean;\n\t/**\n\t * Whether the model accepts forced Anthropic tool choices (`any` or a named\n\t * tool). Default: true, except Claude Fable/Mythos models.\n\t */\n\tsupportsForcedToolChoice?: boolean;\n\t/**\n\t * Whether to force adaptive thinking (`thinking.type: \"adaptive\"` plus\n\t * `output_config.effort`) regardless of the model id. Built-in models that\n\t * require adaptive thinking set this in generated metadata. Custom\n\t * Anthropic-compatible providers can set this to `true` for any model whose\n\t * upstream requires the adaptive format. Set to `false` to opt out on\n\t * overridden built-in models and disable model id/name inference.\n\t * Default: infer from adaptive Claude model ids/names when possible.\n\t */\n\tforceAdaptiveThinking?: boolean;\n\t/** Whether to replay empty thinking signatures as `signature: \"\"` instead of converting thinking to text. Default: false. */\n\tallowEmptySignature?: boolean;\n\t/** Whether the provider supports Anthropic strict tool schemas. Default: false; generated Anthropic models enable it explicitly. */\n\tsupportsStrictTools?: boolean;\n\t/**\n\t * How to replay thinking blocks that have no usable Anthropic signature.\n\t * `\"text\"` demotes them to text; `\"empty-signature\"` preserves Anthropic's\n\t * thinking shape with `signature: \"\"`. Defaults to `\"text\"`; the legacy\n\t * `allowEmptySignature` setting remains a compatibility alias for\n\t * `\"empty-signature\"`.\n\t */\n\tunsignedThinkingReplay?: \"text\" | \"empty-signature\";\n\t/**\n\t * Model ids Anthropic accepts in `fallbacks` for server-side refusal fallback.\n\t * When absent or empty, callers must omit `fallbacks`; Anthropic rejects the\n\t * field for models with no permitted fallback targets.\n\t */\n\tallowedFallbackModels?: string[];\n\t/**\n\t * Whether the provider supports deferred tools loaded by `tool_reference`\n\t * blocks in tool results. Default: true for first-party Anthropic models\n\t * except Haiku and models older than Claude 4.5; false for other providers.\n\t */\n\tsupportsToolReferences?: boolean;\n\t/**\n\t * Whether the provider executes Anthropic server-side `web_search_*` native\n\t * tools and accepts their `server_tool_use` / `web_search_tool_result`\n\t * blocks on replay. Anthropic-compatible endpoints (e.g., kimi-coding) may\n\t * run the search but reject the replayed server-tool blocks on the next\n\t * request. When false, hook-injected `web_search_*` tools are stripped from\n\t * the payload. Default: true only for the first-party Anthropic endpoint.\n\t */\n\tsupportsWebSearch?: boolean;\n}\n\n/** Compatibility settings for Amazon Bedrock models. */\nexport interface BedrockCompat {\n\t/** Whether the model supports Bedrock strict tool schemas. Default: false. */\n\tsupportsStrictMode?: boolean;\n}\n\n/**\n * OpenRouter provider routing preferences.\n * Controls which upstream providers OpenRouter routes requests to.\n * Sent as the `provider` field in the OpenRouter API request body.\n * @see https://openrouter.ai/docs/guides/routing/provider-selection\n */\nexport interface OpenRouterRouting {\n\t/** Whether to allow backup providers to serve requests. Default: true. */\n\tallow_fallbacks?: boolean;\n\t/** Whether to filter providers to only those that support all parameters in the request. Default: false. */\n\trequire_parameters?: boolean;\n\t/** Data collection setting. \"allow\" (default): allow providers that may store/train on data. \"deny\": only use providers that don't collect user data. */\n\tdata_collection?: \"deny\" | \"allow\";\n\t/** Whether to restrict routing to only ZDR (Zero Data Retention) endpoints. */\n\tzdr?: boolean;\n\t/** Whether to restrict routing to only models that allow text distillation. */\n\tenforce_distillable_text?: boolean;\n\t/** An ordered list of provider names/slugs to try in sequence, falling back to the next if unavailable. */\n\torder?: string[];\n\t/** List of provider names/slugs to exclusively allow for this request. */\n\tonly?: string[];\n\t/** List of provider names/slugs to skip for this request. */\n\tignore?: string[];\n\t/** A list of quantization levels to filter providers by (e.g., [\"fp16\", \"bf16\", \"fp8\", \"fp6\", \"int8\", \"int4\", \"fp4\", \"fp32\"]). */\n\tquantizations?: string[];\n\t/** Sorting strategy. Can be a string (e.g., \"price\", \"throughput\", \"latency\") or an object with `by` and `partition`. */\n\tsort?:\n\t\t| string\n\t\t| {\n\t\t\t\t/** The sorting metric: \"price\", \"throughput\", \"latency\". */\n\t\t\t\tby?: string;\n\t\t\t\t/** Partitioning strategy: \"model\" (default) or \"none\". */\n\t\t\t\tpartition?: string | null;\n\t\t };\n\t/** Maximum price per million tokens (USD). */\n\tmax_price?: {\n\t\t/** Price per million prompt tokens. */\n\t\tprompt?: number | string;\n\t\t/** Price per million completion tokens. */\n\t\tcompletion?: number | string;\n\t\t/** Price per image. */\n\t\timage?: number | string;\n\t\t/** Price per audio unit. */\n\t\taudio?: number | string;\n\t\t/** Price per request. */\n\t\trequest?: number | string;\n\t};\n\t/** Preferred minimum throughput (tokens/second). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */\n\tpreferred_min_throughput?:\n\t\t| number\n\t\t| {\n\t\t\t\t/** Minimum tokens/second at the 50th percentile. */\n\t\t\t\tp50?: number;\n\t\t\t\t/** Minimum tokens/second at the 75th percentile. */\n\t\t\t\tp75?: number;\n\t\t\t\t/** Minimum tokens/second at the 90th percentile. */\n\t\t\t\tp90?: number;\n\t\t\t\t/** Minimum tokens/second at the 99th percentile. */\n\t\t\t\tp99?: number;\n\t\t };\n\t/** Preferred maximum latency (seconds). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */\n\tpreferred_max_latency?:\n\t\t| number\n\t\t| {\n\t\t\t\t/** Maximum latency in seconds at the 50th percentile. */\n\t\t\t\tp50?: number;\n\t\t\t\t/** Maximum latency in seconds at the 75th percentile. */\n\t\t\t\tp75?: number;\n\t\t\t\t/** Maximum latency in seconds at the 90th percentile. */\n\t\t\t\tp90?: number;\n\t\t\t\t/** Maximum latency in seconds at the 99th percentile. */\n\t\t\t\tp99?: number;\n\t\t };\n}\n\n/**\n * Vercel AI Gateway routing preferences.\n * Controls which upstream providers the gateway routes requests to.\n * @see https://vercel.com/docs/ai-gateway/models-and-providers/provider-options\n */\nexport interface VercelGatewayRouting {\n\t/** List of provider slugs to exclusively use for this request (e.g., [\"bedrock\", \"anthropic\"]). */\n\tonly?: string[];\n\t/** List of provider slugs to try in order (e.g., [\"anthropic\", \"openai\"]). */\n\torder?: string[];\n}\n\nexport interface ModelCostRates {\n\tinput: number; // $/million tokens\n\toutput: number; // $/million tokens\n\tcacheRead: number; // $/million tokens\n\tcacheWrite: number; // $/million tokens\n}\n\nexport interface ModelCostTier extends ModelCostRates {\n\t/** Use this tier for requests whose total input usage exceeds this token count. */\n\tinputTokensAbove: number;\n}\n\nexport interface ModelCost extends ModelCostRates {\n\t/** Request-wide pricing tiers. The highest matching input threshold applies to the full request. */\n\ttiers?: ModelCostTier[];\n}\n\nexport interface ImagesModel<TApi extends ImagesApi>\n\textends Omit<Model<Api>, \"api\" | \"provider\" | \"reasoning\" | \"contextWindow\" | \"maxTokens\" | \"compat\"> {\n\tapi: TApi;\n\tprovider: ImagesProviderId;\n\toutput: (\"text\" | \"image\")[];\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA+bA,sFAAsF;AACtF,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC/C,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AACpD,CAAC","sourcesContent":["import type { TelemetryContext } from \"@earendil-works/pi-telemetry\";\nimport type { AnthropicOptions } from \"./api/anthropic-messages.ts\";\nimport type { AzureOpenAIResponsesOptions } from \"./api/azure-openai-responses.ts\";\nimport type { BedrockOptions } from \"./api/bedrock-converse-stream.ts\";\nimport type { CursorAgentOptions } from \"./api/cursor-agent/types.ts\";\nimport type { GoogleOptions } from \"./api/google-generative-ai.ts\";\nimport type { GoogleVertexOptions } from \"./api/google-vertex.ts\";\nimport type { MistralOptions } from \"./api/mistral-conversations.ts\";\nimport type { OpenAICodexResponsesOptions } from \"./api/openai-codex-responses.ts\";\nimport type { OpenAICompletionsOptions } from \"./api/openai-completions.ts\";\nimport type { OpenAIResponsesOptions } from \"./api/openai-responses.ts\";\nimport type { PiMessagesOptions } from \"./api/pi-messages.ts\";\nimport type { Model } from \"./model.ts\";\nimport type {\n\tOpenAIResponsesCompat as BaseOpenAIResponsesCompat,\n\tSessionAffinityFormat,\n} from \"./openai-responses-compat.ts\";\nimport type { AssistantMessageDiagnostic } from \"./utils/diagnostics.ts\";\nimport type { AssistantMessageEventStream } from \"./utils/event-stream.ts\";\n\nexport type { Model } from \"./model.ts\";\nexport type { SessionAffinityFormat } from \"./openai-responses-compat.ts\";\nexport type OpenAIResponsesCompat = BaseOpenAIResponsesCompat & {\n\t/** Whether the model supports message-anchored `additional_tools` input items. Default: false. */\n\tsupportsAdditionalTools?: boolean;\n};\nexport type { AssistantMessageEventStream } from \"./utils/event-stream.ts\";\n\nexport type KnownApi =\n\t| \"openai-completions\"\n\t| \"mistral-conversations\"\n\t| \"openai-responses\"\n\t| \"azure-openai-responses\"\n\t| \"openai-codex-responses\"\n\t| \"cursor-agent\"\n\t| \"anthropic-messages\"\n\t| \"bedrock-converse-stream\"\n\t| \"google-generative-ai\"\n\t| \"google-vertex\"\n\t| \"pi-messages\";\n\nexport type Api = KnownApi | (string & {});\n\nexport type KnownImagesApi = \"openrouter-images\" | \"openai-images\";\n\nexport type ImagesApi = KnownImagesApi | (string & {});\n\nexport type KnownProvider =\n\t| \"alibaba-token-plan\"\n\t| \"amazon-bedrock\"\n\t| \"ant-ling\"\n\t| \"anthropic\"\n\t| \"google\"\n\t| \"google-vertex\"\n\t| \"openai\"\n\t| \"azure-openai-responses\"\n\t| \"openai-codex\"\n\t| \"ollama\"\n\t| \"cursor\"\n\t| \"radius\"\n\t| \"nvidia\"\n\t| \"deepseek\"\n\t| \"github-copilot\"\n\t| \"xai\"\n\t| \"groq\"\n\t| \"cerebras\"\n\t| \"openrouter\"\n\t| \"vercel-ai-gateway\"\n\t| \"opengateway\"\n\t| \"zai\"\n\t| \"zai-coding-cn\"\n\t| \"mistral\"\n\t| \"minimax\"\n\t| \"minimax-cn\"\n\t| \"moonshotai\"\n\t| \"moonshotai-cn\"\n\t| \"huggingface\"\n\t| \"fireworks\"\n\t| \"together\"\n\t| \"baseten\"\n\t| \"opencode\"\n\t| \"opencode-go\"\n\t| \"kimi-coding\"\n\t| \"cloudflare-workers-ai\"\n\t| \"cloudflare-ai-gateway\"\n\t| \"qwen-token-plan\"\n\t| \"qwen-token-plan-cn\"\n\t| \"qwen-token-plan-individual\"\n\t| \"xiaomi\"\n\t| \"xiaomi-token-plan-cn\"\n\t| \"xiaomi-token-plan-ams\"\n\t| \"xiaomi-token-plan-sgp\";\nexport type ProviderId = KnownProvider | string;\n\nexport type KnownImagesProvider = \"openrouter\";\n\nexport type ImagesProviderId = KnownImagesProvider | string;\n\nexport type ToolChoice = \"auto\" | \"none\";\nexport type ThinkingLevel = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\nexport type ModelThinkingLevel = \"off\" | ThinkingLevel;\n\n/**\n * Provenance-bearing thinking selection. Distinct from the always-materialized\n * effective level: a selection exists only when the user (or a legacy variant\n * alias) explicitly chose a level. See .omo/plans/cursor-reasoning-levels.md §4.1.\n */\nexport interface ThinkingSelection {\n\treadonly level: ModelThinkingLevel;\n\treadonly source: \"explicit\" | \"legacy-variant\";\n\t/** Required when source is \"legacy-variant\": the exact allowlisted original variant id. */\n\treadonly legacyVariantId?: string;\n}\nexport type ThinkingLevelMap = Partial<Record<ModelThinkingLevel, string | null>>;\nexport type ChatTemplateKwargValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| {\n\t\t\t$var: \"thinking.enabled\" | \"thinking.effort\" | \"thinking.budget\";\n\t\t\tomitWhenOff?: boolean;\n\t };\n\n/** Top-level request field used to cap reasoning tokens on OpenAI-compatible servers. */\nexport type ThinkingTokenBudgetField = \"thinking_token_budget\" | \"thinking_budget\" | \"thinking_budget_tokens\";\n\n/** Token budgets for each thinking level (token-based providers only) */\nexport interface ThinkingBudgets {\n\tminimal?: number;\n\tlow?: number;\n\tmedium?: number;\n\thigh?: number;\n\tmax?: number;\n}\n\n// Base options all providers share\nexport type CacheRetention = \"none\" | \"short\" | \"long\";\n\nexport type Transport = \"sse\" | \"websocket\" | \"websocket-cached\" | \"auto\";\n\n/** Provider-scoped environment overrides. Values take precedence over process.env. */\nexport type ProviderEnv = Record<string, string>;\nexport type ProviderHeaders = Record<string, string | null>;\n/** Effective model and fully transformed headers for a request payload hook. */\nexport type ProviderRequestMetadata = {\n\tmodel: Model<Api>;\n\theaders: ProviderHeaders;\n};\nexport type FetchFunction = typeof globalThis.fetch;\n\nexport interface ProviderResponse {\n\tstatus: number;\n\theaders: Record<string, string>;\n}\n\n/** Authentication, HTTP transport, and lifecycle callbacks shared by provider requests. */\nexport interface ProviderRequestOptions<TModel = Model<Api>> {\n\tsignal?: AbortSignal;\n\t/**\n\t * Abort the request when the provider reports that a safety classifier\n\t * declined the requested model and a substitute model served the turn\n\t * instead (Anthropic `server-side-fallback-*` betas). The substitute's output\n\t * is billed but was never requested, so aborting keeps model selection with\n\t * the caller. Providers without server-side fallback ignore this.\n\t * Default: undefined (honor the substituted response).\n\t */\n\tabortServerSideFallback?: boolean;\n\t/** Explicit parent context for telemetry produced by this logical request. */\n\ttelemetryContext?: TelemetryContext;\n\tapiKey?: string;\n\t/**\n\t * Stable identity of the originating session for account-affinity providers,\n\t * preserved across auxiliary calls that replace `sessionId` (for example\n\t * compaction). Providers without account affinity ignore this.\n\t */\n\taffinitySessionId?: string;\n\t/**\n\t * Identifies whether the stream belongs to the main agent loop or an auxiliary request.\n\t * An absent value must be treated as auxiliary as a fail-safe.\n\t */\n\tstreamKind?: \"main\" | \"auxiliary\";\n\t/**\n\t * Optional fetch implementation for provider HTTP requests.\n\t * Defaults to `globalThis.fetch`. Provider adapters that cannot inject a custom implementation may reject it.\n\t * This does not affect WebSocket transports.\n\t */\n\tfetch?: FetchFunction;\n\t/**\n\t * Provider-scoped environment values. These take precedence over process.env for\n\t * provider configuration such as regional settings, endpoint placeholders, and\n\t * proxy variables.\n\t */\n\tenv?: ProviderEnv;\n\t/**\n\t * Optional callback for inspecting or replacing provider payloads before sending.\n\t * Return undefined to keep the payload unchanged.\n\t */\n\tonPayload?: (\n\t\tpayload: unknown,\n\t\tmodel: TModel,\n\t\trequest?: ProviderRequestMetadata,\n\t) => unknown | undefined | Promise<unknown | undefined>;\n\t/**\n\t * Optional callback invoked after an HTTP response is received.\n\t */\n\tonResponse?: (response: ProviderResponse, model: TModel) => void | Promise<void>;\n\t/**\n\t * Optional custom HTTP headers to include in API requests.\n\t * Merged with provider defaults; caller values override default headers.\n\t * On AWS Bedrock these are injected via a Smithy `build`-step middleware so\n\t * they are covered by SigV4 signing; reserved headers (`x-amz-*`,\n\t * `authorization`, `host`) are silently ignored to preserve SigV4 / bearer auth.\n\t * A null value suppresses a provider/API default header with the same name.\n\t */\n\theaders?: ProviderHeaders;\n\t/**\n\t * HTTP request timeout in milliseconds for providers/SDKs that support it.\n\t * For example, OpenAI and Anthropic SDK clients default to 10 minutes.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum retry attempts for providers/SDKs that support client-side retries.\n\t * For example, OpenAI and Anthropic SDK clients default to 2.\n\t */\n\tmaxRetries?: number;\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately\n\t * with an error containing the requested delay, allowing higher-level retry logic\n\t * to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n}\n\nexport interface StreamOptions extends ProviderRequestOptions<Model<Api>> {\n\ttemperature?: number;\n\t/**\n\t * Arbitrary sampling parameters merged into the request body as-is, after the named request\n\t * fields, so keys here override them. Lets custom OpenAI-compatible servers (llama.cpp, vLLM,\n\t * SGLang, ...) receive parameters pi does not model, e.g. `top_p`, `top_k`, `min_p`,\n\t * `repetition_penalty`. Merged over `Model.samplingParams` per key. Only applied by\n\t * OpenAI-compatible adapters (completions, responses, Azure responses); other APIs ignore it.\n\t */\n\tsamplingParams?: Record<string, unknown>;\n\tmaxTokens?: number;\n\t/**\n\t * Preferred transport for providers that support multiple transports.\n\t * Providers that do not support this option ignore it.\n\t */\n\ttransport?: Transport;\n\t/**\n\t * Prompt cache retention preference. Providers map this to their supported values.\n\t * Default: \"short\".\n\t */\n\tcacheRetention?: CacheRetention;\n\t/**\n\t * Optional session identifier for providers that support session-based caching.\n\t * Providers can use this to enable prompt caching, request routing, or other\n\t * session-aware features. Ignored by providers that don't support it.\n\t */\n\tsessionId?: string;\n\t/**\n\t * Optional custom fields to merge into the outgoing provider request body.\n\t * Applied before `onPayload` so `onPayload` can observe/override them.\n\t * Provider-managed fields (e.g. `model`, `messages`, `stream`) are preserved\n\t * and cannot be overridden to avoid breaking core request semantics.\n\t */\n\textraBody?: Record<string, unknown>;\n\t/**\n\t * WebSocket connect timeout in milliseconds for providers that support\n\t * WebSocket transports. This covers the connection/open handshake only;\n\t * stream idleness after connection uses timeoutMs.\n\t */\n\twebsocketConnectTimeoutMs?: number;\n\t/**\n\t * Optional metadata to include in API requests.\n\t * Providers extract the fields they understand and ignore the rest.\n\t * For example, Anthropic uses `user_id` for abuse tracking and rate limiting.\n\t */\n\tmetadata?: Record<string, unknown>;\n}\n\nexport type ProviderStreamOptions = StreamOptions & Record<string, unknown>;\n\nexport interface DeferredFetchOptions extends ProviderRequestOptions<Model<Api>> {\n\t/**\n\t * Maximum provider long-poll duration in milliseconds.\n\t * Defaults to 0, which performs one status check.\n\t */\n\twait?: number;\n}\n\n/** Request options for best-effort deferred-response cancellation. */\nexport type DeferredCancelOptions = ProviderRequestOptions<Model<Api>>;\n\n/**\n * Maps known APIs to their full provider-specific stream option types.\n * Type-only imports from API implementation modules are erased at emit, so\n * this is tree-shake safe.\n */\nexport interface ApiOptionsMap {\n\t\"anthropic-messages\": AnthropicOptions;\n\t\"openai-completions\": OpenAICompletionsOptions;\n\t\"openai-responses\": OpenAIResponsesOptions;\n\t\"openai-codex-responses\": OpenAICodexResponsesOptions;\n\t\"cursor-agent\": CursorAgentOptions;\n\t\"azure-openai-responses\": AzureOpenAIResponsesOptions;\n\t\"google-generative-ai\": GoogleOptions;\n\t\"google-vertex\": GoogleVertexOptions;\n\t\"mistral-conversations\": MistralOptions;\n\t\"bedrock-converse-stream\": BedrockOptions;\n\t\"pi-messages\": PiMessagesOptions;\n}\n\n/**\n * Full stream options for an API. Known APIs resolve to their concrete option\n * type; custom API strings fall back to the generic shape.\n */\nexport type ApiStreamOptions<TApi extends Api> = TApi extends keyof ApiOptionsMap\n\t? ApiOptionsMap[TApi]\n\t: StreamOptions & Record<string, unknown>;\n\n/**\n * The uniform stream contract of an API implementation module: every module\n * under `src/api/` exports `stream` and `streamSimple`; capable modules may also\n * export deferred-response methods. Lazy wrappers (`lazyApi()`) and provider\n * factories pass these around as values. This is the untyped dispatch shape;\n * per-API option typing lives on the implementation modules themselves and on\n * `Provider.stream()` via `ApiStreamOptions`.\n */\nexport interface ProviderStreams {\n\tstream(model: Model<Api>, context: Context, options?: StreamOptions): AssistantMessageEventStream;\n\tstreamSimple(model: Model<Api>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;\n\tfetchDeferred?(\n\t\tmodel: Model<Api>,\n\t\thandle: DeferredHandle,\n\t\toptions?: DeferredFetchOptions,\n\t): AssistantMessageEventStream;\n\tcancelDeferred?(model: Model<Api>, handle: DeferredHandle, options?: DeferredCancelOptions): Promise<void>;\n}\n\n/**\n * The uniform contract of an image-generation API implementation module:\n * every image API module under `src/api/` exports exactly `generateImages`,\n * so the module itself satisfies this interface. Lazy wrappers and image\n * provider factories pass these around as values.\n */\nexport interface ProviderImages {\n\tgenerateImages(\n\t\tmodel: ImagesModel<ImagesApi>,\n\t\tcontext: ImagesContext,\n\t\toptions?: ImagesOptions,\n\t): Promise<AssistantImages>;\n}\n\nexport interface ImagesOptions extends ProviderRequestOptions<ImagesModel<ImagesApi>> {\n\t/**\n\t * Optional metadata to include in API requests.\n\t * Providers extract the fields they understand and ignore the rest.\n\t */\n\tmetadata?: Record<string, unknown>;\n}\n\nexport type ProviderImagesOptions = ImagesOptions & Record<string, unknown>;\n\nexport interface AnthropicAllowedFallbackModel {\n\tprovider: ProviderId;\n\tmodel: string;\n\tcost: ModelCost;\n}\n\nexport type AnthropicRefusalFallback = \"default\" | readonly { model: string }[];\n\n// Unified options with reasoning passed to streamSimple() and completeSimple()\nexport interface SimpleStreamOptions extends StreamOptions {\n\t/** Provider-neutral tool selection for simple requests. Default: \"auto\". */\n\ttoolChoice?: ToolChoice;\n\treasoning?: ThinkingLevel;\n\t/**\n\t * Provenance-bearing thinking selection. Providers that need to distinguish\n\t * an explicit user choice from the always-materialized effective level read\n\t * this; `reasoning` remains the normalized effective level for everyone.\n\t */\n\tthinkingSelection?: ThinkingSelection;\n\t/** Anthropic server-side fallback for eligible refusal stop reasons. Anthropic providers only. */\n\trefusalFallbacks?: AnthropicRefusalFallback;\n\t/** Ask a capable provider to return a durable handle and continue the request asynchronously. */\n\tdeferred?: boolean | { window?: \"15m\" | \"1h\" | \"24h\" };\n\t/** Custom token budgets for thinking levels (token-based providers only) */\n\tthinkingBudgets?: ThinkingBudgets;\n}\n\n// Generic StreamFunction with typed options.\n//\n// Contract:\n// - Must return an AssistantMessageEventStream.\n// - Once invoked, request/model/runtime failures should be encoded in the\n// returned stream, not thrown.\n// - Error termination must produce an AssistantMessage with stopReason\n// \"error\" or \"aborted\" and errorMessage, emitted via the stream protocol.\nexport type StreamFunction<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> = (\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: TOptions,\n) => AssistantMessageEventStream;\n\nexport type ImagesFunction<TApi extends ImagesApi = ImagesApi, TOptions extends ImagesOptions = ImagesOptions> = (\n\tmodel: ImagesModel<TApi>,\n\tcontext: ImagesContext,\n\toptions?: TOptions,\n) => Promise<AssistantImages>;\n\nexport interface TextSignatureV1 {\n\tv: 1;\n\tid: string;\n\tphase?: \"commentary\" | \"final_answer\";\n}\n\nexport interface TextContent {\n\ttype: \"text\";\n\ttext: string;\n\ttextSignature?: string; // e.g., for OpenAI responses, message metadata (legacy id string or TextSignatureV1 JSON)\n}\n\nexport interface ThinkingContent {\n\ttype: \"thinking\";\n\tthinking: string;\n\t/** Epoch ms, stamped by the agent loop at stream-event receipt, best-effort. */\n\tstartedAt?: number;\n\t/** Epoch ms, stamped by the agent loop at stream-event receipt, best-effort. */\n\tendedAt?: number;\n\tthinkingSignature?: string; // e.g., for OpenAI responses, the reasoning item ID\n\t/** When true, the thinking content was redacted by safety filters. The opaque\n\t * encrypted payload is stored in `thinkingSignature` so it can be passed back\n\t * to the API for multi-turn continuity. */\n\tredacted?: boolean;\n}\n\nexport interface ImageContent {\n\ttype: \"image\";\n\tdata: string; // base64 encoded image data\n\tmimeType: string; // e.g., \"image/jpeg\", \"image/png\". Video payloads (e.g. \"video/mp4\") ride this\n\t// same block for models that declare the \"video\" input modality; use isVideoMimeType() to branch.\n}\n\n/** True when an ImageContent block actually carries video data (e.g. \"video/mp4\"). */\nexport function isVideoMimeType(mimeType: string): boolean {\n\treturn mimeType.toLowerCase().startsWith(\"video/\");\n}\n\nexport interface ToolCall {\n\ttype: \"toolCall\";\n\tid: string;\n\tname: string;\n\targuments: Record<string, any>;\n\t/** Set by text tool-call middleware when a truncated call could not be recovered. Carriers of `incomplete` MUST NOT be executed. */\n\tincomplete?: true;\n\t/** Error explaining why an incomplete tool call could not be recovered. */\n\terrorMessage?: string;\n\tthoughtSignature?: string; // Google-specific: opaque signature for reusing thought context\n\t/** OpenAI Responses namespace for calls to dynamically loaded or namespaced tools. */\n\tnamespace?: string;\n}\n\n/**\n * Provider-emitted content block whose semantics are owned by the originating\n * provider. Surfaces server-side tool invocations (web_search), server-side\n * tool results (web_search_tool_result), code execution traces, grounding\n * metadata fragments, and any other vendor-specific block the core does not\n * normalize.\n *\n * `subtype` mirrors the provider's wire `type` discriminator (e.g.\n * \"server_tool_use\", \"web_search_tool_result\", \"executableCode\"). `raw` is\n * the verbatim wire payload — extensions interpret it per provider+subtype.\n *\n * The owning provider id lives on the parent `AssistantMessage.provider`, not\n * here, to avoid drift on replay.\n *\n * On replay across providers, `convertMessages` implementations MUST drop\n * these blocks (they are not portable). This mirrors the existing\n * `redacted_thinking` skip pattern.\n */\nexport interface ProviderNativeContent {\n\ttype: \"providerNative\";\n\tsubtype: string;\n\traw: unknown;\n}\n\nexport interface Usage {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\t/** Subset of `cacheWrite` written with 1h retention. Only Anthropic reports this split. */\n\tcacheWrite1h?: number;\n\t/**\n\t * Reasoning/thinking tokens, when the provider reports them. This is a subset of\n\t * `output`: `output` already includes these tokens. Set to a number (possibly 0) by\n\t * providers that expose a reasoning breakdown; left undefined by providers that don't.\n\t */\n\treasoning?: number;\n\ttotalTokens: number;\n\tcost: {\n\t\tinput: number;\n\t\toutput: number;\n\t\tcacheRead: number;\n\t\tcacheWrite: number;\n\t\ttotal: number;\n\t};\n}\n\nexport type StopReason = \"pending\" | \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\" | \"deferred\";\n\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\n\nexport interface DeferredHandle {\n\tprovider: string;\n\tmodelId: string;\n\tapi: string;\n\t/** Provider token, such as a response id or batch id plus row id. */\n\tid: string;\n\texpiresAt?: number;\n\tpollAfterMs?: number;\n\t/** Provider conversion data required to reconstruct the final assistant message. */\n\tdata?: JsonValue;\n}\n\nexport type AssistantStopDetails = { type: \"refusal\"; explanation?: string } | { type: \"sensitive\" };\n\nexport interface UserMessage {\n\trole: \"user\";\n\tcontent: string | (TextContent | ImageContent)[];\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport interface AssistantMessage {\n\trole: \"assistant\";\n\tcontent: (TextContent | ThinkingContent | ToolCall | ProviderNativeContent)[];\n\tapi: Api;\n\tprovider: ProviderId;\n\tmodel: string;\n\tresponseModel?: string; // Concrete `chunk.model` when different from the requested `model` (e.g. OpenRouter `auto` -> `anthropic/...`)\n\tresponseId?: string; // Provider-specific response/message identifier when the upstream API exposes one\n\tdiagnostics?: AssistantMessageDiagnostic[]; // Redacted provider/runtime diagnostics for failures and recoveries.\n\tusage: Usage;\n\tstopReason: StopReason;\n\tstopDetails?: AssistantStopDetails;\n\tdeferred?: DeferredHandle;\n\terrorMessage?: string;\n\t/** Explicit owner for an abort initiated by the provider retry watchdog. */\n\tabortSource?: \"provider\";\n\trawStopReason?: string;\n\t/**\n\t * Provider indication of whether the model explicitly ended its turn.\n\t * Preserved for debugging and does not currently affect agent control flow.\n\t */\n\tendTurn?: boolean;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport interface ToolResultMessage<TDetails = any> {\n\trole: \"toolResult\";\n\ttoolCallId: string;\n\ttoolName: string;\n\tcontent: (TextContent | ImageContent)[]; // Supports text and images\n\tdetails?: TDetails;\n\t/** Usage from the tool execution itself, if available. Not part of main LLM context accounting. */\n\tusage?: Usage;\n\t/**\n\t * Names from `Context.tools` that became available after this result.\n\t * Providers with native deferred tool loading use this as the load point;\n\t * other providers ignore it and use `Context.tools` normally.\n\t */\n\taddedToolNames?: string[];\n\tisError: boolean;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport type Message = UserMessage | AssistantMessage | ToolResultMessage;\n\nexport type ImagesInputContent = TextContent | ImageContent;\nexport type ImagesOutputContent = TextContent | ImageContent;\n\nexport interface ImagesContext {\n\tinput: ImagesInputContent[];\n}\n\nexport type ImagesStopReason = \"stop\" | \"error\" | \"aborted\";\n\nexport interface AssistantImages {\n\tapi: ImagesApi;\n\tprovider: ImagesProviderId;\n\tmodel: string;\n\toutput: ImagesOutputContent[];\n\tresponseId?: string;\n\tusage?: Usage;\n\tstopReason: ImagesStopReason;\n\terrorMessage?: string;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nimport type { TSchema } from \"typebox\";\n\nexport interface FreeformToolFormat {\n\ttype: \"grammar\";\n\tsyntax: \"lark\";\n\tdefinition: string;\n}\n\n/** OpenAI grammar variants for constrained sampling. */\nexport type GrammarFormat = \"openai_lark\" | \"openai_regex\";\n\nexport type GrammarVariants = Partial<Record<GrammarFormat, string>>;\n\n/**\n * Optional provider-side constrained sampling configs for a tool.\n *\n * The `json_schema` value roughly maps to the concept of `strict` in APIs which is\n * implemented as json-schema constrained sampling by APIs. Grammar variants let\n * callers provide provider-specific encodings of the same intended language.\n */\nexport type ConstrainedSamplingConfig =\n\t| {\n\t\t\ttype: \"json_schema\";\n\t\t\tstrict: \"prefer\" | \"require\";\n\t }\n\t| {\n\t\t\ttype: \"grammar\";\n\t\t\tvariants: GrammarVariants;\n\t };\nexport interface Tool<TParameters extends TSchema = TSchema> {\n\tname: string;\n\tdescription: string;\n\tparameters: TParameters;\n\tfreeform?: FreeformToolFormat;\n\tconstrainedSampling?: false | ConstrainedSamplingConfig;\n}\n\nexport interface Context {\n\tsystemPrompt?: string;\n\tmessages: Message[];\n\ttools?: Tool[];\n}\n\n/**\n * Event protocol for AssistantMessageEventStream.\n *\n * Streams should emit `start` before partial updates, then terminate with either:\n * - `done` carrying the final successful AssistantMessage, or\n * - `error` carrying the final AssistantMessage with stopReason \"error\" or \"aborted\"\n * and errorMessage.\n */\nexport type AssistantMessageEvent =\n\t| { type: \"start\"; partial: AssistantMessage }\n\t| { type: \"text_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| { type: \"text_end\"; contentIndex: number; content: string; partial: AssistantMessage }\n\t| { type: \"thinking_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| { type: \"thinking_end\"; contentIndex: number; content: string; partial: AssistantMessage }\n\t| { type: \"toolcall_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t/** Finalized - executable iff `incomplete !== true` on `toolCall`. */\n\t| { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall; partial: AssistantMessage }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<StopReason, \"stop\" | \"length\" | \"toolUse\" | \"deferred\">;\n\t\t\tmessage: AssistantMessage;\n\t }\n\t| { type: \"error\"; reason: Extract<StopReason, \"aborted\" | \"error\">; error: AssistantMessage };\n\n/**\n * Compatibility settings for OpenAI-compatible completions APIs.\n * Use this to override URL-based auto-detection for custom providers.\n */\nexport interface OpenAICompletionsCompat {\n\t/** Whether the provider supports the `store` field. Default: auto-detected from URL. */\n\tsupportsStore?: boolean;\n\t/** Whether the provider supports the `developer` role (vs `system`). Default: auto-detected from URL. */\n\tsupportsDeveloperRole?: boolean;\n\t/** Whether the provider supports `reasoning_effort`. Default: auto-detected from URL. */\n\tsupportsReasoningEffort?: boolean;\n\t/** Whether the provider supports `stream_options: { include_usage: true }` for token usage in streaming responses. Default: true. */\n\tsupportsUsageInStreaming?: boolean;\n\t/** Whether streamed responses include `finish_reason`. When false, pi infers `stop` or `toolUse` when the stream ends. Default: true. */\n\tsupportsFinishReason?: boolean;\n\t/** Which field to use for max tokens. Default: auto-detected from URL. */\n\tmaxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n\t/** Whether tool results require the `name` field. Default: auto-detected from URL. */\n\trequiresToolResultName?: boolean;\n\t/** Whether a user message after tool results requires an assistant message in between. Default: auto-detected from URL. */\n\trequiresAssistantAfterToolResult?: boolean;\n\t/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */\n\trequiresThinkingAsText?: boolean;\n\t/** Whether all replayed assistant messages must include an empty reasoning_content field when reasoning is enabled. Default: auto-detected from URL. */\n\trequiresReasoningContentOnAssistantMessages?: boolean;\n\t/** Format for reasoning/thinking parameter. \"openai\" uses reasoning_effort, \"openrouter\" uses reasoning: { effort }, \"deepseek\" uses thinking: { type } plus reasoning_effort when supported, \"together\" uses reasoning: { enabled } plus reasoning_effort when supported, \"baseten\" uses configurable chat_template_args plus reasoning_effort when supported, \"zai\" uses thinking: { type }, \"qwen\" uses top-level enable_thinking: boolean, \"qwen-chat-template\" uses chat_template_kwargs.enable_thinking and preserve_thinking, \"chat-template\" uses configurable chat_template_kwargs, \"string-thinking\" uses top-level thinking: string, and \"ant-ling\" uses reasoning: { effort } only when the mapped effort is non-null. Default: \"openai\". */\n\tthinkingFormat?:\n\t\t| \"openai\"\n\t\t| \"openrouter\"\n\t\t| \"deepseek\"\n\t\t| \"together\"\n\t\t| \"baseten\"\n\t\t| \"zai\"\n\t\t| \"qwen\"\n\t\t| \"chat-template\"\n\t\t| \"qwen-chat-template\"\n\t\t| \"string-thinking\"\n\t\t| \"ant-ling\";\n\t/** Whether the provider accepts explicit disabled-thinking markers when thinking is off. Default: true. */\n\tsupportsDisabledThinking?: boolean;\n\t/** Kwargs to send as `chat_template_kwargs` when `thinkingFormat` is `chat-template`. Use `{ \"$var\": \"thinking.enabled\" }`, `{ \"$var\": \"thinking.effort\" }`, or `{ \"$var\": \"thinking.budget\" }` for pi-controlled thinking values. */\n\tchatTemplateKwargs?: Record<string, ChatTemplateKwargValue>;\n\t/** Arguments to send as `chat_template_args` when `thinkingFormat` is `baseten`. Use `{ \"$var\": \"thinking.enabled\" }`, `{ \"$var\": \"thinking.effort\" }`, or `{ \"$var\": \"thinking.budget\" }` for pi-controlled thinking values. */\n\tchatTemplateArgs?: Record<string, ChatTemplateKwargValue>;\n\t/** OpenRouter-compatible routing preferences sent as the `provider` request field. */\n\topenRouterRouting?: OpenRouterRouting;\n\t/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */\n\tvercelGatewayRouting?: VercelGatewayRouting;\n\t/** Whether z.ai supports top-level `tool_stream: true` for streaming tool call deltas. Default: false. */\n\tzaiToolStream?: boolean;\n\t/**\n\t * Top-level request field used to cap reasoning tokens from `thinkingBudgets`.\n\t * Reasoning and the answer share `max_tokens` on these endpoints, so without a budget a\n\t * reasoning-heavy turn can consume the whole response and emit no answer.\n\t * `\"thinking_token_budget\"` is vLLM, `\"thinking_budget\"` is Qwen/DashScope/SGLang,\n\t * `\"thinking_budget_tokens\"` is llama.cpp. Off by default; not set on the generated catalog.\n\t */\n\tthinkingTokenBudgetField?: ThinkingTokenBudgetField;\n\t/** Alias for `thinkingTokenBudgetField: \"thinking_token_budget\"` (vLLM). Prefer `thinkingTokenBudgetField`. Default: false. */\n\tsupportsThinkingTokenBudget?: boolean;\n\t/** Whether the provider supports OpenAI custom tools with Lark/regex grammar formats. When false, grammar-constrained tools fall back to normal function tools. Default: false; the generated model catalog enables it for capable models. */\n\tsupportsOpenAIGrammarTools?: boolean;\n\t/** Whether the provider supports the `strict` field in tool definitions. Default: true. */\n\tsupportsStrictMode?: boolean;\n\t/**\n\t * Provider-specific JSON Schema flavor for tool parameters. `\"moonshot-mfjs\"`\n\t * normalizes schemas for Moonshot / Kimi backends that enforce a stricter subset.\n\t */\n\ttoolSchemaFlavor?: \"moonshot-mfjs\";\n\t/**\n\t * Tool call format for models that don't natively support tool calling.\n\t * When set, the middleware will intercept tool calls and format them as text.\n\t * Supported values: \"hermes\", \"morph-xml\", \"xml\" (deprecated alias for \"morph-xml\"), \"yaml-xml\", \"gemma4-delimiter\", \"anthropic-xml\", \"antml\", \"kimi-xtml\"\n\t */\n\ttoolCallFormat?: string;\n\t/** Cache control convention for prompt caching. \"anthropic\" applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user, assistant, or tool-result text content. */\n\tcacheControlFormat?: \"anthropic\";\n\t/** Whether to send session-affinity data from `options.sessionId`. Default: false. */\n\tsendSessionAffinityHeaders?: boolean;\n\t/** Provider-specific deferred tool serialization mode. */\n\tdeferredToolsMode?: \"kimi\";\n\t/** Session-affinity header format: `openai` sends `session_id`, `x-client-request-id`, and `x-session-affinity`; `openai-nosession` sends `x-client-request-id` and `x-session-affinity`; `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param, which is governed by cache retention. Default: auto-detected. */\n\tsessionAffinityFormat?: SessionAffinityFormat;\n\t/** Whether the provider accepts the `prompt_cache_key` request field. Default: auto-detected. */\n\tsupportsPromptCacheKey?: boolean;\n\t/** Whether the provider supports long prompt cache retention (`prompt_cache_retention: \"24h\"` or Anthropic-style `cache_control.ttl: \"1h\"`, depending on format). Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n}\n\n/** Compatibility settings for Anthropic Messages-compatible APIs. */\nexport interface AnthropicMessagesCompat {\n\t/**\n\t * Whether the provider accepts per-tool `eager_input_streaming`.\n\t * When false, the Anthropic provider omits `tools[].eager_input_streaming`\n\t * and sends the legacy `fine-grained-tool-streaming-2025-05-14` beta header\n\t * for tool-enabled requests.\n\t * Default: true.\n\t */\n\tsupportsEagerToolInputStreaming?: boolean;\n\t/** Whether the provider supports Anthropic long cache retention (`cache_control.ttl: \"1h\"`). Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n\t/**\n\t * Whether to send the `x-session-affinity` header from `options.sessionId`\n\t * when caching is enabled. Required for providers like Fireworks that use\n\t * session affinity for prompt cache routing (requests to the same replica\n\t * maximize cache hits).\n\t * Default: false.\n\t */\n\tsendSessionAffinityHeaders?: boolean;\n\t/**\n\t * Whether the provider supports Anthropic-style `cache_control` markers on\n\t * tool definitions. When false, `cache_control` is omitted from tool params.\n\t * Some Anthropic-compatible providers (e.g., Fireworks) do not support this\n\t * field on tools and may reject or ignore it.\n\t * Default: true.\n\t */\n\tsupportsCacheControlOnTools?: boolean;\n\t/**\n\t * Whether the provider accepts `thinking: { type: \"disabled\" }` when\n\t * extended thinking is off. Some Anthropic-compatible providers support\n\t * thinking but reject Anthropic's explicit disabled marker.\n\t * Default: true.\n\t */\n\tsupportsDisabledThinking?: boolean;\n\t/**\n\t * Whether the model accepts the Anthropic `temperature` request field.\n\t * Claude Opus 4.7+ rejects non-default temperature values.\n\t * Default: true.\n\t */\n\tsupportsTemperature?: boolean;\n\t/** Whether the model accepts Anthropic `tool_choice`. Default: true. */\n\tsupportsToolChoice?: boolean;\n\t/**\n\t * Whether the model accepts forced Anthropic tool choices (`any` or a named\n\t * tool). Default: true, except Claude Fable/Mythos models.\n\t */\n\tsupportsForcedToolChoice?: boolean;\n\t/**\n\t * Whether to force adaptive thinking (`thinking.type: \"adaptive\"` plus\n\t * `output_config.effort`) regardless of the model id. Built-in models that\n\t * require adaptive thinking set this in generated metadata. Custom\n\t * Anthropic-compatible providers can set this to `true` for any model whose\n\t * upstream requires the adaptive format. Set to `false` to opt out on\n\t * overridden built-in models and disable model id/name inference.\n\t * Default: infer from adaptive Claude model ids/names when possible.\n\t */\n\tforceAdaptiveThinking?: boolean;\n\t/** Whether to replay empty thinking signatures as `signature: \"\"` instead of converting thinking to text. Default: false. */\n\tallowEmptySignature?: boolean;\n\t/** Whether the provider supports Anthropic strict tool schemas. Default: false; generated Anthropic models enable it explicitly. */\n\tsupportsStrictTools?: boolean;\n\t/**\n\t * How to replay thinking blocks that have no usable Anthropic signature.\n\t * `\"text\"` demotes them to text; `\"empty-signature\"` preserves Anthropic's\n\t * thinking shape with `signature: \"\"`. Defaults to `\"text\"`; the legacy\n\t * `allowEmptySignature` setting remains a compatibility alias for\n\t * `\"empty-signature\"`.\n\t */\n\tunsignedThinkingReplay?: \"text\" | \"empty-signature\";\n\t/**\n\t * Model ids Anthropic accepts in `fallbacks` for server-side refusal fallback.\n\t * When absent or empty, callers must omit `fallbacks`; Anthropic rejects the\n\t * field for models with no permitted fallback targets.\n\t */\n\tallowedFallbackModels?: Array<AnthropicAllowedFallbackModel | string>;\n\t/**\n\t * Whether the provider supports deferred tools loaded by `tool_reference`\n\t * blocks in tool results. Default: true for first-party Anthropic models\n\t * except Haiku and models older than Claude 4.5; false for other providers.\n\t */\n\tsupportsToolReferences?: boolean;\n\t/**\n\t * Whether the provider executes Anthropic server-side `web_search_*` native\n\t * tools and accepts their `server_tool_use` / `web_search_tool_result`\n\t * blocks on replay. Anthropic-compatible endpoints (e.g., kimi-coding) may\n\t * run the search but reject the replayed server-tool blocks on the next\n\t * request. When false, hook-injected `web_search_*` tools are stripped from\n\t * the payload. Default: true only for the first-party Anthropic endpoint.\n\t */\n\tsupportsWebSearch?: boolean;\n}\n\n/** Compatibility settings for Amazon Bedrock models. */\nexport interface BedrockCompat {\n\t/** Whether the model supports Bedrock strict tool schemas. Default: false. */\n\tsupportsStrictMode?: boolean;\n}\n\n/**\n * OpenRouter provider routing preferences.\n * Controls which upstream providers OpenRouter routes requests to.\n * Sent as the `provider` field in the OpenRouter API request body.\n * @see https://openrouter.ai/docs/guides/routing/provider-selection\n */\nexport interface OpenRouterRouting {\n\t/** Whether to allow backup providers to serve requests. Default: true. */\n\tallow_fallbacks?: boolean;\n\t/** Whether to filter providers to only those that support all parameters in the request. Default: false. */\n\trequire_parameters?: boolean;\n\t/** Data collection setting. \"allow\" (default): allow providers that may store/train on data. \"deny\": only use providers that don't collect user data. */\n\tdata_collection?: \"deny\" | \"allow\";\n\t/** Whether to restrict routing to only ZDR (Zero Data Retention) endpoints. */\n\tzdr?: boolean;\n\t/** Whether to restrict routing to only models that allow text distillation. */\n\tenforce_distillable_text?: boolean;\n\t/** An ordered list of provider names/slugs to try in sequence, falling back to the next if unavailable. */\n\torder?: string[];\n\t/** List of provider names/slugs to exclusively allow for this request. */\n\tonly?: string[];\n\t/** List of provider names/slugs to skip for this request. */\n\tignore?: string[];\n\t/** A list of quantization levels to filter providers by (e.g., [\"fp16\", \"bf16\", \"fp8\", \"fp6\", \"int8\", \"int4\", \"fp4\", \"fp32\"]). */\n\tquantizations?: string[];\n\t/** Sorting strategy. Can be a string (e.g., \"price\", \"throughput\", \"latency\") or an object with `by` and `partition`. */\n\tsort?:\n\t\t| string\n\t\t| {\n\t\t\t\t/** The sorting metric: \"price\", \"throughput\", \"latency\". */\n\t\t\t\tby?: string;\n\t\t\t\t/** Partitioning strategy: \"model\" (default) or \"none\". */\n\t\t\t\tpartition?: string | null;\n\t\t };\n\t/** Maximum price per million tokens (USD). */\n\tmax_price?: {\n\t\t/** Price per million prompt tokens. */\n\t\tprompt?: number | string;\n\t\t/** Price per million completion tokens. */\n\t\tcompletion?: number | string;\n\t\t/** Price per image. */\n\t\timage?: number | string;\n\t\t/** Price per audio unit. */\n\t\taudio?: number | string;\n\t\t/** Price per request. */\n\t\trequest?: number | string;\n\t};\n\t/** Preferred minimum throughput (tokens/second). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */\n\tpreferred_min_throughput?:\n\t\t| number\n\t\t| {\n\t\t\t\t/** Minimum tokens/second at the 50th percentile. */\n\t\t\t\tp50?: number;\n\t\t\t\t/** Minimum tokens/second at the 75th percentile. */\n\t\t\t\tp75?: number;\n\t\t\t\t/** Minimum tokens/second at the 90th percentile. */\n\t\t\t\tp90?: number;\n\t\t\t\t/** Minimum tokens/second at the 99th percentile. */\n\t\t\t\tp99?: number;\n\t\t };\n\t/** Preferred maximum latency (seconds). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */\n\tpreferred_max_latency?:\n\t\t| number\n\t\t| {\n\t\t\t\t/** Maximum latency in seconds at the 50th percentile. */\n\t\t\t\tp50?: number;\n\t\t\t\t/** Maximum latency in seconds at the 75th percentile. */\n\t\t\t\tp75?: number;\n\t\t\t\t/** Maximum latency in seconds at the 90th percentile. */\n\t\t\t\tp90?: number;\n\t\t\t\t/** Maximum latency in seconds at the 99th percentile. */\n\t\t\t\tp99?: number;\n\t\t };\n}\n\n/**\n * Vercel AI Gateway routing preferences.\n * Controls which upstream providers the gateway routes requests to.\n * @see https://vercel.com/docs/ai-gateway/models-and-providers/provider-options\n */\nexport interface VercelGatewayRouting {\n\t/** List of provider slugs to exclusively use for this request (e.g., [\"bedrock\", \"anthropic\"]). */\n\tonly?: string[];\n\t/** List of provider slugs to try in order (e.g., [\"anthropic\", \"openai\"]). */\n\torder?: string[];\n}\n\nexport interface ModelCostRates {\n\tinput: number; // $/million tokens\n\toutput: number; // $/million tokens\n\tcacheRead: number; // $/million tokens\n\tcacheWrite: number; // $/million tokens\n}\n\nexport interface ModelCostTier extends ModelCostRates {\n\t/** Use this tier for requests whose total input usage exceeds this token count. */\n\tinputTokensAbove: number;\n}\n\nexport interface ModelCost extends ModelCostRates {\n\t/** Request-wide pricing tiers. The highest matching input threshold applies to the full request. */\n\ttiers?: ModelCostTier[];\n}\n\nexport interface ImagesModel<TApi extends ImagesApi>\n\textends Omit<Model<Api>, \"api\" | \"provider\" | \"reasoning\" | \"contextWindow\" | \"maxTokens\" | \"compat\"> {\n\tapi: TApi;\n\tprovider: ImagesProviderId;\n\toutput: (\"text\" | \"image\")[];\n}\n"]}
@@ -76,6 +76,22 @@ export declare function isCursorPayloadResourceExhausted(message: {
76
76
  totalTokens?: number;
77
77
  };
78
78
  }, _estimateTokens: number): boolean;
79
+ /**
80
+ * Detects Cursor's verified usage-pool exhaustion signature: a token-bearing
81
+ * `resource_exhausted` error while the conversation is well below the model
82
+ * context window.
83
+ */
84
+ export declare function isCursorQuotaResourceExhausted(message: {
85
+ stopReason?: string;
86
+ errorMessage?: string;
87
+ usage?: {
88
+ input?: number;
89
+ output?: number;
90
+ cacheRead?: number;
91
+ cacheWrite?: number;
92
+ totalTokens?: number;
93
+ };
94
+ }, contextWindow: number): boolean;
79
95
  export declare function isCursorZeroTokenResourceExhausted(message: {
80
96
  stopReason?: string;
81
97
  errorMessage?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"overflow.d.ts","sourceRoot":"","sources":["../../src/utils/overflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA4FpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAmC5F;AACD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAEhG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAYD,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3G,EACD,eAAe,EAAE,MAAM,GACrB,OAAO,CAKT;AAED,wBAAgB,kCAAkC,CAAC,OAAO,EAAE;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3G,GAAG,OAAO,CAKV;AAED,wBAAgB,yCAAyC,CAAC,OAAO,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GAAG,OAAO,CAErH;AAED,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAGnG;AAED,wBAAgB,gCAAgC,CAAC,CAAC,SAAS;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE,EACrH,QAAQ,EAAE,CAAC,EACX,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,GACxB,CAAC,CAIH"}
1
+ {"version":3,"file":"overflow.d.ts","sourceRoot":"","sources":["../../src/utils/overflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA4FpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAwC5F;AACD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAEhG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAYD,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3G,EACD,eAAe,EAAE,MAAM,GACrB,OAAO,CAKT;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3G,EACD,aAAa,EAAE,MAAM,GACnB,OAAO,CAST;AAED,wBAAgB,kCAAkC,CAAC,OAAO,EAAE;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3G,GAAG,OAAO,CAKV;AAED,wBAAgB,yCAAyC,CAAC,OAAO,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GAAG,OAAO,CAErH;AAED,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAGnG;AAED,wBAAgB,gCAAgC,CAAC,CAAC,SAAS;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE,EACrH,QAAQ,EAAE,CAAC,EACX,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,GACxB,CAAC,CAIH"}
@@ -149,7 +149,10 @@ export function isContextOverflow(message, contextWindow) {
149
149
  }
150
150
  const usage = message.usage;
151
151
  const hasTokenEvidence = (usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite) > 0;
152
- if (!isNonOverflow && hasTokenEvidence && RESOURCE_EXHAUSTED_PATTERN.test(message.errorMessage)) {
152
+ if (!isNonOverflow &&
153
+ hasTokenEvidence &&
154
+ RESOURCE_EXHAUSTED_PATTERN.test(message.errorMessage) &&
155
+ (contextWindow === undefined || contextWindow <= 0 || cursorZeroTokenCount(message) >= contextWindow * 0.5)) {
153
156
  return true;
154
157
  }
155
158
  }
@@ -198,6 +201,19 @@ export function isCursorPayloadResourceExhausted(message, _estimateTokens) {
198
201
  }
199
202
  return !(cursorZeroTokenCount(message) > 0);
200
203
  }
204
+ /**
205
+ * Detects Cursor's verified usage-pool exhaustion signature: a token-bearing
206
+ * `resource_exhausted` error while the conversation is well below the model
207
+ * context window.
208
+ */
209
+ export function isCursorQuotaResourceExhausted(message, contextWindow) {
210
+ const tokens = cursorZeroTokenCount(message);
211
+ return (message.stopReason === "error" &&
212
+ RESOURCE_EXHAUSTED_PATTERN.test(message.errorMessage || "") &&
213
+ contextWindow > 0 &&
214
+ tokens > 0 &&
215
+ tokens < contextWindow * 0.5);
216
+ }
201
217
  export function isCursorZeroTokenResourceExhausted(message) {
202
218
  if (message.stopReason !== "error" || !/resource.?exhausted/i.test(message.errorMessage || "")) {
203
219
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"overflow.js","sourceRoot":"","sources":["../../src/utils/overflow.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"../types.ts\";\n\n/**\n * Regex patterns to detect context overflow errors from different providers.\n *\n * These patterns match error messages returned when the input exceeds\n * the model's context window.\n *\n * Provider-specific patterns (with example error messages):\n *\n * - Anthropic: \"prompt is too long: 213462 tokens > 200000 maximum\"\n * - Anthropic: \"413 {\\\"error\\\":{\\\"type\\\":\\\"request_too_large\\\",\\\"message\\\":\\\"Request exceeds the maximum size\\\"}}\"\n * - OpenAI: \"Your input exceeds the context window of this model\"\n * - OpenAI/LiteLLM: \"Requested token count exceeds the model's maximum context length of 131072 tokens\"\n * - OpenAI-compatible: \"Input length (265330) exceeds model's maximum context length (262144).\"\n * - Google: \"The input token count (1196265) exceeds the maximum number of tokens allowed (1048575)\"\n * - xAI: \"This model's maximum prompt length is 131072 but the request contains 537812 tokens\"\n * - Groq: \"Please reduce the length of the messages or completion\"\n * - OpenRouter: \"This endpoint's maximum context length is X tokens. However, you requested about Y tokens\"\n * - OpenRouter/Poolside: \"Input length X exceeds the maximum allowed input length of Y tokens.\"\n * - Together AI: \"The input (X tokens) is longer than the model's context length (Y tokens).\"\n * - llama.cpp: \"the request exceeds the available context size, try increasing it\"\n * - LM Studio: \"tokens to keep from the initial prompt is greater than the context length\"\n * - GitHub Copilot: \"prompt token count of X exceeds the limit of Y\"\n * - MiniMax: \"invalid params, context window exceeds limit\"\n * - Kimi For Coding: \"Your request exceeded model token limit: X (requested: Y)\"\n * - DS4: \"Prompt has X tokens, but the configured context size is Y tokens\"\n * - Cerebras: \"400/413 status code (no body)\"\n * - Gateways: \"413 Request body too large\" / \"Request Entity Too Large\" / \"Payload Too Large\" (byte-size overflow)\n * - Mistral: \"Prompt contains X tokens ... too large for model with Y maximum context length\"\n * - z.ai: Does NOT error, accepts overflow silently - handled via usage.input > contextWindow\n * - Xiaomi MiMo: Truncates input to fill contextWindow exactly, then returns finish_reason \"length\"\n * with output=0 (no room left to generate). Detected via stopReason \"length\" + zero output +\n * input filling the context window.\n * - DashScope/Qwen: \"Range of input length should be [1, X]\" (HTTP 400 invalid_parameter_error)\n * - Ollama: Some deployments truncate silently, others return errors like \"prompt too long; exceeded max context length by X tokens\"\n */\nconst OVERFLOW_PATTERNS = [\n\t/prompt is too long/i, // Anthropic token overflow\n\t/request_too_large/i, // Anthropic request byte-size overflow (HTTP 413)\n\t/input is too long for requested model/i, // Amazon Bedrock\n\t/exceeds the context window/i, // OpenAI (Completions & Responses API)\n\t/exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\\d,]+ tokens?|\\s*\\([\\d,]+\\))/i, // OpenAI-compatible proxies (LiteLLM)\n\t/input token count.*exceeds the maximum/i, // Google (Gemini)\n\t/maximum prompt length is \\d+/i, // xAI (Grok)\n\t/reduce the length of the messages/i, // Groq\n\t/maximum context length is \\d+ tokens/i, // OpenRouter (most backends)\n\t/exceeds (?:the )?maximum allowed input length of [\\d,]+ tokens?/i, // OpenRouter/Poolside\n\t/input \\(\\d+ tokens\\) is longer than the model'?s context length \\(\\d+ tokens\\)/i, // Together AI\n\t/exceeds the limit of \\d+/i, // GitHub Copilot\n\t/exceeds the available context size/i, // llama.cpp server\n\t/greater than the context length/i, // LM Studio\n\t/context window exceeds limit/i, // MiniMax\n\t/exceeded model token limit/i, // Kimi For Coding\n\t/too large for model with \\d+ maximum context length/i, // Mistral\n\t/prompt has [\\d,]+ tokens?, but the configured context size is [\\d,]+ tokens?/i, // DS4 server\n\t/model_context_window_exceeded/i, // z.ai non-standard finish_reason surfaced as error text\n\t/prompt too long; exceeded (?:max )?context length/i, // Ollama explicit overflow error\n\t/range of input length should be/i, // DashScope / Qwen Token Plan\n\t/context[_ ]length[_ ]exceeded/i, // Generic fallback\n\t/too many tokens/i, // Generic fallback\n\t/token limit exceeded/i, // Generic fallback\n\t/^4(?:00|13)\\s*(?:status code)?\\s*\\(no body\\)/i, // Cerebras: 400/413 with no body\n\t/(?:request[ _])?(?:body|entity|payload)[_ ]too[_ ]large/i, // Gateway HTTP 413 byte-size rejections (\"Request body too large\", \"Request Entity Too Large\", \"body_too_large\", \"Payload Too Large\"). Substring-anchored by design (JSON bodies lack an adjacent status code); a non-context size rejection (e.g. an oversized image) can over-match, which costs one bounded shrink-retry, never a wedge.\n];\n\n/**\n * Patterns that indicate non-overflow errors (e.g. rate limiting, server errors).\n * Error messages matching any of these are excluded from overflow detection\n * even if they also match an OVERFLOW_PATTERN.\n *\n * Example: Bedrock formats throttling errors as \"ThrottlingException: Too many tokens,\n * please wait before trying again.\" which would match the /too many tokens/i overflow\n * pattern without this exclusion.\n */\nconst NON_OVERFLOW_PATTERNS = [\n\t/^(Throttling error|Service unavailable):/i, // AWS Bedrock non-overflow errors (human-readable prefixes from formatBedrockError)\n\t/rate limit/i, // Generic rate limiting\n\t/too many requests/i, // Generic HTTP 429 style\n];\n\n/**\n * Cursor's api2.cursor.sh surfaces a context overflow as a bare gRPC\n * `resource_exhausted` end-stream — the same wording its backend uses for\n * quota and poisoned-conversation rejections. Token evidence disambiguates:\n * a request that already streamed or billed tokens overflowed mid-flight,\n * while a zero-token rejection is a quota/conversation failure that must stay\n * on the rate-limit path (the cursor client rotates the conversation id for\n * those and retry handling supplies the backoff).\n */\nconst RESOURCE_EXHAUSTED_PATTERN = /resource.?exhausted/i;\n\n/**\n * Check if an assistant message represents a context overflow error.\n *\n * This handles three cases:\n * 1. Error-based overflow: Most providers return stopReason \"error\" with a\n * specific error message pattern.\n * 2. Silent overflow: Some providers accept overflow requests and return\n * successfully. For these, we check if usage.input exceeds the context window.\n * 3. Length-stop overflow: Xiaomi MiMo can return \"length\" with zero output when\n * the input fills the context window.\n *\n * ## Reliability by Provider\n *\n * **Reliable detection (returns error with detectable message):**\n * - Anthropic: \"prompt is too long: X tokens > Y maximum\" or \"request_too_large\"\n * - OpenAI (Completions & Responses): \"exceeds the context window\", \"exceeds the model's maximum context length of X tokens\", or \"exceeds model's maximum context length (X)\"\n * - Google Gemini: \"input token count exceeds the maximum\"\n * - xAI (Grok): \"maximum prompt length is X but request contains Y\"\n * - Groq: \"reduce the length of the messages\"\n * - Cerebras: 400/413 status code (no body)\n * - Mistral: \"Prompt contains X tokens ... too large for model with Y maximum context length\"\n * - OpenRouter (most backends): \"maximum context length is X tokens\"\n * - OpenRouter/Poolside: \"Input length X exceeds the maximum allowed input length of Y tokens.\"\n * - Together AI: \"The input (X tokens) is longer than the model's context length (Y tokens).\"\n * - llama.cpp: \"exceeds the available context size\"\n * - LM Studio: \"greater than the context length\"\n * - Kimi For Coding: \"exceeded model token limit: X (requested: Y)\"\n * - DS4: \"Prompt has X tokens, but the configured context size is Y tokens\"\n * - DashScope/Qwen: \"Range of input length should be [1, X]\"\n *\n * **Unreliable detection:**\n * - z.ai: Sometimes accepts overflow silently (detectable via usage.input > contextWindow),\n * sometimes returns rate limit errors. Pass contextWindow param to detect silent overflow.\n * - Xiaomi MiMo: Truncates input to fit contextWindow then returns stopReason \"length\" with\n * output=0. Pass contextWindow param to detect via the \"filled context + zero output\" signal.\n * - Ollama: May truncate input silently for some setups, but may also return explicit\n * overflow errors that match the patterns above. Silent truncation still cannot be\n * detected here because we do not know the expected token count.\n *\n * ## Custom Providers\n *\n * If you've added custom models via settings.json, this function may not detect\n * overflow errors from those providers. To add support:\n *\n * 1. Send a request that exceeds the model's context window\n * 2. Check the errorMessage in the response\n * 3. Create a regex pattern that matches the error\n * 4. The pattern should be added to OVERFLOW_PATTERNS in this file, or\n * check the errorMessage yourself before calling this function\n *\n * @param message - The assistant message to check\n * @param contextWindow - Optional context window size for detecting silent overflow (z.ai)\n * @returns true if the message indicates a context overflow\n */\nexport function isContextOverflow(message: AssistantMessage, contextWindow?: number): boolean {\n\t// Case 1: Check error message patterns\n\tif (message.stopReason === \"error\" && message.errorMessage) {\n\t\t// Skip messages matching known non-overflow patterns (e.g. throttling / rate-limit)\n\t\tconst isNonOverflow = NON_OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage!));\n\t\tif (!isNonOverflow && OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage!))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst usage = message.usage;\n\t\tconst hasTokenEvidence =\n\t\t\t(usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite) > 0;\n\t\tif (!isNonOverflow && hasTokenEvidence && RESOURCE_EXHAUSTED_PATTERN.test(message.errorMessage)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Case 2: Silent overflow (z.ai style) - successful but usage exceeds context\n\tif (contextWindow && message.stopReason === \"stop\") {\n\t\tconst inputTokens = message.usage.input + message.usage.cacheRead;\n\t\tif (inputTokens > contextWindow) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Case 3: Length-stop overflow (Xiaomi MiMo style) - server truncates oversized input\n\t// to fit the context window, leaving no room for output. Returns stopReason \"length\"\n\t// with output=0 and input+cacheRead filling the context window.\n\tif (contextWindow && message.stopReason === \"length\" && message.usage.output === 0) {\n\t\tconst inputTokens = message.usage.input + message.usage.cacheRead;\n\t\tif (inputTokens >= contextWindow * 0.99) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n/**\n * Check whether a length stop ended below the caller or model's intended output limit.\n * Such responses may be caused by context pressure or provider-side truncation, so callers\n * can make one bounded compact-and-retry attempt. `desiredMaxOutput` must be the original\n * limit before any context-based clamping.\n */\nexport function isRecoverableLength(message: AssistantMessage, desiredMaxOutput: number): boolean {\n\treturn message.stopReason === \"length\" && desiredMaxOutput > 0 && message.usage.output < desiredMaxOutput;\n}\n\n/**\n * Get the overflow patterns for testing purposes.\n */\nexport function getOverflowPatterns(): RegExp[] {\n\treturn [...OVERFLOW_PATTERNS];\n}\n\nfunction cursorZeroTokenCount(message: {\n\tusage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; totalTokens?: number };\n}): number {\n\tconst usage = message.usage;\n\tif (!usage) return 0;\n\treturn (\n\t\tusage.totalTokens || (usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0)\n\t);\n}\n\nexport function isCursorPayloadResourceExhausted(\n\tmessage: {\n\t\tstopReason?: string;\n\t\terrorMessage?: string;\n\t\tusage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; totalTokens?: number };\n\t},\n\t_estimateTokens: number,\n): boolean {\n\tif (message.stopReason !== \"error\" || !/resource.?exhausted/i.test(message.errorMessage || \"\")) {\n\t\treturn false;\n\t}\n\treturn !(cursorZeroTokenCount(message) > 0);\n}\n\nexport function isCursorZeroTokenResourceExhausted(message: {\n\tstopReason?: string;\n\terrorMessage?: string;\n\tusage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; totalTokens?: number };\n}): boolean {\n\tif (message.stopReason !== \"error\" || !/resource.?exhausted/i.test(message.errorMessage || \"\")) {\n\t\treturn false;\n\t}\n\treturn !(cursorZeroTokenCount(message) > 0);\n}\n\nexport function shouldSkipProviderFallbackForCursorZeroRe(options: { sameModelRemint?: boolean } | undefined): boolean {\n\treturn options?.sameModelRemint === true;\n}\n\nexport function shouldRetryOverflowWithoutCompact(compacted: boolean, errorMessage: string): boolean {\n\tif (compacted) return false;\n\treturn /Nothing to compact/i.test(errorMessage || \"\");\n}\n\nexport function cursorOverflowCompactionSettings<T extends { keepRecentTokens?: number; restorationEnabled?: boolean }>(\n\tsettings: T,\n\tprovider: string | undefined,\n\treason: string | undefined,\n): T {\n\tif (reason !== \"overflow\") return settings;\n\tif (provider !== \"cursor\" && provider !== \"cursor-cli-oauth\") return settings;\n\treturn { ...settings, keepRecentTokens: 0, restorationEnabled: false };\n}\n"]}
1
+ {"version":3,"file":"overflow.js","sourceRoot":"","sources":["../../src/utils/overflow.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"../types.ts\";\n\n/**\n * Regex patterns to detect context overflow errors from different providers.\n *\n * These patterns match error messages returned when the input exceeds\n * the model's context window.\n *\n * Provider-specific patterns (with example error messages):\n *\n * - Anthropic: \"prompt is too long: 213462 tokens > 200000 maximum\"\n * - Anthropic: \"413 {\\\"error\\\":{\\\"type\\\":\\\"request_too_large\\\",\\\"message\\\":\\\"Request exceeds the maximum size\\\"}}\"\n * - OpenAI: \"Your input exceeds the context window of this model\"\n * - OpenAI/LiteLLM: \"Requested token count exceeds the model's maximum context length of 131072 tokens\"\n * - OpenAI-compatible: \"Input length (265330) exceeds model's maximum context length (262144).\"\n * - Google: \"The input token count (1196265) exceeds the maximum number of tokens allowed (1048575)\"\n * - xAI: \"This model's maximum prompt length is 131072 but the request contains 537812 tokens\"\n * - Groq: \"Please reduce the length of the messages or completion\"\n * - OpenRouter: \"This endpoint's maximum context length is X tokens. However, you requested about Y tokens\"\n * - OpenRouter/Poolside: \"Input length X exceeds the maximum allowed input length of Y tokens.\"\n * - Together AI: \"The input (X tokens) is longer than the model's context length (Y tokens).\"\n * - llama.cpp: \"the request exceeds the available context size, try increasing it\"\n * - LM Studio: \"tokens to keep from the initial prompt is greater than the context length\"\n * - GitHub Copilot: \"prompt token count of X exceeds the limit of Y\"\n * - MiniMax: \"invalid params, context window exceeds limit\"\n * - Kimi For Coding: \"Your request exceeded model token limit: X (requested: Y)\"\n * - DS4: \"Prompt has X tokens, but the configured context size is Y tokens\"\n * - Cerebras: \"400/413 status code (no body)\"\n * - Gateways: \"413 Request body too large\" / \"Request Entity Too Large\" / \"Payload Too Large\" (byte-size overflow)\n * - Mistral: \"Prompt contains X tokens ... too large for model with Y maximum context length\"\n * - z.ai: Does NOT error, accepts overflow silently - handled via usage.input > contextWindow\n * - Xiaomi MiMo: Truncates input to fill contextWindow exactly, then returns finish_reason \"length\"\n * with output=0 (no room left to generate). Detected via stopReason \"length\" + zero output +\n * input filling the context window.\n * - DashScope/Qwen: \"Range of input length should be [1, X]\" (HTTP 400 invalid_parameter_error)\n * - Ollama: Some deployments truncate silently, others return errors like \"prompt too long; exceeded max context length by X tokens\"\n */\nconst OVERFLOW_PATTERNS = [\n\t/prompt is too long/i, // Anthropic token overflow\n\t/request_too_large/i, // Anthropic request byte-size overflow (HTTP 413)\n\t/input is too long for requested model/i, // Amazon Bedrock\n\t/exceeds the context window/i, // OpenAI (Completions & Responses API)\n\t/exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\\d,]+ tokens?|\\s*\\([\\d,]+\\))/i, // OpenAI-compatible proxies (LiteLLM)\n\t/input token count.*exceeds the maximum/i, // Google (Gemini)\n\t/maximum prompt length is \\d+/i, // xAI (Grok)\n\t/reduce the length of the messages/i, // Groq\n\t/maximum context length is \\d+ tokens/i, // OpenRouter (most backends)\n\t/exceeds (?:the )?maximum allowed input length of [\\d,]+ tokens?/i, // OpenRouter/Poolside\n\t/input \\(\\d+ tokens\\) is longer than the model'?s context length \\(\\d+ tokens\\)/i, // Together AI\n\t/exceeds the limit of \\d+/i, // GitHub Copilot\n\t/exceeds the available context size/i, // llama.cpp server\n\t/greater than the context length/i, // LM Studio\n\t/context window exceeds limit/i, // MiniMax\n\t/exceeded model token limit/i, // Kimi For Coding\n\t/too large for model with \\d+ maximum context length/i, // Mistral\n\t/prompt has [\\d,]+ tokens?, but the configured context size is [\\d,]+ tokens?/i, // DS4 server\n\t/model_context_window_exceeded/i, // z.ai non-standard finish_reason surfaced as error text\n\t/prompt too long; exceeded (?:max )?context length/i, // Ollama explicit overflow error\n\t/range of input length should be/i, // DashScope / Qwen Token Plan\n\t/context[_ ]length[_ ]exceeded/i, // Generic fallback\n\t/too many tokens/i, // Generic fallback\n\t/token limit exceeded/i, // Generic fallback\n\t/^4(?:00|13)\\s*(?:status code)?\\s*\\(no body\\)/i, // Cerebras: 400/413 with no body\n\t/(?:request[ _])?(?:body|entity|payload)[_ ]too[_ ]large/i, // Gateway HTTP 413 byte-size rejections (\"Request body too large\", \"Request Entity Too Large\", \"body_too_large\", \"Payload Too Large\"). Substring-anchored by design (JSON bodies lack an adjacent status code); a non-context size rejection (e.g. an oversized image) can over-match, which costs one bounded shrink-retry, never a wedge.\n];\n\n/**\n * Patterns that indicate non-overflow errors (e.g. rate limiting, server errors).\n * Error messages matching any of these are excluded from overflow detection\n * even if they also match an OVERFLOW_PATTERN.\n *\n * Example: Bedrock formats throttling errors as \"ThrottlingException: Too many tokens,\n * please wait before trying again.\" which would match the /too many tokens/i overflow\n * pattern without this exclusion.\n */\nconst NON_OVERFLOW_PATTERNS = [\n\t/^(Throttling error|Service unavailable):/i, // AWS Bedrock non-overflow errors (human-readable prefixes from formatBedrockError)\n\t/rate limit/i, // Generic rate limiting\n\t/too many requests/i, // Generic HTTP 429 style\n];\n\n/**\n * Cursor's api2.cursor.sh surfaces a context overflow as a bare gRPC\n * `resource_exhausted` end-stream — the same wording its backend uses for\n * quota and poisoned-conversation rejections. Token evidence disambiguates:\n * a request that already streamed or billed tokens overflowed mid-flight,\n * while a zero-token rejection is a quota/conversation failure that must stay\n * on the rate-limit path (the cursor client rotates the conversation id for\n * those and retry handling supplies the backoff).\n */\nconst RESOURCE_EXHAUSTED_PATTERN = /resource.?exhausted/i;\n\n/**\n * Check if an assistant message represents a context overflow error.\n *\n * This handles three cases:\n * 1. Error-based overflow: Most providers return stopReason \"error\" with a\n * specific error message pattern.\n * 2. Silent overflow: Some providers accept overflow requests and return\n * successfully. For these, we check if usage.input exceeds the context window.\n * 3. Length-stop overflow: Xiaomi MiMo can return \"length\" with zero output when\n * the input fills the context window.\n *\n * ## Reliability by Provider\n *\n * **Reliable detection (returns error with detectable message):**\n * - Anthropic: \"prompt is too long: X tokens > Y maximum\" or \"request_too_large\"\n * - OpenAI (Completions & Responses): \"exceeds the context window\", \"exceeds the model's maximum context length of X tokens\", or \"exceeds model's maximum context length (X)\"\n * - Google Gemini: \"input token count exceeds the maximum\"\n * - xAI (Grok): \"maximum prompt length is X but request contains Y\"\n * - Groq: \"reduce the length of the messages\"\n * - Cerebras: 400/413 status code (no body)\n * - Mistral: \"Prompt contains X tokens ... too large for model with Y maximum context length\"\n * - OpenRouter (most backends): \"maximum context length is X tokens\"\n * - OpenRouter/Poolside: \"Input length X exceeds the maximum allowed input length of Y tokens.\"\n * - Together AI: \"The input (X tokens) is longer than the model's context length (Y tokens).\"\n * - llama.cpp: \"exceeds the available context size\"\n * - LM Studio: \"greater than the context length\"\n * - Kimi For Coding: \"exceeded model token limit: X (requested: Y)\"\n * - DS4: \"Prompt has X tokens, but the configured context size is Y tokens\"\n * - DashScope/Qwen: \"Range of input length should be [1, X]\"\n *\n * **Unreliable detection:**\n * - z.ai: Sometimes accepts overflow silently (detectable via usage.input > contextWindow),\n * sometimes returns rate limit errors. Pass contextWindow param to detect silent overflow.\n * - Xiaomi MiMo: Truncates input to fit contextWindow then returns stopReason \"length\" with\n * output=0. Pass contextWindow param to detect via the \"filled context + zero output\" signal.\n * - Ollama: May truncate input silently for some setups, but may also return explicit\n * overflow errors that match the patterns above. Silent truncation still cannot be\n * detected here because we do not know the expected token count.\n *\n * ## Custom Providers\n *\n * If you've added custom models via settings.json, this function may not detect\n * overflow errors from those providers. To add support:\n *\n * 1. Send a request that exceeds the model's context window\n * 2. Check the errorMessage in the response\n * 3. Create a regex pattern that matches the error\n * 4. The pattern should be added to OVERFLOW_PATTERNS in this file, or\n * check the errorMessage yourself before calling this function\n *\n * @param message - The assistant message to check\n * @param contextWindow - Optional context window size for detecting silent overflow (z.ai)\n * @returns true if the message indicates a context overflow\n */\nexport function isContextOverflow(message: AssistantMessage, contextWindow?: number): boolean {\n\t// Case 1: Check error message patterns\n\tif (message.stopReason === \"error\" && message.errorMessage) {\n\t\t// Skip messages matching known non-overflow patterns (e.g. throttling / rate-limit)\n\t\tconst isNonOverflow = NON_OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage!));\n\t\tif (!isNonOverflow && OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage!))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst usage = message.usage;\n\t\tconst hasTokenEvidence =\n\t\t\t(usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite) > 0;\n\t\tif (\n\t\t\t!isNonOverflow &&\n\t\t\thasTokenEvidence &&\n\t\t\tRESOURCE_EXHAUSTED_PATTERN.test(message.errorMessage) &&\n\t\t\t(contextWindow === undefined || contextWindow <= 0 || cursorZeroTokenCount(message) >= contextWindow * 0.5)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Case 2: Silent overflow (z.ai style) - successful but usage exceeds context\n\tif (contextWindow && message.stopReason === \"stop\") {\n\t\tconst inputTokens = message.usage.input + message.usage.cacheRead;\n\t\tif (inputTokens > contextWindow) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Case 3: Length-stop overflow (Xiaomi MiMo style) - server truncates oversized input\n\t// to fit the context window, leaving no room for output. Returns stopReason \"length\"\n\t// with output=0 and input+cacheRead filling the context window.\n\tif (contextWindow && message.stopReason === \"length\" && message.usage.output === 0) {\n\t\tconst inputTokens = message.usage.input + message.usage.cacheRead;\n\t\tif (inputTokens >= contextWindow * 0.99) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n/**\n * Check whether a length stop ended below the caller or model's intended output limit.\n * Such responses may be caused by context pressure or provider-side truncation, so callers\n * can make one bounded compact-and-retry attempt. `desiredMaxOutput` must be the original\n * limit before any context-based clamping.\n */\nexport function isRecoverableLength(message: AssistantMessage, desiredMaxOutput: number): boolean {\n\treturn message.stopReason === \"length\" && desiredMaxOutput > 0 && message.usage.output < desiredMaxOutput;\n}\n\n/**\n * Get the overflow patterns for testing purposes.\n */\nexport function getOverflowPatterns(): RegExp[] {\n\treturn [...OVERFLOW_PATTERNS];\n}\n\nfunction cursorZeroTokenCount(message: {\n\tusage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; totalTokens?: number };\n}): number {\n\tconst usage = message.usage;\n\tif (!usage) return 0;\n\treturn (\n\t\tusage.totalTokens || (usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0)\n\t);\n}\n\nexport function isCursorPayloadResourceExhausted(\n\tmessage: {\n\t\tstopReason?: string;\n\t\terrorMessage?: string;\n\t\tusage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; totalTokens?: number };\n\t},\n\t_estimateTokens: number,\n): boolean {\n\tif (message.stopReason !== \"error\" || !/resource.?exhausted/i.test(message.errorMessage || \"\")) {\n\t\treturn false;\n\t}\n\treturn !(cursorZeroTokenCount(message) > 0);\n}\n\n/**\n * Detects Cursor's verified usage-pool exhaustion signature: a token-bearing\n * `resource_exhausted` error while the conversation is well below the model\n * context window.\n */\nexport function isCursorQuotaResourceExhausted(\n\tmessage: {\n\t\tstopReason?: string;\n\t\terrorMessage?: string;\n\t\tusage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; totalTokens?: number };\n\t},\n\tcontextWindow: number,\n): boolean {\n\tconst tokens = cursorZeroTokenCount(message);\n\treturn (\n\t\tmessage.stopReason === \"error\" &&\n\t\tRESOURCE_EXHAUSTED_PATTERN.test(message.errorMessage || \"\") &&\n\t\tcontextWindow > 0 &&\n\t\ttokens > 0 &&\n\t\ttokens < contextWindow * 0.5\n\t);\n}\n\nexport function isCursorZeroTokenResourceExhausted(message: {\n\tstopReason?: string;\n\terrorMessage?: string;\n\tusage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; totalTokens?: number };\n}): boolean {\n\tif (message.stopReason !== \"error\" || !/resource.?exhausted/i.test(message.errorMessage || \"\")) {\n\t\treturn false;\n\t}\n\treturn !(cursorZeroTokenCount(message) > 0);\n}\n\nexport function shouldSkipProviderFallbackForCursorZeroRe(options: { sameModelRemint?: boolean } | undefined): boolean {\n\treturn options?.sameModelRemint === true;\n}\n\nexport function shouldRetryOverflowWithoutCompact(compacted: boolean, errorMessage: string): boolean {\n\tif (compacted) return false;\n\treturn /Nothing to compact/i.test(errorMessage || \"\");\n}\n\nexport function cursorOverflowCompactionSettings<T extends { keepRecentTokens?: number; restorationEnabled?: boolean }>(\n\tsettings: T,\n\tprovider: string | undefined,\n\treason: string | undefined,\n): T {\n\tif (reason !== \"overflow\") return settings;\n\tif (provider !== \"cursor\" && provider !== \"cursor-cli-oauth\") return settings;\n\treturn { ...settings, keepRecentTokens: 0, restorationEnabled: false };\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import type { RetryBackoffPolicy } from "./types.ts";
2
+ /**
3
+ * Pure per-attempt retry delay for a stage's backoff policy.
4
+ *
5
+ * The exponential base is `baseDelayMs * growthFactor ** (retryNumber - 1)`
6
+ * with `retryNumber` 1-based. The per-attempt cap is applied to that base
7
+ * BEFORE jitter (`null` = no cap, `0` = literal zero cap), then the jitter
8
+ * mode scales the capped value by the injected `random` sample in `[0, 1)`:
9
+ * `none` returns the capped delay, `additive` grows it by up to `ratio`,
10
+ * `subtractive` shrinks it by up to `ratio`. No `Math.random` here — callers
11
+ * inject the sample so the schedule stays deterministic and testable.
12
+ */
13
+ export declare function retryBackoffDelayMs(policy: RetryBackoffPolicy, retryNumber: number, random: number): number;
14
+ //# sourceMappingURL=backoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backoff.d.ts","sourceRoot":"","sources":["../../../src/utils/retry-profile/backoff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAW3G"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Pure per-attempt retry delay for a stage's backoff policy.
3
+ *
4
+ * The exponential base is `baseDelayMs * growthFactor ** (retryNumber - 1)`
5
+ * with `retryNumber` 1-based. The per-attempt cap is applied to that base
6
+ * BEFORE jitter (`null` = no cap, `0` = literal zero cap), then the jitter
7
+ * mode scales the capped value by the injected `random` sample in `[0, 1)`:
8
+ * `none` returns the capped delay, `additive` grows it by up to `ratio`,
9
+ * `subtractive` shrinks it by up to `ratio`. No `Math.random` here — callers
10
+ * inject the sample so the schedule stays deterministic and testable.
11
+ */
12
+ export function retryBackoffDelayMs(policy, retryNumber, random) {
13
+ const exponential = policy.baseDelayMs * policy.growthFactor ** (retryNumber - 1);
14
+ const capped = policy.perAttemptCapMs === null ? exponential : Math.min(exponential, policy.perAttemptCapMs);
15
+ switch (policy.jitter.mode) {
16
+ case "none":
17
+ return capped;
18
+ case "additive":
19
+ return capped + random * policy.jitter.ratio * capped;
20
+ case "subtractive":
21
+ return capped - random * policy.jitter.ratio * capped;
22
+ }
23
+ }
24
+ //# sourceMappingURL=backoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backoff.js","sourceRoot":"","sources":["../../../src/utils/retry-profile/backoff.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA0B,EAAE,WAAmB,EAAE,MAAc;IAClG,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,YAAY,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IAC7G,QAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5B,KAAK,MAAM;YACV,OAAO,MAAM,CAAC;QACf,KAAK,UAAU;YACd,OAAO,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;QACvD,KAAK,aAAa;YACjB,OAAO,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;IACxD,CAAC;AACF,CAAC","sourcesContent":["import type { RetryBackoffPolicy } from \"./types.ts\";\n\n/**\n * Pure per-attempt retry delay for a stage's backoff policy.\n *\n * The exponential base is `baseDelayMs * growthFactor ** (retryNumber - 1)`\n * with `retryNumber` 1-based. The per-attempt cap is applied to that base\n * BEFORE jitter (`null` = no cap, `0` = literal zero cap), then the jitter\n * mode scales the capped value by the injected `random` sample in `[0, 1)`:\n * `none` returns the capped delay, `additive` grows it by up to `ratio`,\n * `subtractive` shrinks it by up to `ratio`. No `Math.random` here — callers\n * inject the sample so the schedule stays deterministic and testable.\n */\nexport function retryBackoffDelayMs(policy: RetryBackoffPolicy, retryNumber: number, random: number): number {\n\tconst exponential = policy.baseDelayMs * policy.growthFactor ** (retryNumber - 1);\n\tconst capped = policy.perAttemptCapMs === null ? exponential : Math.min(exponential, policy.perAttemptCapMs);\n\tswitch (policy.jitter.mode) {\n\t\tcase \"none\":\n\t\t\treturn capped;\n\t\tcase \"additive\":\n\t\t\treturn capped + random * policy.jitter.ratio * capped;\n\t\tcase \"subtractive\":\n\t\t\treturn capped - random * policy.jitter.ratio * capped;\n\t}\n}\n"]}
@@ -0,0 +1,36 @@
1
+ import type { RetryClassifier } from "./types.ts";
2
+ /**
3
+ * Kimi provider-request classifier, ported from the source provider's retry
4
+ * policy (policy only, not its code). The switch is exhaustive over
5
+ * {@link RetryFailure}["kind"]:
6
+ *
7
+ * - abort / refusal / sensitive / quota-exhausted / image-format / unknown are
8
+ * terminal: user cancellations, content refusals, dead accounts, rejected
9
+ * payloads, and unrecognized failures never recover by re-sending.
10
+ * - connection / timeout / provider failures are transient transport noise.
11
+ * - empty-response is transient unless the model said `finishReason` was
12
+ * "filtered", which is a deterministic content rejection.
13
+ * - http-status is retryable only for the whitelisted codes above.
14
+ */
15
+ export declare const classifyKimiFailure: RetryClassifier;
16
+ /**
17
+ * Senpi assistant-turn classifier: the existing message regexes decide first;
18
+ * structured failure facts are consulted only where the regexes are silent.
19
+ *
20
+ * Precedence (terminal wins at every tie):
21
+ * 1. Deterministic failure kinds (abort/refusal/sensitive/quota/image-format)
22
+ * are terminal before any text inspection.
23
+ * 2. A non-retryable regex match is terminal — request-shape and quota wording
24
+ * outrank any structured status (a 500 carrying invalid-tool-schema text
25
+ * stays terminal, unlike under {@link classifyKimiFailure}).
26
+ * 3. Structured terminal facts (`shouldRetry: false`, quota provider codes).
27
+ * 4. A retryable regex match is transient — e.g. a 400 carrying Anthropic's
28
+ * server-tool pairing text stays retryable because the request builder
29
+ * repairs the replayed history.
30
+ * 5. Only when the regexes have no opinion does the structured status decide:
31
+ * whitelisted transient codes retry, everything else is terminal.
32
+ * 6. No regex match and no structured facts: terminal, exactly the legacy
33
+ * boolean fallback.
34
+ */
35
+ export declare const classifySenpiAssistantFailure: RetryClassifier;
36
+ //# sourceMappingURL=classifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifiers.d.ts","sourceRoot":"","sources":["../../../src/utils/retry-profile/classifiers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAuB,eAAe,EAAgB,MAAM,YAAY,CAAC;AAqBrF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,EAAE,eAoBjC,CAAC;AAkBF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,6BAA6B,EAAE,eAwB3C,CAAC"}
@@ -0,0 +1,109 @@
1
+ import { classifyErrorMessage } from "../retry.js";
2
+ /**
3
+ * Status codes Kimi's provider-request stage treats as retryable. 429 is its
4
+ * own `rate-limited` verdict (the turn budget treats it through hint tiers);
5
+ * the other whitelisted codes are ordinary `transient`. Every other status —
6
+ * client errors and non-whitelisted 5xx alike — is `terminal`.
7
+ */
8
+ const KIMI_RETRYABLE_STATUS_CODES = new Set([408, 409, 429, 500, 502, 503, 504, 529]);
9
+ function classifyKimiHttpStatus(statusCode) {
10
+ if (statusCode === undefined || !KIMI_RETRYABLE_STATUS_CODES.has(statusCode)) {
11
+ return { verdict: "terminal" };
12
+ }
13
+ return statusCode === 429 ? { verdict: "rate-limited" } : { verdict: "transient" };
14
+ }
15
+ function assertNever(kind) {
16
+ throw new Error(`Unhandled retry failure kind: ${kind}`);
17
+ }
18
+ /**
19
+ * Kimi provider-request classifier, ported from the source provider's retry
20
+ * policy (policy only, not its code). The switch is exhaustive over
21
+ * {@link RetryFailure}["kind"]:
22
+ *
23
+ * - abort / refusal / sensitive / quota-exhausted / image-format / unknown are
24
+ * terminal: user cancellations, content refusals, dead accounts, rejected
25
+ * payloads, and unrecognized failures never recover by re-sending.
26
+ * - connection / timeout / provider failures are transient transport noise.
27
+ * - empty-response is transient unless the model said `finishReason` was
28
+ * "filtered", which is a deterministic content rejection.
29
+ * - http-status is retryable only for the whitelisted codes above.
30
+ */
31
+ export const classifyKimiFailure = (failure) => {
32
+ switch (failure.kind) {
33
+ case "abort":
34
+ case "refusal":
35
+ case "sensitive":
36
+ case "quota-exhausted":
37
+ case "image-format":
38
+ case "unknown":
39
+ return { verdict: "terminal" };
40
+ case "connection":
41
+ case "timeout":
42
+ case "provider":
43
+ return { verdict: "transient" };
44
+ case "empty-response":
45
+ return failure.finishReason === "filtered" ? { verdict: "terminal" } : { verdict: "transient" };
46
+ case "http-status":
47
+ return classifyKimiHttpStatus(failure.statusCode);
48
+ default:
49
+ return assertNever(failure.kind);
50
+ }
51
+ };
52
+ /**
53
+ * Structured status codes the senpi default classifier treats as retryable
54
+ * when — and only when — the message regexes have no opinion. Mirrors the
55
+ * transient half of Kimi's table plus the Cloudflare gateway codes senpi
56
+ * already retries by regex.
57
+ */
58
+ const SENPI_STRUCTURED_RETRYABLE_STATUS_CODES = new Set([
59
+ 408, 409, 429, 500, 502, 503, 504, 522, 524, 529,
60
+ ]);
61
+ /** Provider error codes that prove a dead account regardless of message text. */
62
+ const SENPI_STRUCTURED_TERMINAL_PROVIDER_CODES = new Set([
63
+ "insufficient_quota",
64
+ "credits_required",
65
+ ]);
66
+ /**
67
+ * Senpi assistant-turn classifier: the existing message regexes decide first;
68
+ * structured failure facts are consulted only where the regexes are silent.
69
+ *
70
+ * Precedence (terminal wins at every tie):
71
+ * 1. Deterministic failure kinds (abort/refusal/sensitive/quota/image-format)
72
+ * are terminal before any text inspection.
73
+ * 2. A non-retryable regex match is terminal — request-shape and quota wording
74
+ * outrank any structured status (a 500 carrying invalid-tool-schema text
75
+ * stays terminal, unlike under {@link classifyKimiFailure}).
76
+ * 3. Structured terminal facts (`shouldRetry: false`, quota provider codes).
77
+ * 4. A retryable regex match is transient — e.g. a 400 carrying Anthropic's
78
+ * server-tool pairing text stays retryable because the request builder
79
+ * repairs the replayed history.
80
+ * 5. Only when the regexes have no opinion does the structured status decide:
81
+ * whitelisted transient codes retry, everything else is terminal.
82
+ * 6. No regex match and no structured facts: terminal, exactly the legacy
83
+ * boolean fallback.
84
+ */
85
+ export const classifySenpiAssistantFailure = (failure) => {
86
+ switch (failure.kind) {
87
+ case "abort":
88
+ case "refusal":
89
+ case "sensitive":
90
+ case "quota-exhausted":
91
+ case "image-format":
92
+ return { verdict: "terminal" };
93
+ }
94
+ const regexVerdict = classifyErrorMessage(failure.message);
95
+ if (regexVerdict === "non-retryable")
96
+ return { verdict: "terminal" };
97
+ if (failure.shouldRetry === false)
98
+ return { verdict: "terminal" };
99
+ if (failure.providerCodes?.some((code) => SENPI_STRUCTURED_TERMINAL_PROVIDER_CODES.has(code))) {
100
+ return { verdict: "terminal" };
101
+ }
102
+ if (regexVerdict === "retryable")
103
+ return { verdict: "transient" };
104
+ if (failure.statusCode !== undefined && SENPI_STRUCTURED_RETRYABLE_STATUS_CODES.has(failure.statusCode)) {
105
+ return failure.statusCode === 429 ? { verdict: "rate-limited" } : { verdict: "transient" };
106
+ }
107
+ return { verdict: "terminal" };
108
+ };
109
+ //# sourceMappingURL=classifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifiers.js","sourceRoot":"","sources":["../../../src/utils/retry-profile/classifiers.ts"],"names":[],"mappings":"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","sourcesContent":["import { classifyErrorMessage } from \"../retry.ts\";\nimport type { RetryClassification, RetryClassifier, RetryFailure } from \"./types.ts\";\n\n/**\n * Status codes Kimi's provider-request stage treats as retryable. 429 is its\n * own `rate-limited` verdict (the turn budget treats it through hint tiers);\n * the other whitelisted codes are ordinary `transient`. Every other status —\n * client errors and non-whitelisted 5xx alike — is `terminal`.\n */\nconst KIMI_RETRYABLE_STATUS_CODES: ReadonlySet<number> = new Set([408, 409, 429, 500, 502, 503, 504, 529]);\n\nfunction classifyKimiHttpStatus(statusCode: number | undefined): RetryClassification {\n\tif (statusCode === undefined || !KIMI_RETRYABLE_STATUS_CODES.has(statusCode)) {\n\t\treturn { verdict: \"terminal\" };\n\t}\n\treturn statusCode === 429 ? { verdict: \"rate-limited\" } : { verdict: \"transient\" };\n}\n\nfunction assertNever(kind: never): never {\n\tthrow new Error(`Unhandled retry failure kind: ${kind}`);\n}\n\n/**\n * Kimi provider-request classifier, ported from the source provider's retry\n * policy (policy only, not its code). The switch is exhaustive over\n * {@link RetryFailure}[\"kind\"]:\n *\n * - abort / refusal / sensitive / quota-exhausted / image-format / unknown are\n * terminal: user cancellations, content refusals, dead accounts, rejected\n * payloads, and unrecognized failures never recover by re-sending.\n * - connection / timeout / provider failures are transient transport noise.\n * - empty-response is transient unless the model said `finishReason` was\n * \"filtered\", which is a deterministic content rejection.\n * - http-status is retryable only for the whitelisted codes above.\n */\nexport const classifyKimiFailure: RetryClassifier = (failure) => {\n\tswitch (failure.kind) {\n\t\tcase \"abort\":\n\t\tcase \"refusal\":\n\t\tcase \"sensitive\":\n\t\tcase \"quota-exhausted\":\n\t\tcase \"image-format\":\n\t\tcase \"unknown\":\n\t\t\treturn { verdict: \"terminal\" };\n\t\tcase \"connection\":\n\t\tcase \"timeout\":\n\t\tcase \"provider\":\n\t\t\treturn { verdict: \"transient\" };\n\t\tcase \"empty-response\":\n\t\t\treturn failure.finishReason === \"filtered\" ? { verdict: \"terminal\" } : { verdict: \"transient\" };\n\t\tcase \"http-status\":\n\t\t\treturn classifyKimiHttpStatus(failure.statusCode);\n\t\tdefault:\n\t\t\treturn assertNever(failure.kind);\n\t}\n};\n\n/**\n * Structured status codes the senpi default classifier treats as retryable\n * when — and only when — the message regexes have no opinion. Mirrors the\n * transient half of Kimi's table plus the Cloudflare gateway codes senpi\n * already retries by regex.\n */\nconst SENPI_STRUCTURED_RETRYABLE_STATUS_CODES: ReadonlySet<number> = new Set([\n\t408, 409, 429, 500, 502, 503, 504, 522, 524, 529,\n]);\n\n/** Provider error codes that prove a dead account regardless of message text. */\nconst SENPI_STRUCTURED_TERMINAL_PROVIDER_CODES: ReadonlySet<string> = new Set([\n\t\"insufficient_quota\",\n\t\"credits_required\",\n]);\n\n/**\n * Senpi assistant-turn classifier: the existing message regexes decide first;\n * structured failure facts are consulted only where the regexes are silent.\n *\n * Precedence (terminal wins at every tie):\n * 1. Deterministic failure kinds (abort/refusal/sensitive/quota/image-format)\n * are terminal before any text inspection.\n * 2. A non-retryable regex match is terminal — request-shape and quota wording\n * outrank any structured status (a 500 carrying invalid-tool-schema text\n * stays terminal, unlike under {@link classifyKimiFailure}).\n * 3. Structured terminal facts (`shouldRetry: false`, quota provider codes).\n * 4. A retryable regex match is transient — e.g. a 400 carrying Anthropic's\n * server-tool pairing text stays retryable because the request builder\n * repairs the replayed history.\n * 5. Only when the regexes have no opinion does the structured status decide:\n * whitelisted transient codes retry, everything else is terminal.\n * 6. No regex match and no structured facts: terminal, exactly the legacy\n * boolean fallback.\n */\nexport const classifySenpiAssistantFailure: RetryClassifier = (failure) => {\n\tswitch (failure.kind) {\n\t\tcase \"abort\":\n\t\tcase \"refusal\":\n\t\tcase \"sensitive\":\n\t\tcase \"quota-exhausted\":\n\t\tcase \"image-format\":\n\t\t\treturn { verdict: \"terminal\" };\n\t}\n\n\tconst regexVerdict = classifyErrorMessage(failure.message);\n\tif (regexVerdict === \"non-retryable\") return { verdict: \"terminal\" };\n\n\tif (failure.shouldRetry === false) return { verdict: \"terminal\" };\n\tif (failure.providerCodes?.some((code) => SENPI_STRUCTURED_TERMINAL_PROVIDER_CODES.has(code))) {\n\t\treturn { verdict: \"terminal\" };\n\t}\n\n\tif (regexVerdict === \"retryable\") return { verdict: \"transient\" };\n\n\tif (failure.statusCode !== undefined && SENPI_STRUCTURED_RETRYABLE_STATUS_CODES.has(failure.statusCode)) {\n\t\treturn failure.statusCode === 429 ? { verdict: \"rate-limited\" } : { verdict: \"transient\" };\n\t}\n\treturn { verdict: \"terminal\" };\n};\n"]}