@code-yeongyu/senpi 2026.7.17 → 2026.7.20-2

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 (738) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/README.md +5 -2
  3. package/dist/cli/neo/build-argv.d.ts.map +1 -1
  4. package/dist/cli/neo/build-argv.js +2 -0
  5. package/dist/cli/neo/build-argv.js.map +1 -1
  6. package/dist/core/agent-session-services.d.ts.map +1 -1
  7. package/dist/core/agent-session-services.js +11 -4
  8. package/dist/core/agent-session-services.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +37 -0
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +395 -73
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/compaction/compaction.d.ts +2 -2
  14. package/dist/core/compaction/compaction.d.ts.map +1 -1
  15. package/dist/core/compaction/compaction.js +59 -15
  16. package/dist/core/compaction/compaction.js.map +1 -1
  17. package/dist/core/dynamic-prompt/build.d.ts +7 -0
  18. package/dist/core/dynamic-prompt/build.d.ts.map +1 -1
  19. package/dist/core/dynamic-prompt/build.js +5 -0
  20. package/dist/core/dynamic-prompt/build.js.map +1 -1
  21. package/dist/core/dynamic-prompt/workstation.d.ts +35 -0
  22. package/dist/core/dynamic-prompt/workstation.d.ts.map +1 -0
  23. package/dist/core/dynamic-prompt/workstation.js +81 -0
  24. package/dist/core/dynamic-prompt/workstation.js.map +1 -0
  25. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  26. package/dist/core/extensions/builtin/compaction/index.js +68 -10
  27. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  28. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts +1 -0
  29. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts.map +1 -1
  30. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js +20 -2
  31. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js.map +1 -1
  32. package/dist/core/extensions/builtin/compaction/speculative.d.ts +7 -1
  33. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  34. package/dist/core/extensions/builtin/compaction/speculative.js +29 -11
  35. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  36. package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +9 -7
  37. package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
  38. package/dist/core/extensions/builtin/compaction/todo-bridge.js +34 -9
  39. package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
  40. package/dist/core/extensions/builtin/goal/command-registration.d.ts +2 -2
  41. package/dist/core/extensions/builtin/goal/command-registration.d.ts.map +1 -1
  42. package/dist/core/extensions/builtin/goal/command-registration.js +3 -4
  43. package/dist/core/extensions/builtin/goal/command-registration.js.map +1 -1
  44. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  45. package/dist/core/extensions/builtin/goal/index.js +11 -27
  46. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  47. package/dist/core/extensions/builtin/goal/tool-registration.d.ts +2 -2
  48. package/dist/core/extensions/builtin/goal/tool-registration.d.ts.map +1 -1
  49. package/dist/core/extensions/builtin/goal/tool-registration.js +2 -3
  50. package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
  51. package/dist/core/extensions/builtin/goal/turn-usage.d.ts +20 -0
  52. package/dist/core/extensions/builtin/goal/turn-usage.d.ts.map +1 -0
  53. package/dist/core/extensions/builtin/goal/turn-usage.js +61 -0
  54. package/dist/core/extensions/builtin/goal/turn-usage.js.map +1 -0
  55. package/dist/core/extensions/builtin/gpt-apply-patch/constants.d.ts +1 -0
  56. package/dist/core/extensions/builtin/gpt-apply-patch/constants.d.ts.map +1 -1
  57. package/dist/core/extensions/builtin/gpt-apply-patch/constants.js +5 -1
  58. package/dist/core/extensions/builtin/gpt-apply-patch/constants.js.map +1 -1
  59. package/dist/core/extensions/builtin/gpt-apply-patch/extension.d.ts +2 -1
  60. package/dist/core/extensions/builtin/gpt-apply-patch/extension.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/gpt-apply-patch/extension.js +48 -29
  62. package/dist/core/extensions/builtin/gpt-apply-patch/extension.js.map +1 -1
  63. package/dist/core/extensions/builtin/gpt-apply-patch/index.d.ts +2 -2
  64. package/dist/core/extensions/builtin/gpt-apply-patch/index.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/gpt-apply-patch/index.js +2 -2
  66. package/dist/core/extensions/builtin/gpt-apply-patch/index.js.map +1 -1
  67. package/dist/core/extensions/builtin/gpt-apply-patch/tool.d.ts +1 -1
  68. package/dist/core/extensions/builtin/gpt-apply-patch/tool.d.ts.map +1 -1
  69. package/dist/core/extensions/builtin/gpt-apply-patch/tool.js +5 -3
  70. package/dist/core/extensions/builtin/gpt-apply-patch/tool.js.map +1 -1
  71. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts +7 -6
  72. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts.map +1 -1
  73. package/dist/core/extensions/builtin/gpt-apply-patch/types.js.map +1 -1
  74. package/dist/core/extensions/builtin/hooks/matcher.d.ts.map +1 -1
  75. package/dist/core/extensions/builtin/hooks/matcher.js +1 -0
  76. package/dist/core/extensions/builtin/hooks/matcher.js.map +1 -1
  77. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  78. package/dist/core/extensions/builtin/index.js +4 -0
  79. package/dist/core/extensions/builtin/index.js.map +1 -1
  80. package/dist/core/extensions/builtin/mcp/config-schema.d.ts +8 -1
  81. package/dist/core/extensions/builtin/mcp/config-schema.d.ts.map +1 -1
  82. package/dist/core/extensions/builtin/mcp/config-schema.js +23 -0
  83. package/dist/core/extensions/builtin/mcp/config-schema.js.map +1 -1
  84. package/dist/core/extensions/builtin/mcp/config.d.ts +13 -0
  85. package/dist/core/extensions/builtin/mcp/config.d.ts.map +1 -1
  86. package/dist/core/extensions/builtin/mcp/config.js +36 -0
  87. package/dist/core/extensions/builtin/mcp/config.js.map +1 -1
  88. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts +1 -1
  89. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts.map +1 -1
  90. package/dist/core/extensions/builtin/mcp/expose/native-search.js +1 -1
  91. package/dist/core/extensions/builtin/mcp/expose/native-search.js.map +1 -1
  92. package/dist/core/extensions/builtin/mcp/expose/policy.js +1 -1
  93. package/dist/core/extensions/builtin/mcp/expose/policy.js.map +1 -1
  94. package/dist/core/extensions/builtin/mcp/expose/status.js +1 -1
  95. package/dist/core/extensions/builtin/mcp/expose/status.js.map +1 -1
  96. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts +3 -3
  97. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts.map +1 -1
  98. package/dist/core/extensions/builtin/mcp/expose/tier-b.js +10 -10
  99. package/dist/core/extensions/builtin/mcp/expose/tier-b.js.map +1 -1
  100. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts +3 -3
  101. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts.map +1 -1
  102. package/dist/core/extensions/builtin/mcp/expose/tool-search.js +14 -14
  103. package/dist/core/extensions/builtin/mcp/expose/tool-search.js.map +1 -1
  104. package/dist/core/extensions/builtin/mcp/index.js +5 -5
  105. package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
  106. package/dist/core/extensions/builtin/mcp/service-snapshot.d.ts.map +1 -1
  107. package/dist/core/extensions/builtin/mcp/service-snapshot.js +1 -0
  108. package/dist/core/extensions/builtin/mcp/service-snapshot.js.map +1 -1
  109. package/dist/core/extensions/builtin/mcp/service-types.d.ts +12 -0
  110. package/dist/core/extensions/builtin/mcp/service-types.d.ts.map +1 -1
  111. package/dist/core/extensions/builtin/mcp/service-types.js.map +1 -1
  112. package/dist/core/extensions/builtin/mcp/service.d.ts +2 -2
  113. package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
  114. package/dist/core/extensions/builtin/mcp/service.js +4 -3
  115. package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
  116. package/dist/core/extensions/builtin/mcp/status.js +1 -0
  117. package/dist/core/extensions/builtin/mcp/status.js.map +1 -1
  118. package/dist/core/extensions/builtin/model-fallback/index.d.ts +4 -0
  119. package/dist/core/extensions/builtin/model-fallback/index.d.ts.map +1 -0
  120. package/dist/core/extensions/builtin/model-fallback/index.js +55 -0
  121. package/dist/core/extensions/builtin/model-fallback/index.js.map +1 -0
  122. package/dist/core/extensions/builtin/model-fallback/settings.d.ts +6 -0
  123. package/dist/core/extensions/builtin/model-fallback/settings.d.ts.map +1 -0
  124. package/dist/core/extensions/builtin/model-fallback/settings.js +11 -0
  125. package/dist/core/extensions/builtin/model-fallback/settings.js.map +1 -0
  126. package/dist/core/extensions/builtin/model-fallback/ui.d.ts +12 -0
  127. package/dist/core/extensions/builtin/model-fallback/ui.d.ts.map +1 -0
  128. package/dist/core/extensions/builtin/model-fallback/ui.js +72 -0
  129. package/dist/core/extensions/builtin/model-fallback/ui.js.map +1 -0
  130. package/dist/core/extensions/builtin/nested-agents-md/index.d.ts.map +1 -1
  131. package/dist/core/extensions/builtin/nested-agents-md/index.js +4 -1
  132. package/dist/core/extensions/builtin/nested-agents-md/index.js.map +1 -1
  133. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -1
  134. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +5 -1
  135. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
  136. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.d.ts.map +1 -1
  137. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js +5 -1
  138. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js.map +1 -1
  139. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.d.ts.map +1 -1
  140. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js +5 -1
  141. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js.map +1 -1
  142. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.d.ts.map +1 -1
  143. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js +5 -1
  144. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js.map +1 -1
  145. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.d.ts.map +1 -1
  146. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js +5 -1
  147. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js.map +1 -1
  148. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.js +2 -2
  149. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.js.map +1 -1
  150. package/dist/core/extensions/builtin/prompt-preset/gpt-5.2.js +1 -1
  151. package/dist/core/extensions/builtin/prompt-preset/gpt-5.2.js.map +1 -1
  152. package/dist/core/extensions/builtin/prompt-preset/gpt-5.3-codex.js +1 -1
  153. package/dist/core/extensions/builtin/prompt-preset/gpt-5.3-codex.js.map +1 -1
  154. package/dist/core/extensions/builtin/prompt-preset/gpt-5.4.js +1 -1
  155. package/dist/core/extensions/builtin/prompt-preset/gpt-5.4.js.map +1 -1
  156. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +3 -3
  157. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
  158. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +3 -3
  159. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  160. package/dist/core/extensions/builtin/prompt-preset/gpt-5.js +1 -1
  161. package/dist/core/extensions/builtin/prompt-preset/gpt-5.js.map +1 -1
  162. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts +3 -0
  163. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts.map +1 -0
  164. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +80 -0
  165. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js.map +1 -0
  166. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js +1 -1
  167. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js.map +1 -1
  168. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js +1 -1
  169. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js.map +1 -1
  170. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.d.ts.map +1 -1
  171. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +5 -7
  172. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
  173. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  174. package/dist/core/extensions/builtin/prompt-preset/presets.js +14 -0
  175. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  176. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  177. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  178. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  179. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  180. package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -1
  181. package/dist/core/extensions/builtin/rules/index.js +4 -1
  182. package/dist/core/extensions/builtin/rules/index.js.map +1 -1
  183. package/dist/core/extensions/builtin/terminal/shared.d.ts +7 -0
  184. package/dist/core/extensions/builtin/terminal/shared.d.ts.map +1 -1
  185. package/dist/core/extensions/builtin/terminal/shared.js +7 -0
  186. package/dist/core/extensions/builtin/terminal/shared.js.map +1 -1
  187. package/dist/core/extensions/builtin/terminal/tools/bash.d.ts.map +1 -1
  188. package/dist/core/extensions/builtin/terminal/tools/bash.js +68 -6
  189. package/dist/core/extensions/builtin/terminal/tools/bash.js.map +1 -1
  190. package/dist/core/extensions/builtin/todotools/commands.d.ts +18 -0
  191. package/dist/core/extensions/builtin/todotools/commands.d.ts.map +1 -0
  192. package/dist/core/extensions/builtin/todotools/commands.js +395 -0
  193. package/dist/core/extensions/builtin/todotools/commands.js.map +1 -0
  194. package/dist/core/extensions/builtin/todotools/index.d.ts +4 -1
  195. package/dist/core/extensions/builtin/todotools/index.d.ts.map +1 -1
  196. package/dist/core/extensions/builtin/todotools/index.js +17 -14
  197. package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
  198. package/dist/core/extensions/builtin/todotools/markdown.d.ts +13 -0
  199. package/dist/core/extensions/builtin/todotools/markdown.d.ts.map +1 -0
  200. package/dist/core/extensions/builtin/todotools/markdown.js +82 -0
  201. package/dist/core/extensions/builtin/todotools/markdown.js.map +1 -0
  202. package/dist/core/extensions/builtin/todotools/prompt.d.ts +2 -1
  203. package/dist/core/extensions/builtin/todotools/prompt.d.ts.map +1 -1
  204. package/dist/core/extensions/builtin/todotools/prompt.js +50 -153
  205. package/dist/core/extensions/builtin/todotools/prompt.js.map +1 -1
  206. package/dist/core/extensions/builtin/todotools/state.d.ts +67 -14
  207. package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
  208. package/dist/core/extensions/builtin/todotools/state.js +400 -35
  209. package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
  210. package/dist/core/extensions/builtin/todotools/tools/todo.d.ts +22 -0
  211. package/dist/core/extensions/builtin/todotools/tools/todo.d.ts.map +1 -0
  212. package/dist/core/extensions/builtin/todotools/tools/todo.js +229 -0
  213. package/dist/core/extensions/builtin/todotools/tools/todo.js.map +1 -0
  214. package/dist/core/extensions/builtin/video-in/index.d.ts +3 -0
  215. package/dist/core/extensions/builtin/video-in/index.d.ts.map +1 -0
  216. package/dist/core/extensions/builtin/video-in/index.js +111 -0
  217. package/dist/core/extensions/builtin/video-in/index.js.map +1 -0
  218. package/dist/core/extensions/builtin/websearch/index.d.ts.map +1 -1
  219. package/dist/core/extensions/builtin/websearch/index.js +20 -3
  220. package/dist/core/extensions/builtin/websearch/index.js.map +1 -1
  221. package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts.map +1 -1
  222. package/dist/core/extensions/builtin/websearch/websearch/renderers.js +13 -4
  223. package/dist/core/extensions/builtin/websearch/websearch/renderers.js.map +1 -1
  224. package/dist/core/extensions/builtin/websearch/websearch/search.d.ts +3 -2
  225. package/dist/core/extensions/builtin/websearch/websearch/search.d.ts.map +1 -1
  226. package/dist/core/extensions/builtin/websearch/websearch/search.js +2 -1
  227. package/dist/core/extensions/builtin/websearch/websearch/search.js.map +1 -1
  228. package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts.map +1 -1
  229. package/dist/core/extensions/builtin/websearch/websearch/tool.js +17 -1
  230. package/dist/core/extensions/builtin/websearch/websearch/tool.js.map +1 -1
  231. package/dist/core/extensions/builtin/websearch/websearch/types.d.ts +2 -0
  232. package/dist/core/extensions/builtin/websearch/websearch/types.d.ts.map +1 -1
  233. package/dist/core/extensions/builtin/websearch/websearch/types.js.map +1 -1
  234. package/dist/core/extensions/index.d.ts +1 -0
  235. package/dist/core/extensions/index.d.ts.map +1 -1
  236. package/dist/core/extensions/index.js.map +1 -1
  237. package/dist/core/extensions/loader.d.ts +10 -1
  238. package/dist/core/extensions/loader.d.ts.map +1 -1
  239. package/dist/core/extensions/loader.js +64 -7
  240. package/dist/core/extensions/loader.js.map +1 -1
  241. package/dist/core/extensions/runner.d.ts +6 -2
  242. package/dist/core/extensions/runner.d.ts.map +1 -1
  243. package/dist/core/extensions/runner.js +80 -8
  244. package/dist/core/extensions/runner.js.map +1 -1
  245. package/dist/core/extensions/types.d.ts +116 -18
  246. package/dist/core/extensions/types.d.ts.map +1 -1
  247. package/dist/core/extensions/types.js.map +1 -1
  248. package/dist/core/model-registry.d.ts +5 -1
  249. package/dist/core/model-registry.d.ts.map +1 -1
  250. package/dist/core/model-registry.js +17 -2
  251. package/dist/core/model-registry.js.map +1 -1
  252. package/dist/core/model-runtime.d.ts +12 -1
  253. package/dist/core/model-runtime.d.ts.map +1 -1
  254. package/dist/core/model-runtime.js +51 -9
  255. package/dist/core/model-runtime.js.map +1 -1
  256. package/dist/core/prompt-templates.d.ts +1 -0
  257. package/dist/core/prompt-templates.d.ts.map +1 -1
  258. package/dist/core/prompt-templates.js +4 -4
  259. package/dist/core/prompt-templates.js.map +1 -1
  260. package/dist/core/provider-composer.d.ts +1 -1
  261. package/dist/core/provider-composer.d.ts.map +1 -1
  262. package/dist/core/provider-composer.js +8 -1
  263. package/dist/core/provider-composer.js.map +1 -1
  264. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  265. package/dist/core/remote-catalog-provider.js +16 -3
  266. package/dist/core/remote-catalog-provider.js.map +1 -1
  267. package/dist/core/resource-loader.d.ts +6 -0
  268. package/dist/core/resource-loader.d.ts.map +1 -1
  269. package/dist/core/resource-loader.js +27 -2
  270. package/dist/core/resource-loader.js.map +1 -1
  271. package/dist/core/retry-fallback/chains.d.ts +29 -0
  272. package/dist/core/retry-fallback/chains.d.ts.map +1 -0
  273. package/dist/core/retry-fallback/chains.js +109 -0
  274. package/dist/core/retry-fallback/chains.js.map +1 -0
  275. package/dist/core/retry-fallback/controller.d.ts +77 -0
  276. package/dist/core/retry-fallback/controller.d.ts.map +1 -0
  277. package/dist/core/retry-fallback/controller.js +157 -0
  278. package/dist/core/retry-fallback/controller.js.map +1 -0
  279. package/dist/core/retry-fallback/cooldown.d.ts +21 -0
  280. package/dist/core/retry-fallback/cooldown.d.ts.map +1 -0
  281. package/dist/core/retry-fallback/cooldown.js +49 -0
  282. package/dist/core/retry-fallback/cooldown.js.map +1 -0
  283. package/dist/core/retry-fallback/log.d.ts +10 -0
  284. package/dist/core/retry-fallback/log.d.ts.map +1 -0
  285. package/dist/core/retry-fallback/log.js +128 -0
  286. package/dist/core/retry-fallback/log.js.map +1 -0
  287. package/dist/core/retry-fallback/validate.d.ts +8 -0
  288. package/dist/core/retry-fallback/validate.d.ts.map +1 -0
  289. package/dist/core/retry-fallback/validate.js +63 -0
  290. package/dist/core/retry-fallback/validate.js.map +1 -0
  291. package/dist/core/sdk.d.ts.map +1 -1
  292. package/dist/core/sdk.js +1 -0
  293. package/dist/core/sdk.js.map +1 -1
  294. package/dist/core/session-manager.d.ts +6 -1
  295. package/dist/core/session-manager.d.ts.map +1 -1
  296. package/dist/core/session-manager.js +19 -3
  297. package/dist/core/session-manager.js.map +1 -1
  298. package/dist/core/settings-manager.d.ts +21 -0
  299. package/dist/core/settings-manager.d.ts.map +1 -1
  300. package/dist/core/settings-manager.js +100 -1
  301. package/dist/core/settings-manager.js.map +1 -1
  302. package/dist/core/tools/bash.d.ts.map +1 -1
  303. package/dist/core/tools/bash.js +20 -5
  304. package/dist/core/tools/bash.js.map +1 -1
  305. package/dist/core/tools/read.js +1 -1
  306. package/dist/core/tools/read.js.map +1 -1
  307. package/dist/extensions/index.d.ts +3 -0
  308. package/dist/extensions/index.d.ts.map +1 -0
  309. package/dist/extensions/index.js +3 -0
  310. package/dist/extensions/index.js.map +1 -0
  311. package/dist/extensions/llama/client.d.ts +61 -0
  312. package/dist/extensions/llama/client.d.ts.map +1 -0
  313. package/dist/extensions/llama/client.js +298 -0
  314. package/dist/extensions/llama/client.js.map +1 -0
  315. package/dist/extensions/llama/huggingface.d.ts +23 -0
  316. package/dist/extensions/llama/huggingface.d.ts.map +1 -0
  317. package/dist/extensions/llama/huggingface.js +139 -0
  318. package/dist/extensions/llama/huggingface.js.map +1 -0
  319. package/dist/extensions/llama/index.d.ts +3 -0
  320. package/dist/extensions/llama/index.d.ts.map +1 -0
  321. package/dist/extensions/llama/index.js +208 -0
  322. package/dist/extensions/llama/index.js.map +1 -0
  323. package/dist/extensions/llama/provider.d.ts +10 -0
  324. package/dist/extensions/llama/provider.d.ts.map +1 -0
  325. package/dist/extensions/llama/provider.js +106 -0
  326. package/dist/extensions/llama/provider.js.map +1 -0
  327. package/dist/extensions/llama/ui.d.ts +42 -0
  328. package/dist/extensions/llama/ui.d.ts.map +1 -0
  329. package/dist/extensions/llama/ui.js +400 -0
  330. package/dist/extensions/llama/ui.js.map +1 -0
  331. package/dist/index.d.ts +2 -2
  332. package/dist/index.d.ts.map +1 -1
  333. package/dist/index.js.map +1 -1
  334. package/dist/main.d.ts.map +1 -1
  335. package/dist/main.js +6 -4
  336. package/dist/main.js.map +1 -1
  337. package/dist/modes/interactive/components/assistant-message.d.ts +6 -7
  338. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  339. package/dist/modes/interactive/components/assistant-message.js +154 -114
  340. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  341. package/dist/modes/interactive/components/footer.d.ts +2 -1
  342. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  343. package/dist/modes/interactive/components/footer.js +25 -4
  344. package/dist/modes/interactive/components/footer.js.map +1 -1
  345. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  346. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  347. package/dist/modes/interactive/components/settings-selector.js +20 -0
  348. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  349. package/dist/modes/interactive/interactive-mode.d.ts +7 -0
  350. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  351. package/dist/modes/interactive/interactive-mode.js +165 -13
  352. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  353. package/dist/modes/interactive/streaming-reveal.d.ts +35 -0
  354. package/dist/modes/interactive/streaming-reveal.d.ts.map +1 -0
  355. package/dist/modes/interactive/streaming-reveal.js +268 -0
  356. package/dist/modes/interactive/streaming-reveal.js.map +1 -0
  357. package/dist/modes/interactive/tool-args-reveal.d.ts +20 -0
  358. package/dist/modes/interactive/tool-args-reveal.d.ts.map +1 -0
  359. package/dist/modes/interactive/tool-args-reveal.js +153 -0
  360. package/dist/modes/interactive/tool-args-reveal.js.map +1 -0
  361. package/dist/utils/child-process.d.ts +17 -1
  362. package/dist/utils/child-process.d.ts.map +1 -1
  363. package/dist/utils/child-process.js +41 -1
  364. package/dist/utils/child-process.js.map +1 -1
  365. package/docs/AGENTS.md +70 -0
  366. package/docs/custom-provider.md +28 -0
  367. package/docs/extensions.md +111 -5
  368. package/docs/index.md +1 -0
  369. package/docs/llama-cpp.md +99 -0
  370. package/docs/mcp.md +21 -5
  371. package/docs/neo.md +2 -1
  372. package/docs/prompt-templates.md +1 -0
  373. package/docs/providers.md +7 -0
  374. package/docs/settings.md +35 -0
  375. package/docs/tui.md +41 -26
  376. package/docs/usage.md +1 -0
  377. package/examples/AGENTS.md +3 -0
  378. package/examples/extensions/README.md +1 -1
  379. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +74 -0
  380. package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
  381. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +59 -19
  382. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +0 -1
  383. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +69 -2
  384. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +6 -0
  385. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  386. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +95 -12
  387. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  388. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  389. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +26 -1
  390. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  391. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  392. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +24 -2
  393. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  394. package/node_modules/@earendil-works/pi-agent-core/dist/proxy.d.ts +3 -1
  395. package/node_modules/@earendil-works/pi-agent-core/dist/proxy.d.ts.map +1 -1
  396. package/node_modules/@earendil-works/pi-agent-core/dist/proxy.js +4 -2
  397. package/node_modules/@earendil-works/pi-agent-core/dist/proxy.js.map +1 -1
  398. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +5 -0
  399. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
  400. package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
  401. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  402. package/node_modules/@earendil-works/pi-ai/README.md +1 -1
  403. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  404. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +92 -29
  405. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  406. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts +2 -1
  407. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  408. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +25 -1
  409. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  410. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts.map +1 -1
  411. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +105 -61
  412. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
  413. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts +1 -0
  414. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
  415. package/node_modules/@earendil-works/pi-ai/dist/compat.js +1 -0
  416. package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
  417. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +15 -0
  418. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  419. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +15 -0
  420. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  421. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
  422. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  423. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  424. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  425. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +4263 -22314
  426. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  427. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts +436 -1988
  428. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
  429. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js +2 -1892
  430. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js.map +1 -1
  431. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.d.ts +10 -80
  432. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.d.ts.map +1 -1
  433. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.js +2 -57
  434. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.js.map +1 -1
  435. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts +43 -267
  436. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts.map +1 -1
  437. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js +2 -252
  438. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js.map +1 -1
  439. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.d.ts +184 -883
  440. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.d.ts.map +1 -1
  441. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.js +2 -811
  442. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.js.map +1 -1
  443. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts +10 -60
  444. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts.map +1 -1
  445. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js +2 -56
  446. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js.map +1 -1
  447. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts +168 -884
  448. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
  449. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js +2 -755
  450. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
  451. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.d.ts +40 -286
  452. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -1
  453. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.js +2 -236
  454. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.js.map +1 -1
  455. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -0
  456. package/node_modules/@earendil-works/pi-ai/dist/providers/data/ant-ling.json +1 -0
  457. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -0
  458. package/node_modules/@earendil-works/pi-ai/dist/providers/data/azure-openai-responses.json +1 -0
  459. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cerebras.json +1 -0
  460. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -0
  461. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -0
  462. package/node_modules/@earendil-works/pi-ai/dist/providers/data/deepseek.json +1 -0
  463. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -0
  464. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -0
  465. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google-vertex.json +1 -0
  466. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -0
  467. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -0
  468. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -0
  469. package/node_modules/@earendil-works/pi-ai/dist/providers/data/kimi-coding.json +1 -0
  470. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax-cn.json +1 -0
  471. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax.json +1 -0
  472. package/node_modules/@earendil-works/pi-ai/dist/providers/data/mistral.json +1 -0
  473. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai-cn.json +1 -0
  474. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai.json +1 -0
  475. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -0
  476. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -0
  477. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -0
  478. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -0
  479. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -0
  480. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -0
  481. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -0
  482. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -0
  483. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xai.json +1 -0
  484. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-ams.json +1 -0
  485. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-cn.json +1 -0
  486. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-sgp.json +1 -0
  487. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi.json +1 -0
  488. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -0
  489. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -0
  490. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.d.ts +7 -58
  491. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.d.ts.map +1 -1
  492. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.js +2 -40
  493. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.js.map +1 -1
  494. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts +1 -0
  495. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts.map +1 -1
  496. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js +1 -0
  497. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js.map +1 -1
  498. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts +49 -362
  499. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts.map +1 -1
  500. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js +2 -292
  501. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js.map +1 -1
  502. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts +85 -760
  503. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts.map +1 -1
  504. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js +2 -538
  505. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js.map +1 -1
  506. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.d.ts +31 -189
  507. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.d.ts.map +1 -1
  508. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.js +2 -179
  509. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.js.map +1 -1
  510. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.d.ts +49 -309
  511. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.d.ts.map +1 -1
  512. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.js +2 -285
  513. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.js.map +1 -1
  514. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.d.ts +22 -118
  515. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.d.ts.map +1 -1
  516. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.js +2 -122
  517. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.js.map +1 -1
  518. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.d.ts +196 -979
  519. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.d.ts.map +1 -1
  520. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.js +2 -884
  521. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.js.map +1 -1
  522. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts +13 -122
  523. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts.map +1 -1
  524. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js +2 -98
  525. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js.map +1 -1
  526. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.d.ts +10 -48
  527. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.d.ts.map +1 -1
  528. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.js +2 -53
  529. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.js.map +1 -1
  530. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.d.ts +10 -48
  531. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.d.ts.map +1 -1
  532. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.js +2 -53
  533. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.js.map +1 -1
  534. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts +91 -480
  535. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts.map +1 -1
  536. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js +2 -512
  537. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js.map +1 -1
  538. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts +31 -257
  539. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
  540. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js +2 -185
  541. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js.map +1 -1
  542. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts +31 -257
  543. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts.map +1 -1
  544. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js +2 -185
  545. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js.map +1 -1
  546. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts +58 -541
  547. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts.map +1 -1
  548. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js +2 -382
  549. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js.map +1 -1
  550. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.d.ts +22 -196
  551. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.d.ts.map +1 -1
  552. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.js +2 -139
  553. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.js.map +1 -1
  554. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.d.ts +184 -954
  555. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.d.ts.map +1 -1
  556. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.js +2 -825
  557. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.js.map +1 -1
  558. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.d.ts +1 -1
  559. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.d.ts.map +1 -1
  560. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.js +2 -0
  561. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.js.map +1 -1
  562. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts +46 -335
  563. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts.map +1 -1
  564. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js +2 -273
  565. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js.map +1 -1
  566. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts +163 -1185
  567. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts.map +1 -1
  568. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js +2 -996
  569. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js.map +1 -1
  570. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +1076 -5750
  571. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
  572. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +2 -4910
  573. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
  574. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.d.ts +49 -579
  575. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.d.ts.map +1 -1
  576. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js +2 -377
  577. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js.map +1 -1
  578. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +752 -3336
  579. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
  580. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +2 -3263
  581. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
  582. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts +10 -65
  583. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts.map +1 -1
  584. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js +2 -57
  585. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js.map +1 -1
  586. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.d.ts +10 -63
  587. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -1
  588. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.js +2 -56
  589. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -1
  590. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.d.ts +10 -63
  591. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -1
  592. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.js +2 -56
  593. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -1
  594. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.d.ts +10 -63
  595. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -1
  596. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.js +2 -56
  597. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -1
  598. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.d.ts +19 -126
  599. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.d.ts.map +1 -1
  600. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.js +2 -110
  601. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.js.map +1 -1
  602. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.d.ts +19 -144
  603. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.d.ts.map +1 -1
  604. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.js +2 -111
  605. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.js.map +1 -1
  606. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.d.ts +19 -144
  607. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.d.ts.map +1 -1
  608. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.js +2 -111
  609. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.js.map +1 -1
  610. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.d.ts.map +1 -1
  611. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.js +12 -0
  612. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.js.map +1 -1
  613. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts +1 -1
  614. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts.map +1 -1
  615. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +4 -2
  616. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
  617. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts +1 -0
  618. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts.map +1 -1
  619. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js +1 -1
  620. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js.map +1 -1
  621. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts +1 -0
  622. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts.map +1 -1
  623. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.js +1 -1
  624. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.js.map +1 -1
  625. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.d.ts +19 -0
  626. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.d.ts.map +1 -0
  627. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.js +8 -0
  628. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.js.map +1 -0
  629. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts +11 -0
  630. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts.map +1 -1
  631. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js +40 -1
  632. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js.map +1 -1
  633. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts +2 -0
  634. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts.map +1 -1
  635. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.js +7 -4
  636. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.js.map +1 -1
  637. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts +2 -0
  638. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts.map +1 -1
  639. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js +104 -15
  640. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js.map +1 -1
  641. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.d.ts +15 -0
  642. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.d.ts.map +1 -0
  643. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.js +198 -0
  644. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.js.map +1 -0
  645. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.d.ts +3 -0
  646. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.d.ts.map +1 -0
  647. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.js +8 -0
  648. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.js.map +1 -0
  649. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.d.ts +6 -0
  650. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.d.ts.map +1 -0
  651. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.js +33 -0
  652. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.js.map +1 -0
  653. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.d.ts +6 -0
  654. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.d.ts.map +1 -0
  655. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.js +6 -0
  656. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.js.map +1 -0
  657. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.d.ts +4 -0
  658. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.d.ts.map +1 -0
  659. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.js +6 -0
  660. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.js.map +1 -0
  661. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.d.ts +12 -0
  662. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.d.ts.map +1 -0
  663. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.js +46 -0
  664. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.js.map +1 -0
  665. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.d.ts +4 -0
  666. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.d.ts.map +1 -0
  667. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.js +6 -0
  668. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.js.map +1 -0
  669. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/gemma4.d.ts +8 -1
  670. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/gemma4.d.ts.map +1 -1
  671. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/gemma4.js +129 -27
  672. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/gemma4.js.map +1 -1
  673. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/json-mix.d.ts.map +1 -1
  674. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/json-mix.js +140 -6
  675. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/json-mix.js.map +1 -1
  676. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/morph-xml.d.ts.map +1 -1
  677. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/morph-xml.js +28 -6
  678. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/morph-xml.js.map +1 -1
  679. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/yaml-xml.d.ts.map +1 -1
  680. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/yaml-xml.js +51 -18
  681. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/yaml-xml.js.map +1 -1
  682. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.d.ts.map +1 -1
  683. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.js +70 -9
  684. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.js.map +1 -1
  685. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.d.ts +6 -2
  686. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.d.ts.map +1 -1
  687. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.js.map +1 -1
  688. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +31 -3
  689. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  690. package/node_modules/@earendil-works/pi-ai/dist/types.js +4 -1
  691. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  692. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  693. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +6 -1
  694. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  695. package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.d.ts +4 -0
  696. package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.d.ts.map +1 -0
  697. package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.js +6 -0
  698. package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.js.map +1 -0
  699. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-pair-repair.d.ts.map +1 -1
  700. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-pair-repair.js +19 -2
  701. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-pair-repair.js.map +1 -1
  702. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.d.ts +19 -0
  703. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.d.ts.map +1 -0
  704. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.js +215 -0
  705. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.js.map +1 -0
  706. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  707. package/node_modules/@earendil-works/pi-pty/dist/registry-session.d.ts +1 -1
  708. package/node_modules/@earendil-works/pi-pty/dist/registry-session.d.ts.map +1 -1
  709. package/node_modules/@earendil-works/pi-pty/dist/registry-session.js +25 -6
  710. package/node_modules/@earendil-works/pi-pty/dist/registry-session.js.map +1 -1
  711. package/node_modules/@earendil-works/pi-pty/dist/registry-types.d.ts +6 -0
  712. package/node_modules/@earendil-works/pi-pty/dist/registry-types.d.ts.map +1 -1
  713. package/node_modules/@earendil-works/pi-pty/dist/registry-types.js.map +1 -1
  714. package/node_modules/@earendil-works/pi-pty/dist/registry.d.ts +1 -0
  715. package/node_modules/@earendil-works/pi-pty/dist/registry.d.ts.map +1 -1
  716. package/node_modules/@earendil-works/pi-pty/dist/registry.js +9 -1
  717. package/node_modules/@earendil-works/pi-pty/dist/registry.js.map +1 -1
  718. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  719. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
  720. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  721. package/node_modules/@earendil-works/pi-tui/dist/index.js +1 -1
  722. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  723. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +6 -1
  724. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
  725. package/node_modules/@earendil-works/pi-tui/dist/tui.js +14 -2
  726. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
  727. package/node_modules/@earendil-works/pi-tui/dist/utils.js +1 -1
  728. package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
  729. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  730. package/package.json +6 -6
  731. package/dist/core/extensions/builtin/todotools/tools/todoread.d.ts +0 -4
  732. package/dist/core/extensions/builtin/todotools/tools/todoread.d.ts.map +0 -1
  733. package/dist/core/extensions/builtin/todotools/tools/todoread.js +0 -37
  734. package/dist/core/extensions/builtin/todotools/tools/todoread.js.map +0 -1
  735. package/dist/core/extensions/builtin/todotools/tools/todowrite.d.ts +0 -10
  736. package/dist/core/extensions/builtin/todotools/tools/todowrite.d.ts.map +0 -1
  737. package/dist/core/extensions/builtin/todotools/tools/todowrite.js +0 -95
  738. package/dist/core/extensions/builtin/todotools/tools/todowrite.js.map +0 -1
@@ -16,7 +16,8 @@ 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 { prepareAgentToolCall } from "@earendil-works/pi-agent-core";
19
- import { cleanupSessionResources, isContextOverflow, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
19
+ import { cleanupSessionResources, isClassifierRefusal, isContextOverflow, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
20
+ import { getAgentDir } from "../config.js";
20
21
  import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
21
22
  import { stripFrontmatter } from "../utils/frontmatter.js";
22
23
  import { resolvePath } from "../utils/paths.js";
@@ -34,6 +35,10 @@ import { filterContextExcludedMessages } from "./messages.js";
34
35
  import { ModelRegistry } from "./model-registry.js";
35
36
  import { getModelNarrowingPatterns, resolveModelScope } from "./model-resolver.js";
36
37
  import { expandPromptTemplate } from "./prompt-templates.js";
38
+ import { RetryFallbackController } from "./retry-fallback/controller.js";
39
+ import { SelectorCooldowns } from "./retry-fallback/cooldown.js";
40
+ import { createFallbackLogger } from "./retry-fallback/log.js";
41
+ import { validateFallbackChains } from "./retry-fallback/validate.js";
37
42
  import { buildSessionContext, CURRENT_SESSION_VERSION, getLatestCompactionEntry, } from "./session-manager.js";
38
43
  import { generateSessionTitle, shouldSkipSessionTitle } from "./session-title-generator.js";
39
44
  import { SessionWorkBarrier } from "./session-work-barrier.js";
@@ -65,13 +70,39 @@ function withoutDeletedHeaders(headers) {
65
70
  ? Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] !== null))
66
71
  : undefined;
67
72
  }
73
+ /**
74
+ * Human-readable rejection message paired with a `CompactionRejectionCause`.
75
+ *
76
+ * Kept exhaustive over the union so the compiler flags any new cause that would
77
+ * otherwise reintroduce silent failures at the `compaction_end` UI seam.
78
+ */
79
+ function describeCompactionRejection(cause) {
80
+ switch (cause) {
81
+ case "would-overflow":
82
+ return "Compaction rejected: the produced summary would still overflow the model context window. Reduce context (e.g. /new, drop attachments) or switch to a larger-context model.";
83
+ case "cancelled-by-extension":
84
+ return "Compaction rejected: cancelled by an extension.";
85
+ case "circuit-breaker":
86
+ return "Compaction rejected: the compaction circuit breaker is open after repeated failures. Wait for the cooldown and retry.";
87
+ case "per-turn-cap":
88
+ return "Compaction rejected: per-turn compaction cap reached for this turn.";
89
+ }
90
+ }
68
91
  class CompactionRejectedError extends Error {
69
92
  constructor(rejectionCause) {
70
- super(rejectionCause === "cancelled-by-extension" ? "Compaction cancelled" : "Compaction rejected");
93
+ super(rejectionCause === "cancelled-by-extension"
94
+ ? "Compaction cancelled"
95
+ : describeCompactionRejection(rejectionCause));
71
96
  this.name = "CompactionRejectedError";
72
97
  this.rejectionCause = rejectionCause;
73
98
  }
74
99
  }
100
+ class RequiredCompactionError extends Error {
101
+ constructor() {
102
+ super("Context remains above the compaction threshold because compaction did not complete");
103
+ this.name = "RequiredCompactionError";
104
+ }
105
+ }
75
106
  class MissingModelAccessError extends Error {
76
107
  constructor() {
77
108
  super("AgentSession requires modelRuntime or modelRegistry");
@@ -127,6 +158,7 @@ export class AgentSession {
127
158
  this._retryPromise = undefined;
128
159
  this._retryResolve = undefined;
129
160
  this._userAbortPromise = undefined;
161
+ this._suppressQueuedContinuationAfterUserAbort = false;
130
162
  // Bash execution state
131
163
  this._bashAbortController = undefined;
132
164
  this._pendingBashMessages = [];
@@ -158,6 +190,11 @@ export class AgentSession {
158
190
  this.agent = config.agent;
159
191
  this.sessionManager = config.sessionManager;
160
192
  this.settingsManager = config.settingsManager;
193
+ const noModelFallback = config.resourceLoader.getExtensions().runtime.flagValues.get("no-model-fallback") === true ||
194
+ process.env.SENPI_NO_FALLBACK === "1";
195
+ if (noModelFallback) {
196
+ this.settingsManager.applyOverrides({ retry: { modelFallback: false } });
197
+ }
161
198
  this._scopedModels = config.scopedModels ?? [];
162
199
  this._favoriteModels = config.favoriteModels ?? [];
163
200
  this._resourceLoader = config.resourceLoader;
@@ -169,6 +206,30 @@ export class AgentSession {
169
206
  }
170
207
  this._modelRuntime = modelRuntime;
171
208
  this._modelRegistry = config.modelRegistry ?? new ModelRegistry(modelRuntime);
209
+ const fallbackLogger = createFallbackLogger(config.agentDir ?? getAgentDir());
210
+ this._fallbackValidationWarnings = validateFallbackChains(this.settingsManager.getRawFallbackChains(), this._modelRegistry);
211
+ for (const warning of this._fallbackValidationWarnings) {
212
+ fallbackLogger.warn("validation_warning", { warning });
213
+ }
214
+ this._retryFallback = new RetryFallbackController({
215
+ getSettings: () => this.settingsManager.getRetryFallbackSettings(),
216
+ registry: this._modelRegistry,
217
+ cooldowns: new SelectorCooldowns(config.fallbackNow ?? (() => Date.now())),
218
+ logger: fallbackLogger,
219
+ switchModel: async (model, thinking, reason) => {
220
+ await this._switchActiveModel(model, {
221
+ persistDefault: false,
222
+ appendSessionEntry: true,
223
+ entryReason: reason,
224
+ emitModelSelect: reason === "fallback-revert",
225
+ invalidateCompaction: false,
226
+ ephemeralThinkingLevel: thinking,
227
+ });
228
+ },
229
+ emit: (event) => this._emit(event),
230
+ getCurrentSelector: () => (this.model ? { model: this.model, thinkingLevel: this.thinkingLevel } : undefined),
231
+ isAuthAvailable: (provider) => this._modelRuntime.hasConfiguredAuth(provider),
232
+ });
172
233
  this._extensionRunnerRef = config.extensionRunnerRef;
173
234
  this._initialActiveToolNames = config.initialActiveToolNames;
174
235
  this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
@@ -179,7 +240,7 @@ export class AgentSession {
179
240
  const initialModel = this.agent.state.model;
180
241
  if (initialModel) {
181
242
  const scopedMatch = this._scopedModels.find((sm) => modelsAreEqual(sm.model, initialModel));
182
- this._currentServiceTier = scopedMatch?.serviceTier;
243
+ this._currentServiceTier = this._resolveServiceTier(initialModel, scopedMatch?.serviceTier);
183
244
  }
184
245
  this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
185
246
  this._installAgentToolHooks();
@@ -309,8 +370,27 @@ export class AgentSession {
309
370
  ? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
310
371
  : undefined);
311
372
  this.agent.prepareNextTurnWithContext = async (turn, signal) => {
312
- const previousSnapshot = await previousPrepareNextTurnWithContext?.(turn, signal);
313
- const previousContext = previousSnapshot?.context ?? turn.context;
373
+ let messages = turn.context.messages;
374
+ if (turn.toolResults.length > 0) {
375
+ await this._agentEventQueue;
376
+ const compacted = await this._checkCompaction(turn.message, true, "threshold");
377
+ if (compacted) {
378
+ messages = this.agent.state.messages.slice();
379
+ }
380
+ else {
381
+ const settings = this.settingsManager.getCompactionSettings();
382
+ const contextTokens = estimateContextTokens(filterContextExcludedMessages(this.sessionManager.buildSessionContext().messages)).tokens;
383
+ if (settings.enabled && this.model && shouldCompact(contextTokens, this.model.contextWindow, settings)) {
384
+ throw new RequiredCompactionError();
385
+ }
386
+ }
387
+ }
388
+ const postCompactionTurn = {
389
+ ...turn,
390
+ context: { ...turn.context, messages },
391
+ };
392
+ const previousSnapshot = await previousPrepareNextTurnWithContext?.(postCompactionTurn, signal);
393
+ const previousContext = previousSnapshot?.context ?? postCompactionTurn.context;
314
394
  return {
315
395
  ...previousSnapshot,
316
396
  context: {
@@ -359,7 +439,9 @@ export class AgentSession {
359
439
  _modelSelectionChangesContext(previousModel, nextModel) {
360
440
  if (!modelsAreEqual(previousModel, nextModel))
361
441
  return true;
362
- return previousModel?.contextWindow !== nextModel.contextWindow;
442
+ if (previousModel?.contextWindow !== nextModel.contextWindow)
443
+ return true;
444
+ return previousModel?.api !== nextModel.api;
363
445
  }
364
446
  _invalidateCompactionForModelSelection() {
365
447
  this.abortCompaction();
@@ -416,7 +498,8 @@ export class AgentSession {
416
498
  return;
417
499
  }
418
500
  const lastAssistant = this._findLastAssistantInMessages(event.messages);
419
- if (!lastAssistant || !this._isRetryableError(lastAssistant)) {
501
+ if (!lastAssistant ||
502
+ (!this._isRetryableError(lastAssistant) && !this._isHardErrorFallbackEligible(lastAssistant))) {
420
503
  return;
421
504
  }
422
505
  this._retryPromise = new Promise((resolve) => {
@@ -466,12 +549,22 @@ export class AgentSession {
466
549
  return false;
467
550
  }
468
551
  const lastAssistant = this._lastAssistantMessage ?? this._findLastAssistantInMessages(messages);
469
- if (!lastAssistant || !this._isRetryableError(lastAssistant)) {
552
+ if (!lastAssistant) {
470
553
  return false;
471
554
  }
472
- if (this._retryAttempt + 1 > settings.maxRetries) {
555
+ const retryableError = this._isRetryableError(lastAssistant);
556
+ if (!retryableError && this._isHardErrorFallbackEligible(lastAssistant)) {
557
+ return true;
558
+ }
559
+ if (!retryableError) {
473
560
  return false;
474
561
  }
562
+ if (isClassifierRefusal(lastAssistant)) {
563
+ return this._retryAttempt + 1 <= settings.maxRetries && this._retryFallback.canTryFallback();
564
+ }
565
+ if (this._retryAttempt + 1 > settings.maxRetries) {
566
+ return this._retryFallback.canTryFallback();
567
+ }
475
568
  const errorMessage = lastAssistant.errorMessage || "Unknown error";
476
569
  const providerDelayMs = this._getProviderRetryDelayMs(errorMessage);
477
570
  if (providerDelayMs === undefined) {
@@ -484,6 +577,7 @@ export class AgentSession {
484
577
  // This ensures the UI sees the updated queue state
485
578
  if (event.type === "message_start" && event.message.role === "user") {
486
579
  this._overflowRecoveryAttempted = false;
580
+ this._retryFallback.resetTurn();
487
581
  const messageText = this._getUserMessageText(event.message);
488
582
  if (messageText) {
489
583
  // Check steering queue first
@@ -532,6 +626,14 @@ export class AgentSession {
532
626
  // Reset retry counter immediately on successful assistant response
533
627
  // This prevents accumulation across multiple LLM calls within a turn
534
628
  if (assistantMsg.stopReason !== "error" && this._retryAttempt > 0) {
629
+ const fallback = this._retryFallback.activeState;
630
+ if (fallback) {
631
+ this._emit({
632
+ type: "retry_fallback_succeeded",
633
+ model: this.model ? `${this.model.provider}/${this.model.id}` : "",
634
+ chainKey: fallback.chainKey,
635
+ });
636
+ }
535
637
  this._emit({
536
638
  type: "auto_retry_end",
537
639
  success: true,
@@ -543,16 +645,27 @@ export class AgentSession {
543
645
  }
544
646
  // Check auto-retry and auto-compaction after agent completes
545
647
  let launchedContinuation = false;
546
- const allowsQueuedContinuation = event.type === "agent_end" ? this._agentEndAllowsQueuedContinuation(event.messages) : false;
648
+ const userAbortSuppressedQueuedContinuation = event.type === "agent_end" && this._suppressQueuedContinuationAfterUserAbort;
649
+ if (userAbortSuppressedQueuedContinuation) {
650
+ this._suppressQueuedContinuationAfterUserAbort = false;
651
+ }
652
+ const allowsQueuedContinuation = event.type === "agent_end" && !userAbortSuppressedQueuedContinuation
653
+ ? this._agentEndAllowsQueuedContinuation(event.messages)
654
+ : false;
547
655
  if (event.type === "agent_end" && this._lastAssistantMessage) {
548
656
  const msg = this._lastAssistantMessage;
549
657
  this._lastAssistantMessage = undefined;
550
- // Check for retryable errors first (overloaded, rate limit, server errors)
551
- if (this._isRetryableError(msg)) {
552
- const didRetry = await this._handleRetryableError(msg);
553
- if (didRetry)
554
- return; // Retry was initiated, don't proceed to compaction
658
+ // Retry transient failures normally and eligible hard errors only through a fallback.
659
+ const retryableError = this._isRetryableError(msg);
660
+ let didRetry = false;
661
+ if (retryableError) {
662
+ didRetry = await this._handleRetryableError(msg);
663
+ }
664
+ else if (this._isHardErrorFallbackEligible(msg)) {
665
+ didRetry = await this._handleRetryableError(msg, { hardErrorFallback: true });
555
666
  }
667
+ if (didRetry)
668
+ return; // Retry was initiated, don't proceed to compaction
556
669
  this._resolveRetry();
557
670
  launchedContinuation = await this._checkCompaction(msg);
558
671
  }
@@ -596,6 +709,10 @@ export class AgentSession {
596
709
  }
597
710
  return undefined;
598
711
  }
712
+ _isAssistantFromBeforeLatestCompaction(assistantMessage) {
713
+ const compactionEntry = getLatestCompactionEntry(this.sessionManager.getBranch());
714
+ return compactionEntry !== null && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime();
715
+ }
599
716
  _replaceMessageInPlace(target, replacement) {
600
717
  // Agent-core stores the finalized message object in its state before emitting message_end.
601
718
  // SessionManager persistence happens later in _processAgentEvent() with event.message.
@@ -774,6 +891,17 @@ export class AgentSession {
774
891
  get serviceTier() {
775
892
  return this._currentServiceTier;
776
893
  }
894
+ /**
895
+ * Explicit scoped/favorite tiers win; otherwise fall back to the model's
896
+ * configured serviceTier from models.json/extension compatibility config.
897
+ */
898
+ _resolveServiceTier(model, explicit) {
899
+ if (explicit)
900
+ return explicit;
901
+ if (!model)
902
+ return undefined;
903
+ return this._modelRuntime.getCompatibilityRequestConfig(model).serviceTier;
904
+ }
777
905
  /** Whether the session is currently processing an agent run or post-run continuation. */
778
906
  get isStreaming() {
779
907
  return this._isAgentRunActive;
@@ -996,6 +1124,8 @@ export class AgentSession {
996
1124
  }
997
1125
  const loadedSkills = this._resourceLoader.getSkills().skills;
998
1126
  const loadedContextFiles = this._resourceLoader.getAgentsFiles().agentsFiles;
1127
+ const loaderSystemPrompt = this._resourceLoader.getSystemPrompt();
1128
+ const loaderAppendSystemPrompt = this._resourceLoader.getAppendSystemPrompt();
999
1129
  this._baseSystemPromptOptions = {
1000
1130
  cwd: this._cwd,
1001
1131
  skills: loadedSkills,
@@ -1004,7 +1134,10 @@ export class AgentSession {
1004
1134
  toolSnippets,
1005
1135
  promptGuidelines,
1006
1136
  };
1007
- return buildDynamicSystemPrompt(this._baseSystemPromptOptions);
1137
+ const basePrompt = loaderSystemPrompt ?? buildDynamicSystemPrompt(this._baseSystemPromptOptions);
1138
+ return loaderAppendSystemPrompt.length > 0
1139
+ ? `${basePrompt}\n\n${loaderAppendSystemPrompt.join("\n\n")}`
1140
+ : basePrompt;
1008
1141
  }
1009
1142
  /**
1010
1143
  * Send a prompt to the agent.
@@ -1035,6 +1168,10 @@ export class AgentSession {
1035
1168
  await this._waitForSettledSessionWork();
1036
1169
  throwIfCancelled();
1037
1170
  }
1171
+ // Turn boundary: restore the primary model if the fallback cooldown expired.
1172
+ if (!this.isStreaming) {
1173
+ await this._maybeRestoreFallbackPrimary();
1174
+ }
1038
1175
  const expandPromptTemplates = options?.expandPromptTemplates ?? true;
1039
1176
  const preflightResult = options?.preflightResult;
1040
1177
  const promptDisposition = options?.promptDisposition;
@@ -1112,7 +1249,14 @@ export class AgentSession {
1112
1249
  // The user's new prompt is sent below, so do not call agent.continue() here.
1113
1250
  const lastAssistant = this._findLastAssistantMessage();
1114
1251
  if (lastAssistant) {
1115
- await this._checkCompaction(lastAssistant, false, "pre_prompt");
1252
+ const compacted = await this._checkCompaction(lastAssistant, false, "pre_prompt");
1253
+ if (!compacted && !this._isAssistantFromBeforeLatestCompaction(lastAssistant)) {
1254
+ const settings = this.settingsManager.getCompactionSettings();
1255
+ const contextTokens = estimateContextTokens(filterContextExcludedMessages(this.sessionManager.buildSessionContext().messages)).tokens;
1256
+ if (settings.enabled && this.model && shouldCompact(contextTokens, this.model.contextWindow, settings)) {
1257
+ throw new RequiredCompactionError();
1258
+ }
1259
+ }
1116
1260
  }
1117
1261
  // Build messages array (custom message if any, then user message)
1118
1262
  messages = [];
@@ -1507,6 +1651,9 @@ export class AgentSession {
1507
1651
  await this._userAbortPromise;
1508
1652
  return;
1509
1653
  }
1654
+ if (this.isStreaming) {
1655
+ this._suppressQueuedContinuationAfterUserAbort = true;
1656
+ }
1510
1657
  const abortPromise = (async () => {
1511
1658
  this.agent.abort();
1512
1659
  await this.waitForIdle();
@@ -1574,20 +1721,57 @@ export class AgentSession {
1574
1721
  if (!(await this._modelRuntime.checkAuth(model.provider))) {
1575
1722
  throw new Error(`No API key for ${model.provider}/${model.id}`);
1576
1723
  }
1724
+ // A manual model change abandons any active fallback window; if a fallback
1725
+ // retry sleep is still pending, cancel it so no surprise continuation fires.
1726
+ const hadActiveFallback = this._retryFallback.activeState !== undefined;
1727
+ this._retryFallback.clearForManualModelChange(model);
1728
+ if (hadActiveFallback && this._retryAbortController) {
1729
+ this.abortRetry();
1730
+ }
1731
+ return await this._switchActiveModel(model, {
1732
+ persistDefault: true,
1733
+ appendSessionEntry: true,
1734
+ emitModelSelect: true,
1735
+ invalidateCompaction: true,
1736
+ });
1737
+ }
1738
+ async _maybeRestoreFallbackPrimary() {
1739
+ try {
1740
+ await this._retryFallback.maybeRestorePrimary(this.settingsManager.getRetryFallbackSettings().revertPolicy);
1741
+ }
1742
+ catch (error) {
1743
+ this._retryFallback.clear();
1744
+ console.error("fallback revert failed; cleared fallback state", error);
1745
+ }
1746
+ }
1747
+ async _switchActiveModel(model, opts) {
1577
1748
  const previousModel = this.model;
1578
- const invalidatesCompaction = this._modelSelectionChangesContext(previousModel, model);
1579
- if (invalidatesCompaction) {
1749
+ if (opts.invalidateCompaction && this._modelSelectionChangesContext(previousModel, model)) {
1580
1750
  this._invalidateCompactionForModelSelection();
1581
1751
  }
1582
- const thinkingLevel = this._getThinkingLevelForModelSwitch();
1752
+ const thinkingLevel = this._getThinkingLevelForModelSwitch(opts.ephemeralThinkingLevel);
1583
1753
  this.agent.state.model = model;
1584
- this.sessionManager.appendModelChange(model.provider, model.id);
1585
- this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
1754
+ if (opts.appendSessionEntry) {
1755
+ this.sessionManager.appendModelChange(model.provider, model.id, opts.entryReason, previousModel?.provider, previousModel?.id);
1756
+ }
1757
+ if (opts.persistDefault) {
1758
+ this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
1759
+ }
1586
1760
  const scopedMatch = this._scopedModels.find((sm) => modelsAreEqual(sm.model, model));
1587
- this._currentServiceTier = scopedMatch?.serviceTier;
1588
- this.setThinkingLevel(thinkingLevel);
1761
+ this._currentServiceTier = this._resolveServiceTier(model, scopedMatch?.serviceTier);
1762
+ if (opts.ephemeralThinkingLevel !== undefined) {
1763
+ this._applyEphemeralThinkingLevel(thinkingLevel);
1764
+ }
1765
+ else {
1766
+ this.setThinkingLevel(thinkingLevel);
1767
+ }
1768
+ if (!opts.emitModelSelect)
1769
+ return undefined;
1589
1770
  return await this._emitModelSelect(model, previousModel, "set");
1590
1771
  }
1772
+ _applyEphemeralThinkingLevel(level) {
1773
+ this.agent.state.thinkingLevel = level;
1774
+ }
1591
1775
  /**
1592
1776
  * Cycle to next/previous model.
1593
1777
  * Uses favorite models, constrained by any global model narrowing.
@@ -1619,11 +1803,12 @@ export class AgentSession {
1619
1803
  if (invalidatesCompaction) {
1620
1804
  this._invalidateCompactionForModelSelection();
1621
1805
  }
1806
+ this._retryFallback.clearForManualModelChange(next.model);
1622
1807
  const thinkingLevel = this._getThinkingLevelForModelSwitch(next.thinkingLevel);
1623
1808
  this.agent.state.model = next.model;
1624
1809
  this.sessionManager.appendModelChange(next.model.provider, next.model.id);
1625
1810
  this.settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);
1626
- this._currentServiceTier = next.serviceTier;
1811
+ this._currentServiceTier = this._resolveServiceTier(next.model, next.serviceTier);
1627
1812
  // Apply thinking level.
1628
1813
  // - Explicit favorite model thinking level overrides current session level
1629
1814
  // - Undefined favorite model thinking level inherits the current session preference
@@ -1650,6 +1835,9 @@ export class AgentSession {
1650
1835
  // Only persist if actually changing
1651
1836
  const previousLevel = this.agent.state.thinkingLevel;
1652
1837
  const isChanging = effectiveLevel !== previousLevel;
1838
+ if (isChanging) {
1839
+ this._retryFallback.noteManualThinkingLevel();
1840
+ }
1653
1841
  this.agent.state.thinkingLevel = effectiveLevel;
1654
1842
  if (isChanging) {
1655
1843
  this.sessionManager.appendThinkingLevelChange(effectiveLevel);
@@ -1901,7 +2089,7 @@ export class AgentSession {
1901
2089
  signal,
1902
2090
  }));
1903
2091
  if (extensionResult?.cancel) {
1904
- return await this._rejectCompaction(request, requestId, "cancelled-by-extension", true);
2092
+ return await this._rejectCompaction(request, requestId, extensionResult.rejectionCause ?? "cancelled-by-extension", true, extensionResult.reason);
1905
2093
  }
1906
2094
  if (extensionResult?.compaction) {
1907
2095
  compactionResult = extensionResult.compaction;
@@ -1910,7 +2098,7 @@ export class AgentSession {
1910
2098
  }
1911
2099
  if (!compactionResult) {
1912
2100
  const { apiKey, headers, extraBody, env } = await this._getCompactionRequestAuth(this.model);
1913
- compactionResult = await compact(preparation, this.model, apiKey, headers, request.customInstructions, signal, extraBody, this.thinkingLevel, this.agent.streamFn, env);
2101
+ compactionResult = await compact(preparation, this.model, apiKey, headers, request.customInstructions, signal, extraBody, this.thinkingLevel, this.agent.streamFn, env, this.agent.transformContext);
1914
2102
  }
1915
2103
  }
1916
2104
  if (signal.aborted) {
@@ -1973,11 +2161,22 @@ export class AgentSession {
1973
2161
  fromHook: fromExtension,
1974
2162
  };
1975
2163
  const simulatedMessages = buildSessionContext([...pathEntries, simulatedCompactionEntry], simulatedCompactionEntry.id).messages;
1976
- const contextTokens = estimateContextTokens(filterContextExcludedMessages(simulatedMessages)).tokens;
2164
+ const contextTokens = estimateMessagesTokens(filterContextExcludedMessages(simulatedMessages));
1977
2165
  const settings = this.settingsManager.getCompactionSettings();
1978
2166
  return contextTokens > this.model.contextWindow - settings.reserveTokens;
1979
2167
  }
1980
- async _rejectCompaction(request, requestId, rejectionCause, aborted) {
2168
+ async _rejectCompaction(request, requestId, rejectionCause, aborted, extensionReason) {
2169
+ // Per plan Section 1: rejection must never be silent. The compaction_end event
2170
+ // carries a non-empty human-readable errorMessage (unless the user aborted, where
2171
+ // the aborted branch already renders "Compaction cancelled"). session_compact is
2172
+ // also emitted with accepted:false so the compaction extension's circuit-breaker
2173
+ // bookkeeping stops being dead code; other builtin session_compact handlers guard
2174
+ // on event.accepted.
2175
+ const trimmedExtensionReason = extensionReason?.trim();
2176
+ const detailedMessage = trimmedExtensionReason
2177
+ ? `Compaction rejected: ${trimmedExtensionReason}`
2178
+ : describeCompactionRejection(rejectionCause);
2179
+ const errorMessage = aborted && !trimmedExtensionReason ? undefined : detailedMessage;
1981
2180
  this._emit({
1982
2181
  type: "compaction_end",
1983
2182
  reason: request.reason,
@@ -1987,6 +2186,16 @@ export class AgentSession {
1987
2186
  requestId,
1988
2187
  accepted: false,
1989
2188
  rejectionCause,
2189
+ errorMessage,
2190
+ });
2191
+ await this._extensionRunner.emit({
2192
+ type: "session_compact",
2193
+ reason: request.reason,
2194
+ requestId,
2195
+ accepted: false,
2196
+ rejectionCause,
2197
+ fromExtension: false,
2198
+ willRetry: false,
1990
2199
  });
1991
2200
  return { accepted: false, requestId, rejectionCause };
1992
2201
  }
@@ -2014,7 +2223,7 @@ export class AgentSession {
2014
2223
  * @param assistantMessage The assistant message to check
2015
2224
  * @param skipAbortedCheck If false, include aborted messages (for pre-prompt check). Default: true
2016
2225
  */
2017
- async _checkCompaction(assistantMessage, skipAbortedCheck = true, requestReason) {
2226
+ async _checkCompaction(assistantMessage, skipAbortedCheck = true, inlineReason) {
2018
2227
  const settings = this.settingsManager.getCompactionSettings();
2019
2228
  if (!settings.enabled)
2020
2229
  return false;
@@ -2032,8 +2241,7 @@ export class AgentSession {
2032
2241
  // compaction boundary. This prevents a stale pre-compaction usage/error
2033
2242
  // from retriggering compaction on the first prompt after compaction.
2034
2243
  const compactionEntry = getLatestCompactionEntry(this.sessionManager.getBranch());
2035
- const assistantIsFromBeforeCompaction = compactionEntry !== null && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime();
2036
- if (assistantIsFromBeforeCompaction) {
2244
+ if (this._isAssistantFromBeforeLatestCompaction(assistantMessage)) {
2037
2245
  return false;
2038
2246
  }
2039
2247
  // Case 1: Overflow - LLM returned context overflow error.
@@ -2058,7 +2266,7 @@ export class AgentSession {
2058
2266
  willRetry: false,
2059
2267
  errorMessage,
2060
2268
  });
2061
- if (requestReason === "pre_prompt") {
2269
+ if (inlineReason === "pre_prompt") {
2062
2270
  throw new Error(errorMessage);
2063
2271
  }
2064
2272
  return false;
@@ -2071,42 +2279,47 @@ export class AgentSession {
2071
2279
  this.agent.state.messages = messages.slice(0, -1);
2072
2280
  this._incrementMessageRevision();
2073
2281
  }
2074
- if (requestReason) {
2075
- await this._runPrePromptCompaction(assistantMessage, skipAbortedCheck, "overflow", willRetry);
2282
+ if (inlineReason) {
2283
+ return await this._runPrePromptCompaction(assistantMessage, skipAbortedCheck, "overflow", willRetry);
2076
2284
  }
2077
2285
  else {
2078
2286
  return await this._runAutoCompaction("overflow", willRetry);
2079
2287
  }
2080
- return false;
2081
2288
  }
2082
2289
  // Case 2: Threshold - context is getting large
2083
2290
  // For error messages or all-zero usage messages, estimate from the last valid response.
2084
2291
  // This ensures sessions that hit persistent API errors (e.g. 529) or malformed zero-usage
2085
2292
  // responses can still compact and do not reset context accounting.
2086
2293
  let contextTokens;
2087
- const directContextTokens = assistantMessage.usage ? calculateContextTokens(assistantMessage.usage) : 0;
2088
- if (assistantMessage.stopReason === "error" || directContextTokens === 0) {
2089
- const messages = filterContextExcludedMessages(this.agent.state.messages);
2090
- const estimate = estimateContextTokens(messages);
2091
- if (estimate.lastUsageIndex === null)
2092
- return false; // No usage data at all
2093
- // Verify the usage source is post-compaction. Kept pre-compaction messages
2094
- // have stale usage reflecting the old (larger) context and would falsely
2095
- // trigger compaction right after one just finished.
2096
- const usageMsg = messages[estimate.lastUsageIndex];
2097
- if (compactionEntry &&
2098
- usageMsg.role === "assistant" &&
2099
- usageMsg.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
2100
- return false;
2101
- }
2102
- contextTokens = estimate.tokens;
2294
+ if (inlineReason) {
2295
+ const messages = filterContextExcludedMessages(this.sessionManager.buildSessionContext().messages);
2296
+ contextTokens = estimateContextTokens(messages).tokens;
2103
2297
  }
2104
2298
  else {
2105
- contextTokens = directContextTokens;
2299
+ const directContextTokens = assistantMessage.usage ? calculateContextTokens(assistantMessage.usage) : 0;
2300
+ if (assistantMessage.stopReason !== "error" && directContextTokens !== 0) {
2301
+ contextTokens = directContextTokens;
2302
+ }
2303
+ else {
2304
+ const messages = filterContextExcludedMessages(this.agent.state.messages);
2305
+ const estimate = estimateContextTokens(messages);
2306
+ if (estimate.lastUsageIndex === null)
2307
+ return false; // No usage data at all
2308
+ // Verify the usage source is post-compaction. Kept pre-compaction messages
2309
+ // have stale usage reflecting the old (larger) context and would falsely
2310
+ // trigger compaction right after one just finished.
2311
+ const usageMsg = messages[estimate.lastUsageIndex];
2312
+ if (compactionEntry &&
2313
+ usageMsg.role === "assistant" &&
2314
+ usageMsg.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
2315
+ return false;
2316
+ }
2317
+ contextTokens = estimate.tokens;
2318
+ }
2106
2319
  }
2107
2320
  if (shouldCompact(contextTokens, contextWindow, settings)) {
2108
- if (requestReason) {
2109
- await this._runPrePromptCompaction(assistantMessage, skipAbortedCheck);
2321
+ if (inlineReason) {
2322
+ return await this._runPrePromptCompaction(assistantMessage, skipAbortedCheck, inlineReason);
2110
2323
  }
2111
2324
  else {
2112
2325
  return await this._runAutoCompaction("threshold", false);
@@ -2127,6 +2340,7 @@ export class AgentSession {
2127
2340
  if (!execution.accepted && isContextOverflow(lastAssistantMessage, this.model?.contextWindow ?? 0)) {
2128
2341
  this._overflowRecoveryAttempted = false;
2129
2342
  }
2343
+ return execution.accepted;
2130
2344
  }
2131
2345
  catch (error) {
2132
2346
  if (isContextOverflow(lastAssistantMessage, this.model?.contextWindow ?? 0)) {
@@ -2142,6 +2356,7 @@ export class AgentSession {
2142
2356
  willRetry,
2143
2357
  errorMessage: aborted ? undefined : `Pre-prompt compaction failed: ${errorMessage}`,
2144
2358
  });
2359
+ return false;
2145
2360
  }
2146
2361
  finally {
2147
2362
  this._compactionAbortController = undefined;
@@ -2464,6 +2679,37 @@ export class AgentSession {
2464
2679
  },
2465
2680
  getContextUsage: () => this.getContextUsage(),
2466
2681
  getCompactionSettings: () => this.settingsManager.getCompactionSettings(),
2682
+ sessionSettings: {
2683
+ getRetryFallbackSettings: () => this.settingsManager.getRetryFallbackSettings(),
2684
+ setFallbackChain: async (key, entries) => {
2685
+ this.settingsManager.setFallbackChain(key, [...entries]);
2686
+ await this.settingsManager.flush();
2687
+ },
2688
+ removeFallbackChain: async (key) => {
2689
+ this.settingsManager.removeFallbackChain(key);
2690
+ await this.settingsManager.flush();
2691
+ },
2692
+ setModelFallbackEnabled: async (enabled) => {
2693
+ this.settingsManager.setModelFallbackEnabled(enabled);
2694
+ await this.settingsManager.flush();
2695
+ },
2696
+ setFallbackRevertPolicy: async (policy) => {
2697
+ this.settingsManager.setFallbackRevertPolicy(policy);
2698
+ await this.settingsManager.flush();
2699
+ },
2700
+ reload: () => this.settingsManager.reload(),
2701
+ getFallbackStatus: () => {
2702
+ const active = this._retryFallback.activeState;
2703
+ if (!active)
2704
+ return undefined;
2705
+ return {
2706
+ active: true,
2707
+ currentModel: this.model ? `${this.model.provider}/${this.model.id}` : undefined,
2708
+ originalSelector: active.originalSelector,
2709
+ pinned: active.pinned,
2710
+ };
2711
+ },
2712
+ },
2467
2713
  compact: (options) => {
2468
2714
  void (async () => {
2469
2715
  this._disconnectFromAgent();
@@ -2525,12 +2771,20 @@ export class AgentSession {
2525
2771
  this._modelRuntime.registerProvider(name, config);
2526
2772
  this._refreshCurrentModelFromRegistry();
2527
2773
  },
2774
+ registerNativeProvider: (provider) => {
2775
+ this._modelRuntime.registerNativeProvider(provider);
2776
+ this._refreshCurrentModelFromRegistry();
2777
+ },
2528
2778
  unregisterProvider: (name) => {
2529
2779
  this._modelRuntime.unregisterProvider(name);
2530
2780
  this._refreshCurrentModelFromRegistry();
2531
2781
  },
2532
2782
  });
2533
2783
  }
2784
+ /** Fallback-chain configuration warnings calculated when this session started. */
2785
+ get fallbackValidationWarnings() {
2786
+ return this._fallbackValidationWarnings;
2787
+ }
2534
2788
  _refreshToolRegistry(options) {
2535
2789
  const previousRegistryNames = new Set(this._toolRegistry.keys());
2536
2790
  const previousActiveToolNames = this.getActiveToolNames();
@@ -2678,16 +2932,25 @@ export class AgentSession {
2678
2932
  * Context overflow errors are NOT retryable (handled by compaction instead).
2679
2933
  */
2680
2934
  _isRetryableError(message) {
2681
- if (!message.errorMessage)
2682
- return false;
2683
2935
  // Context overflow is handled by compaction, not retry.
2684
2936
  if (isContextOverflow(message, this.model?.contextWindow ?? 0))
2685
2937
  return false;
2938
+ if (isClassifierRefusal(message))
2939
+ return true;
2940
+ if (!message.errorMessage)
2941
+ return false;
2686
2942
  if (message.stopReason === "aborted") {
2687
2943
  return /timed? out|timeout/i.test(message.errorMessage);
2688
2944
  }
2689
2945
  return isRetryableAssistantError(message);
2690
2946
  }
2947
+ _isHardErrorFallbackEligible(message) {
2948
+ return (message.stopReason === "error" &&
2949
+ !isContextOverflow(message, this.model?.contextWindow ?? 0) &&
2950
+ !isClassifierRefusal(message) &&
2951
+ !message.content.some((content) => content.type === "toolCall") &&
2952
+ this._retryFallback.canTryFallback());
2953
+ }
2691
2954
  _getProviderRetryDelayMs(errorMessage) {
2692
2955
  const retryAfterMsMatch = errorMessage.match(/\bretry[-_ ]?after[-_ ]?ms\s*[:=]\s*(\d+(?:\.\d+)?)/i);
2693
2956
  if (retryAfterMsMatch) {
@@ -2720,7 +2983,7 @@ export class AgentSession {
2720
2983
  * Handle retryable errors with exponential backoff.
2721
2984
  * @returns true if retry was initiated, false if max retries exceeded or disabled
2722
2985
  */
2723
- async _handleRetryableError(message) {
2986
+ async _handleRetryableError(message, options = {}) {
2724
2987
  const settings = this.settingsManager.getRetrySettings();
2725
2988
  if (!settings.enabled) {
2726
2989
  this._resolveRetry();
@@ -2733,21 +2996,71 @@ export class AgentSession {
2733
2996
  this._retryResolve = resolve;
2734
2997
  });
2735
2998
  }
2736
- this._retryAttempt++;
2737
- if (this._retryAttempt > settings.maxRetries) {
2738
- // Max retries exceeded, emit final failure and reset
2739
- this._emit({
2740
- type: "auto_retry_end",
2741
- success: false,
2742
- attempt: this._retryAttempt - 1,
2743
- finalError: message.errorMessage,
2744
- });
2745
- this._retryAttempt = 0;
2746
- this._resolveRetry(); // Resolve so waitForRetry() completes
2747
- return false;
2748
- }
2749
2999
  const errorMessage = message.errorMessage || "Unknown error";
2750
- const providerDelayMs = this._getProviderRetryDelayMs(errorMessage);
3000
+ const isRefusal = isClassifierRefusal(message);
3001
+ const hardErrorFallback = options.hardErrorFallback === true;
3002
+ let switchedFallback = false;
3003
+ if (hardErrorFallback) {
3004
+ // A non-retryable provider failure must never replay on the same model.
3005
+ switchedFallback = await this._retryFallback.tryFallback("hard-error", { errorMessage });
3006
+ if (!switchedFallback) {
3007
+ this._resolveRetry();
3008
+ return false;
3009
+ }
3010
+ // The fallback starts fresh; the failed model's transient attempts do not carry over.
3011
+ this._retryAttempt = 1;
3012
+ }
3013
+ else if (isRefusal) {
3014
+ // Refusals are only retried through a new chain candidate. They never use
3015
+ // same-model retries or the transient over-budget fallback escape hatch.
3016
+ if (this._retryAttempt + 1 > settings.maxRetries) {
3017
+ this._resolveRetry();
3018
+ return false;
3019
+ }
3020
+ switchedFallback = await this._retryFallback.tryFallback("refusal", {});
3021
+ if (!switchedFallback) {
3022
+ const exhaustedChainKey = this._retryFallback.exhaustedChainKey;
3023
+ if (exhaustedChainKey) {
3024
+ this._emit({ type: "retry_fallback_exhausted", chainKey: exhaustedChainKey, lastError: errorMessage });
3025
+ }
3026
+ this._resolveRetry();
3027
+ return false;
3028
+ }
3029
+ this._retryAttempt++;
3030
+ }
3031
+ else {
3032
+ this._retryAttempt++;
3033
+ if (this._retryAttempt > settings.maxRetries) {
3034
+ switchedFallback = await this._retryFallback.tryFallback("transient", {
3035
+ errorMessage,
3036
+ retryAfterMs: this._getProviderRetryDelayMs(errorMessage),
3037
+ });
3038
+ if (switchedFallback) {
3039
+ // The new model receives a fresh retry budget; the failed model does not.
3040
+ this._retryAttempt = 1;
3041
+ }
3042
+ else {
3043
+ const exhaustedChainKey = this._retryFallback.exhaustedChainKey;
3044
+ if (exhaustedChainKey) {
3045
+ this._emit({
3046
+ type: "retry_fallback_exhausted",
3047
+ chainKey: exhaustedChainKey,
3048
+ lastError: errorMessage,
3049
+ });
3050
+ }
3051
+ this._emit({
3052
+ type: "auto_retry_end",
3053
+ success: false,
3054
+ attempt: this._retryAttempt - 1,
3055
+ finalError: message.errorMessage,
3056
+ });
3057
+ this._retryAttempt = 0;
3058
+ this._resolveRetry();
3059
+ return false;
3060
+ }
3061
+ }
3062
+ }
3063
+ const providerDelayMs = isRefusal || hardErrorFallback ? undefined : this._getProviderRetryDelayMs(errorMessage);
2751
3064
  const maxRetryDelayMs = this.settingsManager.getProviderRetrySettings().maxRetryDelayMs;
2752
3065
  if (providerDelayMs !== undefined && providerDelayMs > maxRetryDelayMs) {
2753
3066
  this._emit({
@@ -2760,7 +3073,13 @@ export class AgentSession {
2760
3073
  this._resolveRetry();
2761
3074
  return false;
2762
3075
  }
2763
- const delayMs = providerDelayMs ?? settings.baseDelayMs * 2 ** (this._retryAttempt - 1);
3076
+ if (!switchedFallback) {
3077
+ switchedFallback = await this._retryFallback.tryFallback("transient", {
3078
+ errorMessage,
3079
+ retryAfterMs: providerDelayMs,
3080
+ });
3081
+ }
3082
+ const delayMs = switchedFallback ? 0 : (providerDelayMs ?? settings.baseDelayMs * 2 ** (this._retryAttempt - 1));
2764
3083
  // Prepare before auto_retry_start so an immediate Esc can cancel the retry sleep.
2765
3084
  this._retryAbortController = new AbortController();
2766
3085
  this._emit({
@@ -2796,6 +3115,9 @@ export class AgentSession {
2796
3115
  return false;
2797
3116
  }
2798
3117
  this._retryAbortController = undefined;
3118
+ // Turn boundary: a suppression that expired during the backoff sleep lets
3119
+ // the retry continue on the restored primary instead of the fallback model.
3120
+ await this._maybeRestoreFallbackPrimary();
2799
3121
  // Retry via continue() - use setTimeout to break out of event handler chain
2800
3122
  setTimeout(() => {
2801
3123
  this.agent.continue().catch(() => {