@code-yeongyu/senpi 2026.8.24 → 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 (427) hide show
  1. package/CHANGELOG.md +81 -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.map +1 -1
  13. package/dist/core/agent-abort-provenance.js +5 -1
  14. package/dist/core/agent-abort-provenance.js.map +1 -1
  15. package/dist/core/agent-session.d.ts +11 -0
  16. package/dist/core/agent-session.d.ts.map +1 -1
  17. package/dist/core/agent-session.js +125 -29
  18. package/dist/core/agent-session.js.map +1 -1
  19. package/dist/core/auth-storage.d.ts +4 -0
  20. package/dist/core/auth-storage.d.ts.map +1 -1
  21. package/dist/core/auth-storage.js +35 -8
  22. package/dist/core/auth-storage.js.map +1 -1
  23. package/dist/core/brand.d.ts +2 -0
  24. package/dist/core/brand.d.ts.map +1 -1
  25. package/dist/core/brand.js +1 -0
  26. package/dist/core/brand.js.map +1 -1
  27. package/dist/core/compaction/compaction.d.ts +1 -0
  28. package/dist/core/compaction/compaction.d.ts.map +1 -1
  29. package/dist/core/compaction/compaction.js +24 -8
  30. package/dist/core/compaction/compaction.js.map +1 -1
  31. package/dist/core/defaults.d.ts +1 -0
  32. package/dist/core/defaults.d.ts.map +1 -1
  33. package/dist/core/defaults.js +9 -0
  34. package/dist/core/defaults.js.map +1 -1
  35. package/dist/core/extensions/builtin/goal/terminal-provider-error.js +1 -1
  36. package/dist/core/extensions/builtin/goal/terminal-provider-error.js.map +1 -1
  37. package/dist/core/extensions/builtin/loop-guard/notice.d.ts.map +1 -1
  38. package/dist/core/extensions/builtin/loop-guard/notice.js +5 -1
  39. package/dist/core/extensions/builtin/loop-guard/notice.js.map +1 -1
  40. package/dist/core/extensions/builtin/mcp/config-schema.d.ts +2 -2
  41. package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
  42. package/dist/core/extensions/builtin/ttsr/index.js +6 -6
  43. package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
  44. package/dist/core/extensions/builtin/ttsr/message-update.d.ts +10 -0
  45. package/dist/core/extensions/builtin/ttsr/message-update.d.ts.map +1 -0
  46. package/dist/core/extensions/builtin/ttsr/message-update.js +38 -0
  47. package/dist/core/extensions/builtin/ttsr/message-update.js.map +1 -0
  48. package/dist/core/extensions/builtin/ttsr/remediation.d.ts +5 -10
  49. package/dist/core/extensions/builtin/ttsr/remediation.d.ts.map +1 -1
  50. package/dist/core/extensions/builtin/ttsr/remediation.js +19 -3
  51. package/dist/core/extensions/builtin/ttsr/remediation.js.map +1 -1
  52. package/dist/core/extensions/builtin/ttsr/stream-remediation.d.ts +1 -1
  53. package/dist/core/extensions/builtin/ttsr/stream-remediation.d.ts.map +1 -1
  54. package/dist/core/extensions/builtin/ttsr/stream-remediation.js.map +1 -1
  55. package/dist/core/extensions/builtin/ttsr/types.d.ts +1 -1
  56. package/dist/core/extensions/builtin/ttsr/types.d.ts.map +1 -1
  57. package/dist/core/extensions/builtin/ttsr/types.js.map +1 -1
  58. package/dist/core/extensions/builtin/ttsr/watch.d.ts +1 -1
  59. package/dist/core/extensions/builtin/ttsr/watch.d.ts.map +1 -1
  60. package/dist/core/extensions/builtin/ttsr/watch.js +2 -2
  61. package/dist/core/extensions/builtin/ttsr/watch.js.map +1 -1
  62. package/dist/core/extensions/index.d.ts +2 -2
  63. package/dist/core/extensions/index.d.ts.map +1 -1
  64. package/dist/core/extensions/index.js +1 -1
  65. package/dist/core/extensions/index.js.map +1 -1
  66. package/dist/core/extensions/loader.d.ts.map +1 -1
  67. package/dist/core/extensions/loader.js +107 -45
  68. package/dist/core/extensions/loader.js.map +1 -1
  69. package/dist/core/extensions/types.d.ts +17 -6
  70. package/dist/core/extensions/types.d.ts.map +1 -1
  71. package/dist/core/extensions/types.js +3 -0
  72. package/dist/core/extensions/types.js.map +1 -1
  73. package/dist/core/footer-data-provider.d.ts +1 -1
  74. package/dist/core/footer-data-provider.js +1 -1
  75. package/dist/core/footer-data-provider.js.map +1 -1
  76. package/dist/core/keybindings.d.ts +20 -19
  77. package/dist/core/keybindings.d.ts.map +1 -1
  78. package/dist/core/keybindings.js +26 -5
  79. package/dist/core/keybindings.js.map +1 -1
  80. package/dist/core/model-config-schema.d.ts +17 -5
  81. package/dist/core/model-config-schema.d.ts.map +1 -1
  82. package/dist/core/model-config-schema.js +1 -1
  83. package/dist/core/model-config-schema.js.map +1 -1
  84. package/dist/core/model-config.d.ts.map +1 -1
  85. package/dist/core/model-config.js +7 -5
  86. package/dist/core/model-config.js.map +1 -1
  87. package/dist/core/model-resolver.d.ts +3 -2
  88. package/dist/core/model-resolver.d.ts.map +1 -1
  89. package/dist/core/model-resolver.js +3 -2
  90. package/dist/core/model-resolver.js.map +1 -1
  91. package/dist/core/model-runtime.d.ts +0 -1
  92. package/dist/core/model-runtime.d.ts.map +1 -1
  93. package/dist/core/model-runtime.js +0 -18
  94. package/dist/core/model-runtime.js.map +1 -1
  95. package/dist/core/models-store.d.ts.map +1 -1
  96. package/dist/core/models-store.js +2 -1
  97. package/dist/core/models-store.js.map +1 -1
  98. package/dist/core/package-manager.d.ts.map +1 -1
  99. package/dist/core/package-manager.js +14 -10
  100. package/dist/core/package-manager.js.map +1 -1
  101. package/dist/core/pi-manifest.d.ts.map +1 -1
  102. package/dist/core/pi-manifest.js +2 -1
  103. package/dist/core/pi-manifest.js.map +1 -1
  104. package/dist/core/provider-composer.d.ts +2 -0
  105. package/dist/core/provider-composer.d.ts.map +1 -1
  106. package/dist/core/provider-composer.js +3 -6
  107. package/dist/core/provider-composer.js.map +1 -1
  108. package/dist/core/provider-display-names.d.ts.map +1 -1
  109. package/dist/core/provider-display-names.js +0 -1
  110. package/dist/core/provider-display-names.js.map +1 -1
  111. package/dist/core/provider-timeout-retry.d.ts.map +1 -1
  112. package/dist/core/provider-timeout-retry.js +8 -12
  113. package/dist/core/provider-timeout-retry.js.map +1 -1
  114. package/dist/core/resource-loader.d.ts.map +1 -1
  115. package/dist/core/resource-loader.js +3 -2
  116. package/dist/core/resource-loader.js.map +1 -1
  117. package/dist/core/retry-fallback/profile-override.d.ts +24 -0
  118. package/dist/core/retry-fallback/profile-override.d.ts.map +1 -0
  119. package/dist/core/retry-fallback/profile-override.js +138 -0
  120. package/dist/core/retry-fallback/profile-override.js.map +1 -0
  121. package/dist/core/retry-fallback/settings.d.ts +1 -0
  122. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  123. package/dist/core/retry-fallback/settings.js.map +1 -1
  124. package/dist/core/sdk.d.ts +2 -2
  125. package/dist/core/sdk.d.ts.map +1 -1
  126. package/dist/core/sdk.js +20 -5
  127. package/dist/core/sdk.js.map +1 -1
  128. package/dist/core/session-export.d.ts +4 -0
  129. package/dist/core/session-export.d.ts.map +1 -0
  130. package/dist/core/session-export.js +32 -0
  131. package/dist/core/session-export.js.map +1 -0
  132. package/dist/core/session-manager.d.ts.map +1 -1
  133. package/dist/core/session-manager.js +2 -1
  134. package/dist/core/session-manager.js.map +1 -1
  135. package/dist/core/settings-diagnostics.d.ts +9 -0
  136. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  137. package/dist/core/settings-diagnostics.js +21 -0
  138. package/dist/core/settings-diagnostics.js.map +1 -0
  139. package/dist/core/settings-manager.d.ts +18 -0
  140. package/dist/core/settings-manager.d.ts.map +1 -1
  141. package/dist/core/settings-manager.js +88 -7
  142. package/dist/core/settings-manager.js.map +1 -1
  143. package/dist/core/slash-commands.d.ts.map +1 -1
  144. package/dist/core/slash-commands.js +2 -1
  145. package/dist/core/slash-commands.js.map +1 -1
  146. package/dist/core/system-prompt.d.ts.map +1 -1
  147. package/dist/core/system-prompt.js +11 -2
  148. package/dist/core/system-prompt.js.map +1 -1
  149. package/dist/core/tools/bash.d.ts +14 -1
  150. package/dist/core/tools/bash.d.ts.map +1 -1
  151. package/dist/core/tools/bash.js +35 -19
  152. package/dist/core/tools/bash.js.map +1 -1
  153. package/dist/core/tools/edit-diff.d.ts +0 -5
  154. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  155. package/dist/core/tools/edit-diff.js +2 -5
  156. package/dist/core/tools/edit-diff.js.map +1 -1
  157. package/dist/core/tools/edit.d.ts.map +1 -1
  158. package/dist/core/tools/edit.js +3 -2
  159. package/dist/core/tools/edit.js.map +1 -1
  160. package/dist/core/tools/index.d.ts +4 -1
  161. package/dist/core/tools/index.d.ts.map +1 -1
  162. package/dist/core/tools/index.js +13 -1
  163. package/dist/core/tools/index.js.map +1 -1
  164. package/dist/core/tools/powershell.d.ts +16 -0
  165. package/dist/core/tools/powershell.d.ts.map +1 -0
  166. package/dist/core/tools/powershell.js +39 -0
  167. package/dist/core/tools/powershell.js.map +1 -0
  168. package/dist/core/trust-manager.d.ts.map +1 -1
  169. package/dist/core/trust-manager.js +2 -1
  170. package/dist/core/trust-manager.js.map +1 -1
  171. package/dist/extensions/llama/client.d.ts +6 -0
  172. package/dist/extensions/llama/client.d.ts.map +1 -1
  173. package/dist/extensions/llama/client.js +7 -0
  174. package/dist/extensions/llama/client.js.map +1 -1
  175. package/dist/extensions/llama/provider.d.ts +3 -1
  176. package/dist/extensions/llama/provider.d.ts.map +1 -1
  177. package/dist/extensions/llama/provider.js +27 -6
  178. package/dist/extensions/llama/provider.js.map +1 -1
  179. package/dist/index.d.ts +5 -4
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +4 -3
  182. package/dist/index.js.map +1 -1
  183. package/dist/main.d.ts.map +1 -1
  184. package/dist/main.js +13 -2
  185. package/dist/main.js.map +1 -1
  186. package/dist/migrations.d.ts.map +1 -1
  187. package/dist/migrations.js +4 -3
  188. package/dist/migrations.js.map +1 -1
  189. package/dist/modes/app-server/daemon/probe.js +1 -1
  190. package/dist/modes/app-server/daemon/probe.js.map +1 -1
  191. package/dist/modes/app-server/daemon.js +13 -2
  192. package/dist/modes/app-server/daemon.js.map +1 -1
  193. package/dist/modes/app-server/transports/websocket-connection-handler.d.ts.map +1 -1
  194. package/dist/modes/app-server/transports/websocket-connection-handler.js +4 -0
  195. package/dist/modes/app-server/transports/websocket-connection-handler.js.map +1 -1
  196. package/dist/modes/interactive/aborted-error-label.d.ts +2 -0
  197. package/dist/modes/interactive/aborted-error-label.d.ts.map +1 -1
  198. package/dist/modes/interactive/aborted-error-label.js +7 -0
  199. package/dist/modes/interactive/aborted-error-label.js.map +1 -1
  200. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  201. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  202. package/dist/modes/interactive/components/thinking-selector.js +68 -17
  203. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  204. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  205. package/dist/modes/interactive/external-editor.js +2 -1
  206. package/dist/modes/interactive/external-editor.js.map +1 -1
  207. package/dist/modes/interactive/interactive-mode.d.ts +6 -0
  208. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  209. package/dist/modes/interactive/interactive-mode.js +19 -12
  210. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  211. package/dist/modes/json-event.d.ts +16 -13
  212. package/dist/modes/json-event.d.ts.map +1 -1
  213. package/dist/modes/json-event.js +20 -6
  214. package/dist/modes/json-event.js.map +1 -1
  215. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  216. package/dist/modes/rpc/connection-handler.js +3 -0
  217. package/dist/modes/rpc/connection-handler.js.map +1 -1
  218. package/dist/modes/rpc/rpc-client.d.ts +7 -0
  219. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  220. package/dist/modes/rpc/rpc-client.js +7 -0
  221. package/dist/modes/rpc/rpc-client.js.map +1 -1
  222. package/dist/modes/rpc/rpc-types.d.ts +12 -0
  223. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  224. package/dist/modes/rpc/rpc-types.js.map +1 -1
  225. package/dist/package-manager-cli.d.ts +1 -0
  226. package/dist/package-manager-cli.d.ts.map +1 -1
  227. package/dist/package-manager-cli.js +186 -2
  228. package/dist/package-manager-cli.js.map +1 -1
  229. package/dist/utils/frontmatter.d.ts.map +1 -1
  230. package/dist/utils/frontmatter.js +2 -1
  231. package/dist/utils/frontmatter.js.map +1 -1
  232. package/dist/utils/shell.d.ts +3 -0
  233. package/dist/utils/shell.d.ts.map +1 -1
  234. package/dist/utils/shell.js +17 -5
  235. package/dist/utils/shell.js.map +1 -1
  236. package/dist/utils/syntax-highlight.d.ts +1 -0
  237. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  238. package/dist/utils/syntax-highlight.js +60 -1
  239. package/dist/utils/syntax-highlight.js.map +1 -1
  240. package/dist/utils/text.d.ts +8 -0
  241. package/dist/utils/text.d.ts.map +1 -0
  242. package/dist/utils/text.js +9 -0
  243. package/dist/utils/text.js.map +1 -0
  244. package/docs/compaction.md +0 -2
  245. package/docs/custom-provider.md +6 -6
  246. package/docs/environment-variables.md +8 -8
  247. package/docs/extensions.md +6 -5
  248. package/docs/json.md +7 -2
  249. package/docs/keybindings.md +1 -1
  250. package/docs/packages.md +2 -2
  251. package/docs/rpc.md +32 -3
  252. package/docs/sdk.md +7 -2
  253. package/docs/settings.md +9 -1
  254. package/docs/terminal-setup.md +11 -9
  255. package/docs/usage.md +4 -1
  256. package/docs/windows.md +24 -2
  257. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  258. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  259. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager-proxy.ts +39 -5
  260. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  261. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +7 -4
  262. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  263. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +2 -3
  264. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  265. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +7 -6
  266. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  267. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts +4 -0
  268. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts.map +1 -1
  269. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js +8 -0
  270. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js.map +1 -1
  271. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts +1 -0
  272. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts.map +1 -1
  273. package/node_modules/@earendil-works/pi-agent-core/dist/index.js +1 -0
  274. package/node_modules/@earendil-works/pi-agent-core/dist/index.js.map +1 -1
  275. package/node_modules/@earendil-works/pi-agent-core/package.json +5 -5
  276. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts +1 -5
  277. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +25 -13
  279. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  280. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.d.ts.map +1 -1
  281. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js +2 -1
  282. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js.map +1 -1
  283. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  284. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +91 -5
  285. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
  286. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.d.ts.map +1 -1
  287. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js +4 -2
  288. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js.map +1 -1
  289. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.d.ts.map +1 -1
  290. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js +4 -2
  291. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js.map +1 -1
  292. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.d.ts.map +1 -1
  293. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.js +2 -0
  294. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.js.map +1 -1
  295. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  296. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +93 -54
  297. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  298. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +2 -5
  299. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  300. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +1 -1
  301. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
  302. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts.map +1 -1
  303. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js +97 -46
  304. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js.map +1 -1
  305. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
  306. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +1 -14
  307. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js.map +1 -1
  308. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +50 -0
  309. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -0
  310. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +129 -0
  311. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -0
  312. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
  313. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +3 -1
  314. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
  315. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +8 -1
  316. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  317. package/node_modules/@earendil-works/pi-ai/dist/models.js +16 -3
  318. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  319. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.d.ts +3 -1
  320. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -1
  321. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.js +10 -1
  322. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.js.map +1 -1
  323. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  324. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
  325. package/node_modules/@earendil-works/pi-ai/dist/providers/data/azure-openai-responses.json +1 -1
  326. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  327. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  328. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
  329. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  330. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  331. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  332. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
  333. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
  334. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts +1 -0
  335. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts.map +1 -1
  336. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js +1 -0
  337. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js.map +1 -1
  338. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.d.ts.map +1 -1
  339. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js +4 -0
  340. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js.map +1 -1
  341. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +8 -1
  342. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  343. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  344. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +16 -0
  345. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  346. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +17 -1
  347. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  348. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/backoff.d.ts +14 -0
  349. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/backoff.d.ts.map +1 -0
  350. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/backoff.js +24 -0
  351. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/backoff.js.map +1 -0
  352. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.d.ts +36 -0
  353. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.d.ts.map +1 -0
  354. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.js +109 -0
  355. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.js.map +1 -0
  356. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/failure.d.ts +12 -0
  357. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/failure.d.ts.map +1 -0
  358. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/failure.js +109 -0
  359. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/failure.js.map +1 -0
  360. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/index.d.ts +9 -0
  361. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/index.d.ts.map +1 -0
  362. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/index.js +6 -0
  363. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/index.js.map +1 -0
  364. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/planner.d.ts +46 -0
  365. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/planner.d.ts.map +1 -0
  366. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/planner.js +41 -0
  367. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/planner.js.map +1 -0
  368. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.d.ts +4 -0
  369. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.d.ts.map +1 -0
  370. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.js +93 -0
  371. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.js.map +1 -0
  372. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/types.d.ts +121 -0
  373. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/types.d.ts.map +1 -0
  374. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/types.js +11 -0
  375. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/types.js.map +1 -0
  376. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +12 -0
  377. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  378. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +25 -5
  379. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  380. package/node_modules/@earendil-works/pi-ai/dist/utils/sleep.d.ts +2 -0
  381. package/node_modules/@earendil-works/pi-ai/dist/utils/sleep.d.ts.map +1 -0
  382. package/node_modules/@earendil-works/pi-ai/dist/utils/sleep.js +15 -0
  383. package/node_modules/@earendil-works/pi-ai/dist/utils/sleep.js.map +1 -0
  384. package/node_modules/@earendil-works/pi-ai/package.json +20 -16
  385. package/node_modules/@earendil-works/pi-pty/dist/index.d.ts +1 -0
  386. package/node_modules/@earendil-works/pi-pty/dist/index.d.ts.map +1 -1
  387. package/node_modules/@earendil-works/pi-pty/dist/index.js +1 -0
  388. package/node_modules/@earendil-works/pi-pty/dist/index.js.map +1 -1
  389. package/node_modules/@earendil-works/pi-pty/dist/session-bun.d.ts +30 -0
  390. package/node_modules/@earendil-works/pi-pty/dist/session-bun.d.ts.map +1 -0
  391. package/node_modules/@earendil-works/pi-pty/dist/session-bun.js +76 -0
  392. package/node_modules/@earendil-works/pi-pty/dist/session-bun.js.map +1 -0
  393. package/node_modules/@earendil-works/pi-pty/dist/session-types.d.ts +3 -1
  394. package/node_modules/@earendil-works/pi-pty/dist/session-types.d.ts.map +1 -1
  395. package/node_modules/@earendil-works/pi-pty/dist/session-types.js.map +1 -1
  396. package/node_modules/@earendil-works/pi-pty/dist/session.d.ts +2 -0
  397. package/node_modules/@earendil-works/pi-pty/dist/session.d.ts.map +1 -1
  398. package/node_modules/@earendil-works/pi-pty/dist/session.js +19 -9
  399. package/node_modules/@earendil-works/pi-pty/dist/session.js.map +1 -1
  400. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  401. package/node_modules/@earendil-works/pi-telemetry/package.json +3 -3
  402. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts.map +1 -1
  403. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +9 -4
  404. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js.map +1 -1
  405. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.d.ts +8 -2
  406. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.d.ts.map +1 -1
  407. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.js +24 -4
  408. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.js.map +1 -1
  409. package/node_modules/@earendil-works/pi-tui/dist/keybindings.d.ts +2 -2
  410. package/node_modules/@earendil-works/pi-tui/dist/keybindings.js +2 -2
  411. package/node_modules/@earendil-works/pi-tui/dist/keybindings.js.map +1 -1
  412. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts.map +1 -1
  413. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +2 -8
  414. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js.map +1 -1
  415. package/node_modules/@earendil-works/pi-tui/dist/native-module-path.d.ts +7 -0
  416. package/node_modules/@earendil-works/pi-tui/dist/native-module-path.d.ts.map +1 -0
  417. package/node_modules/@earendil-works/pi-tui/dist/native-module-path.js +19 -0
  418. package/node_modules/@earendil-works/pi-tui/dist/native-module-path.js.map +1 -0
  419. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  420. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +4 -10
  421. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  422. package/node_modules/@earendil-works/pi-tui/package.json +5 -5
  423. package/package.json +90 -88
  424. package/dist/core/radius.d.ts +0 -2
  425. package/dist/core/radius.d.ts.map +0 -1
  426. package/dist/core/radius.js +0 -2
  427. package/dist/core/radius.js.map +0 -1
@@ -16,10 +16,11 @@ import { randomUUID } from "node:crypto";
16
16
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
17
  import { basename, dirname } from "node:path";
18
18
  import { isDeepStrictEqual } from "node:util";
19
- import { prepareAgentToolCall } from "@earendil-works/pi-agent-core";
19
+ import { ProviderRetryWatchdogAbortError, prepareAgentToolCall } from "@earendil-works/pi-agent-core";
20
20
  import { contentText, SERVER_FALLBACK_ABORTED_DIAGNOSTIC } from "@earendil-works/pi-ai";
21
- import { cleanupSessionResources, cursorOverflowCompactionSettings, isClassifierRefusal, isContextOverflow, isCursorPayloadResourceExhausted, isCursorZeroTokenResourceExhausted, isProviderStreamStallError, isProviderTimeoutError, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, shouldRetryOverflowWithoutCompact, streamSimple, } from "@earendil-works/pi-ai/compat";
21
+ import { cleanupSessionResources, cursorOverflowCompactionSettings, isClassifierRefusal, isContextOverflow, isCursorPayloadResourceExhausted, isCursorQuotaResourceExhausted, isCursorZeroTokenResourceExhausted, isProviderStreamStallError, isProviderTimeoutError, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, shouldRetryOverflowWithoutCompact, streamSimple, } from "@earendil-works/pi-ai/compat";
22
22
  import { extract429RetryAfterMs, parseRetryAfterMsMarker } from "@earendil-works/pi-ai/utils/retry-hint";
23
+ import { retryBackoffDelayMs } from "@earendil-works/pi-ai/utils/retry-profile/backoff";
23
24
  import { getAgentDir } from "../config.js";
24
25
  import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
25
26
  import { stripFrontmatter } from "../utils/frontmatter.js";
@@ -313,6 +314,15 @@ export const MAX_SKILL_EXPANSIONS_PER_PROMPT = 5;
313
314
  // AgentSession Class
314
315
  // ============================================================================
315
316
  export class AgentSession {
317
+ /**
318
+ * Resolve the effective retry profile for the current model's provider.
319
+ * Falls back to the senpi-default profile when the provider declares none.
320
+ */
321
+ _resolveRetryProfile() {
322
+ const providerId = this.model?.provider;
323
+ const declared = providerId !== undefined ? this._modelRuntime.getProvider(providerId)?.retryPolicy : undefined;
324
+ return this.settingsManager.resolveRetryProfile(providerId !== undefined ? { id: providerId, retryPolicy: declared } : undefined);
325
+ }
316
326
  constructor(config) {
317
327
  this._eventListeners = [];
318
328
  this._agentEventQueue = Promise.resolve();
@@ -338,6 +348,7 @@ export class AgentSession {
338
348
  this._supersededCompactionLogAttemptIds = new Set();
339
349
  /** Messages queued to be included with the next user prompt as context ("asides"). */
340
350
  this._pendingNextTurnMessages = [];
351
+ this._pendingCustomMessages = [];
341
352
  // Queues held while the first post-compaction response is classified. Agent
342
353
  // core otherwise drains steering immediately before AgentSession can consume
343
354
  // the stale-usage exemption and schedule the continuation itself.
@@ -478,6 +489,7 @@ export class AgentSession {
478
489
  }
479
490
  this._selectorCooldowns = new SelectorCooldowns(config.fallbackNow ?? (() => Date.now()));
480
491
  this._fallbackNow = config.fallbackNow ?? (() => Date.now());
492
+ this._retryRandom = config.retryRandom ?? Math.random;
481
493
  this._retryFallback = new RetryFallbackController({
482
494
  getSettings: () => this.settingsManager.getRetryFallbackSettings(),
483
495
  registry: this._modelRegistry,
@@ -1090,7 +1102,8 @@ export class AgentSession {
1090
1102
  if (!lastAssistant ||
1091
1103
  (!this._isRetryableError(lastAssistant) &&
1092
1104
  !this._isHardErrorFallbackEligible(lastAssistant) &&
1093
- !isCursorZeroTokenResourceExhausted(lastAssistant))) {
1105
+ !isCursorZeroTokenResourceExhausted(lastAssistant) &&
1106
+ !isCursorQuotaResourceExhausted(lastAssistant, this.model?.contextWindow ?? 0))) {
1094
1107
  return;
1095
1108
  }
1096
1109
  this._retryPromise = new Promise((resolve) => {
@@ -1256,10 +1269,17 @@ export class AgentSession {
1256
1269
  if (!settings.enabled) {
1257
1270
  return false;
1258
1271
  }
1272
+ // The same-model budget comes from the resolved profile so a provider-declared
1273
+ // budget (e.g. kimi-code's 9) is honoured; identical to settings.maxRetries for
1274
+ // providers without a profile.
1275
+ const turnMaxRetries = this._resolveRetryProfile().turn.maxRetries;
1259
1276
  const retryableError = this._isRetryableError(lastAssistant);
1260
1277
  if (isCursorZeroTokenResourceExhausted(lastAssistant)) {
1261
1278
  return true;
1262
1279
  }
1280
+ if (isCursorQuotaResourceExhausted(lastAssistant, this.model?.contextWindow ?? 0)) {
1281
+ return this._retryFallback.canTryFallback();
1282
+ }
1263
1283
  if (!retryableError && this._isHardErrorFallbackEligible(lastAssistant)) {
1264
1284
  return true;
1265
1285
  }
@@ -1267,9 +1287,9 @@ export class AgentSession {
1267
1287
  return false;
1268
1288
  }
1269
1289
  if (isClassifierRefusal(lastAssistant)) {
1270
- return this._retryAttempt + 1 <= settings.maxRetries && this._retryFallback.canTryFallback();
1290
+ return this._retryAttempt + 1 <= turnMaxRetries && this._retryFallback.canTryFallback();
1271
1291
  }
1272
- if (this._retryAttempt + 1 > settings.maxRetries) {
1292
+ if (this._retryAttempt + 1 > turnMaxRetries) {
1273
1293
  return this._retryFallback.canTryFallback();
1274
1294
  }
1275
1295
  const errorMessage = lastAssistant.errorMessage || "Unknown error";
@@ -1405,9 +1425,10 @@ export class AgentSession {
1405
1425
  const retryableError = this._isRetryableError(msg);
1406
1426
  const hardErrorFallbackEligible = this._isHardErrorFallbackEligible(msg);
1407
1427
  const cursorZeroTokenRe = isCursorZeroTokenResourceExhausted(msg);
1428
+ const cursorQuotaRe = isCursorQuotaResourceExhausted(msg, this.model?.contextWindow ?? 0);
1408
1429
  const retryCanAdmitProvider = !userAbortSuppressedQueuedContinuation &&
1409
1430
  this.settingsManager.getRetrySettings().enabled &&
1410
- (retryableError || hardErrorFallbackEligible || cursorZeroTokenRe);
1431
+ (retryableError || hardErrorFallbackEligible || cursorZeroTokenRe || cursorQuotaRe);
1411
1432
  let compactedBeforeRetry = false;
1412
1433
  if (retryCanAdmitProvider &&
1413
1434
  requiredAutoCompaction &&
@@ -1423,6 +1444,12 @@ export class AgentSession {
1423
1444
  if (cursorZeroTokenRe) {
1424
1445
  retryOutcome = await this._handleRetryableError(msg, { sameModelRemint: true });
1425
1446
  }
1447
+ else if (cursorQuotaRe) {
1448
+ // Mid-turn Cursor errors may retain unpaired tool calls. Remove the
1449
+ // failed assistant before provider fallback so replay stays valid.
1450
+ this._retireFailedRetryAssistant(msg);
1451
+ retryOutcome = await this._handleRetryableError(msg, { hardErrorFallback: true });
1452
+ }
1426
1453
  else if (retryableError) {
1427
1454
  retryOutcome = await this._handleRetryableError(msg);
1428
1455
  }
@@ -1446,6 +1473,9 @@ export class AgentSession {
1446
1473
  retryOwnedDeferredQueue &&
1447
1474
  retryOutcome === "not-handled" &&
1448
1475
  (msg.stopReason === "error" || msg.stopReason === "aborted");
1476
+ if (retryOutcome === "not-handled" && cursorQuotaRe && msg.errorMessage) {
1477
+ msg.errorMessage = `${msg.errorMessage} (likely provider usage/quota exhaustion: conversation is well below the model context window)`;
1478
+ }
1449
1479
  if (retryOutcome === "not-handled" && this._retryAttempt > 0 && msg.errorMessage) {
1450
1480
  const attempt = this._retryAttempt;
1451
1481
  this._retryAttempt = 0;
@@ -1700,6 +1730,7 @@ export class AgentSession {
1700
1730
  };
1701
1731
  await this._extensionRunner.emit(extensionEvent);
1702
1732
  this._turnIndex++;
1733
+ this._flushPendingCustomMessages();
1703
1734
  }
1704
1735
  else if (event.type === "message_start") {
1705
1736
  const extensionEvent = {
@@ -3006,12 +3037,11 @@ export class AgentSession {
3006
3037
  }
3007
3038
  await this._promptAgent(appMessage, deferredTurnClaim);
3008
3039
  }
3040
+ else if (this.isStreaming) {
3041
+ this._pendingCustomMessages.push(appMessage);
3042
+ }
3009
3043
  else {
3010
- this.agent.state.messages.push(appMessage);
3011
- this.sessionManager.appendCustomMessageEntry(message.customType, message.content, message.display, message.details);
3012
- this._incrementMessageRevision();
3013
- this._emit({ type: "message_start", message: appMessage });
3014
- this._emit({ type: "message_end", message: appMessage });
3044
+ this._appendCustomMessage(appMessage);
3015
3045
  }
3016
3046
  }
3017
3047
  finally {
@@ -3019,6 +3049,19 @@ export class AgentSession {
3019
3049
  finishSessionWork?.();
3020
3050
  }
3021
3051
  }
3052
+ _appendCustomMessage(appMessage) {
3053
+ this.agent.state.messages.push(appMessage);
3054
+ this.sessionManager.appendCustomMessageEntry(appMessage.customType, appMessage.content, appMessage.display, appMessage.details);
3055
+ this._incrementMessageRevision();
3056
+ this._emit({ type: "message_start", message: appMessage });
3057
+ this._emit({ type: "message_end", message: appMessage });
3058
+ }
3059
+ _flushPendingCustomMessages() {
3060
+ const pending = this._pendingCustomMessages;
3061
+ this._pendingCustomMessages = [];
3062
+ for (const message of pending)
3063
+ this._appendCustomMessage(message);
3064
+ }
3022
3065
  /**
3023
3066
  * Send a user message to the agent. Always triggers a turn.
3024
3067
  * When the agent is streaming, use deliverAs to specify how to queue the message.
@@ -4449,11 +4492,7 @@ export class AgentSession {
4449
4492
  else {
4450
4493
  const messages = filterContextExcludedMessages(this.agent.state.messages);
4451
4494
  const estimate = estimateContextTokens(messages);
4452
- if (estimate.lastUsageIndex === null) {
4453
- if (!this._isRequiredCompactionError(assistantMessage))
4454
- return false;
4455
- }
4456
- else {
4495
+ if (estimate.lastUsageIndex !== null) {
4457
4496
  // Verify the usage source is post-compaction. Kept pre-compaction messages
4458
4497
  // have stale usage reflecting the old (larger) context and would falsely
4459
4498
  // trigger compaction right after one just finished.
@@ -4609,7 +4648,10 @@ export class AgentSession {
4609
4648
  }
4610
4649
  },
4611
4650
  getActiveSignal: () => this.agent.signal,
4612
- abortActive: () => this.agent.abort(),
4651
+ abortActive: () => this.agent.abort(new ProviderRetryWatchdogAbortError(`Provider retry continuation watchdog timed out after ${retryTimeoutMs}ms` +
4652
+ (this.agent.streamStartTimeoutMs === undefined
4653
+ ? " (stream-start guard disabled)"
4654
+ : ` (stream-start guard: ${this.agent.streamStartTimeoutMs}ms)`))),
4613
4655
  timeoutMs: retryTimeoutMs,
4614
4656
  });
4615
4657
  return "continued";
@@ -5560,6 +5602,9 @@ export class AgentSession {
5560
5602
  */
5561
5603
  _degradeRateLimitedWithoutFallback(tier, hintMs, message, errorMessage) {
5562
5604
  const settings = this.settingsManager.getRetrySettings();
5605
+ // Budget checks use the resolved profile (same value as settings.maxRetries
5606
+ // for providers without a declared profile).
5607
+ const turnMaxRetries = this._resolveRetryProfile().turn.maxRetries;
5563
5608
  const hintSettings = this.settingsManager.getHintPolicySettings();
5564
5609
  const finishTurn = (attempt, finalError) => {
5565
5610
  const exhaustedChainKey = this._retryFallback.exhaustedChainKey;
@@ -5587,7 +5632,7 @@ export class AgentSession {
5587
5632
  return undefined;
5588
5633
  }
5589
5634
  this._retryAttempt++;
5590
- if (this._retryAttempt > settings.maxRetries) {
5635
+ if (this._retryAttempt > turnMaxRetries) {
5591
5636
  finishTurn(this._retryAttempt - 1, message.errorMessage);
5592
5637
  return undefined;
5593
5638
  }
@@ -5603,6 +5648,10 @@ export class AgentSession {
5603
5648
  this._resolveRetry();
5604
5649
  return "not-handled";
5605
5650
  }
5651
+ // Resolve the effective retry profile for the current provider.
5652
+ // Profile-driven behaviour only diverges when a provider declares one;
5653
+ // the senpi-default profile preserves today's tier routing exactly.
5654
+ const retryProfile = this._resolveRetryProfile();
5606
5655
  // Retry promise is created synchronously in _handleAgentEvent for agent_end.
5607
5656
  // Keep a defensive fallback here in case a future refactor bypasses that path.
5608
5657
  if (!this._retryPromise) {
@@ -5619,7 +5668,7 @@ export class AgentSession {
5619
5668
  let hintTierDelayMs;
5620
5669
  if (sameModelRemint) {
5621
5670
  this._retryAttempt++;
5622
- if (this._retryAttempt > settings.maxRetries) {
5671
+ if (this._retryAttempt > retryProfile.turn.maxRetries) {
5623
5672
  if (this._retryAttempt > 1) {
5624
5673
  this._emit({
5625
5674
  type: "auto_retry_end",
@@ -5652,7 +5701,7 @@ export class AgentSession {
5652
5701
  else if (isRefusal) {
5653
5702
  // Refusals are only retried through a new chain candidate. They never use
5654
5703
  // same-model retries or the transient over-budget fallback escape hatch.
5655
- if (this._retryAttempt + 1 > settings.maxRetries) {
5704
+ if (this._retryAttempt + 1 > retryProfile.turn.maxRetries) {
5656
5705
  if (this._retryAttempt > 0) {
5657
5706
  this._emit({
5658
5707
  type: "auto_retry_end",
@@ -5693,8 +5742,8 @@ export class AgentSession {
5693
5742
  }
5694
5743
  else {
5695
5744
  // A provider-stream stall is an ordinary transient failure: it consumes
5696
- // the same bounded same-model budget (`settings.maxRetries`) as every
5697
- // other retryable class and escalates to the fallback chain only when
5745
+ // the same bounded same-model budget (the resolved profile's turn
5746
+ // maxRetries) as every other retryable class and escalates to the fallback chain only when
5698
5747
  // that budget is exhausted. It is excluded from 429-class tier routing
5699
5748
  // because a stall carries no rate-limit markers or retry-after hint.
5700
5749
  const stallError = isProviderStreamStallError(message);
@@ -5704,7 +5753,44 @@ export class AgentSession {
5704
5753
  // the cadence at a few milliseconds. Do not recompute that floor here.
5705
5754
  const is429Class = !stallError &&
5706
5755
  /rate.?limit|(?:^429(?=\s+\{)|(?:\bHTTP\/1\.[01]\s+|\bHTTP\s+|\bstatus(?:\s+code)?\s+|\berror\s+|\bcode\s+)429\b)|too many requests|resource.?exhausted/i.test(errorMessage);
5707
- if (is429Class) {
5756
+ // Profile-driven routing: "after-turn-budget" (Kimi) keeps 429s on the
5757
+ // ordinary same-model budget; "tiered" (senpi default) uses hint tiers.
5758
+ if (is429Class && retryProfile.fallback.rateLimited === "after-turn-budget") {
5759
+ // Kimi profile: 429s consume the same-model budget like any transient.
5760
+ // Mark tier-routed so the generic non-429 path below does not double-count.
5761
+ is429TierRouted = true;
5762
+ this._retryAttempt++;
5763
+ if (this._retryAttempt > retryProfile.turn.maxRetries) {
5764
+ switchedFallback = await this._retryFallback.tryFallback("transient", {
5765
+ errorMessage,
5766
+ retryAfterMs: this._getProviderRetryDelayMs(errorMessage),
5767
+ });
5768
+ if (switchedFallback) {
5769
+ this._retryAttempt = 1;
5770
+ }
5771
+ else {
5772
+ const exhaustedChainKey = this._retryFallback.exhaustedChainKey;
5773
+ if (exhaustedChainKey) {
5774
+ this._emit({
5775
+ type: "retry_fallback_exhausted",
5776
+ chainKey: exhaustedChainKey,
5777
+ lastError: errorMessage,
5778
+ });
5779
+ }
5780
+ this._emit({
5781
+ type: "auto_retry_end",
5782
+ success: false,
5783
+ attempt: this._retryAttempt - 1,
5784
+ finalError: message.errorMessage,
5785
+ });
5786
+ this._retryAttempt = 0;
5787
+ this._resetHintTierState();
5788
+ this._resolveRetry();
5789
+ return "not-handled";
5790
+ }
5791
+ }
5792
+ }
5793
+ else if (is429Class) {
5708
5794
  const hintMs = this._getProviderRetryDelayMs(errorMessage);
5709
5795
  const hintSettings = this.settingsManager.getHintPolicySettings();
5710
5796
  const tier = classifyRateLimitedWait(hintMs, hintSettings);
@@ -5725,7 +5811,7 @@ export class AgentSession {
5725
5811
  }
5726
5812
  else if (tier === "tier1-in-turn") {
5727
5813
  this._retryAttempt++;
5728
- if (this._retryAttempt > settings.maxRetries) {
5814
+ if (this._retryAttempt > retryProfile.turn.maxRetries) {
5729
5815
  // Budget exhausted within tier1; fall back.
5730
5816
  switchedFallback = await this._retryFallback.tryFallback("transient", {
5731
5817
  errorMessage,
@@ -5826,7 +5912,7 @@ export class AgentSession {
5826
5912
  if (!is429TierRouted) {
5827
5913
  this._retryAttempt++;
5828
5914
  }
5829
- if (!is429TierRouted && this._retryAttempt > settings.maxRetries) {
5915
+ if (!is429TierRouted && this._retryAttempt > retryProfile.turn.maxRetries) {
5830
5916
  switchedFallback = await this._retryFallback.tryFallback("transient", {
5831
5917
  errorMessage,
5832
5918
  retryAfterMs: this._getProviderRetryDelayMs(errorMessage),
@@ -5859,8 +5945,13 @@ export class AgentSession {
5859
5945
  }
5860
5946
  const providerDelayMs = isRefusal || hardErrorFallback ? undefined : this._getProviderRetryDelayMs(errorMessage);
5861
5947
  const maxRetryDelayMs = this.settingsManager.getProviderRetrySettings().maxRetryDelayMs;
5948
+ // Profile ceiling null (Kimi) bypasses the over-ceiling error path entirely.
5949
+ const profileCeiling = retryProfile.turn.serverHint.mode === "override"
5950
+ ? retryProfile.turn.serverHint.ceiling.maxDelayMs
5951
+ : maxRetryDelayMs;
5952
+ const effectiveMaxRetryDelayMs = profileCeiling ?? Number.MAX_SAFE_INTEGER;
5862
5953
  // For 429-class failures the tier routing replaces the over-budget gate.
5863
- if (!is429TierRouted && providerDelayMs !== undefined && providerDelayMs > maxRetryDelayMs) {
5954
+ if (!is429TierRouted && providerDelayMs !== undefined && providerDelayMs > effectiveMaxRetryDelayMs) {
5864
5955
  // A wait this long means the model is unavailable rather than busy, so the
5865
5956
  // configured chain beats failing the turn. The switch is gated: the over-budget
5866
5957
  // branch above may have already switched on this same error, and hopping again
@@ -5895,17 +5986,22 @@ export class AgentSession {
5895
5986
  // 429-tier delays already carry the exponential floor from nextInTurnDelayMs /
5896
5987
  // degradeWithoutFallback; the non-tier branch keeps its own exponential fallback.
5897
5988
  const nonTierProviderDelayMs = providerDelayMs === 0 ? undefined : providerDelayMs;
5989
+ // Locally computed exponential goes through the profile's backoff policy
5990
+ // (cap + jitter), sampled through the injectable retryRandom seam so tests
5991
+ // stay deterministic; provider-derived hints on the non-429 path remain
5992
+ // authoritative and fallback switches stay exact.
5993
+ const localExponentialMs = retryBackoffDelayMs(retryProfile.turn.backoff, this._retryAttempt, this._retryRandom());
5898
5994
  const delayMs = switchedFallback
5899
5995
  ? 0
5900
5996
  : is429TierRouted
5901
- ? (hintTierDelayMs ?? providerDelayMs ?? settings.baseDelayMs * 2 ** (this._retryAttempt - 1))
5902
- : (nonTierProviderDelayMs ?? settings.baseDelayMs * 2 ** (this._retryAttempt - 1));
5997
+ ? (hintTierDelayMs ?? providerDelayMs ?? localExponentialMs)
5998
+ : (nonTierProviderDelayMs ?? localExponentialMs);
5903
5999
  // Prepare before auto_retry_start so an immediate Esc can cancel the retry sleep.
5904
6000
  this._retryAbortController = new AbortController();
5905
6001
  this._emit({
5906
6002
  type: "auto_retry_start",
5907
6003
  attempt: this._retryAttempt,
5908
- maxAttempts: settings.maxRetries,
6004
+ maxAttempts: retryProfile.turn.maxRetries,
5909
6005
  delayMs,
5910
6006
  errorMessage,
5911
6007
  });