@code-yeongyu/senpi 2026.5.13 → 2026.5.15-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 (274) hide show
  1. package/CHANGELOG.md +1109 -1150
  2. package/README.md +1 -2
  3. package/dist/core/agent-session.d.ts +9 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +121 -12
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/bash-executor.d.ts.map +1 -1
  8. package/dist/core/bash-executor.js +1 -1
  9. package/dist/core/bash-executor.js.map +1 -1
  10. package/dist/core/compaction/compaction.d.ts.map +1 -1
  11. package/dist/core/compaction/compaction.js +2 -2
  12. package/dist/core/compaction/compaction.js.map +1 -1
  13. package/dist/core/dynamic-prompt/verification.d.ts +31 -0
  14. package/dist/core/dynamic-prompt/verification.d.ts.map +1 -1
  15. package/dist/core/dynamic-prompt/verification.js +41 -0
  16. package/dist/core/dynamic-prompt/verification.js.map +1 -1
  17. package/dist/core/export-html/index.d.ts.map +1 -1
  18. package/dist/core/export-html/index.js +8 -1
  19. package/dist/core/export-html/index.js.map +1 -1
  20. package/dist/core/extensions/builtin/anthropic-web-search/index.d.ts.map +1 -1
  21. package/dist/core/extensions/builtin/anthropic-web-search/index.js +20 -0
  22. package/dist/core/extensions/builtin/anthropic-web-search/index.js.map +1 -1
  23. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  24. package/dist/core/extensions/builtin/compaction/index.js +157 -29
  25. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  26. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +197 -0
  27. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -0
  28. package/dist/core/extensions/builtin/compaction/openai-remote.js +690 -0
  29. package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -0
  30. package/dist/core/extensions/builtin/compaction/prompts.d.ts +3 -3
  31. package/dist/core/extensions/builtin/compaction/prompts.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/compaction/prompts.js +0 -22
  33. package/dist/core/extensions/builtin/compaction/prompts.js.map +1 -1
  34. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts +4 -0
  35. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts.map +1 -0
  36. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js +48 -0
  37. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js.map +1 -0
  38. package/dist/core/extensions/builtin/compaction/speculative.d.ts +3 -1
  39. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/compaction/speculative.js +82 -33
  41. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  42. package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +8 -0
  43. package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
  44. package/dist/core/extensions/builtin/compaction/todo-bridge.js +12 -6
  45. package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
  46. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/index.js +0 -20
  48. package/dist/core/extensions/builtin/index.js.map +1 -1
  49. package/dist/core/extensions/builtin/openai-web-search/index.d.ts.map +1 -1
  50. package/dist/core/extensions/builtin/openai-web-search/index.js +28 -0
  51. package/dist/core/extensions/builtin/openai-web-search/index.js.map +1 -1
  52. package/dist/core/extensions/builtin/permission-system/prompt.d.ts.map +1 -1
  53. package/dist/core/extensions/builtin/permission-system/prompt.js +0 -5
  54. package/dist/core/extensions/builtin/permission-system/prompt.js.map +1 -1
  55. package/dist/core/extensions/builtin/system-messages.d.ts +7 -7
  56. package/dist/core/extensions/builtin/system-messages.d.ts.map +1 -1
  57. package/dist/core/extensions/builtin/system-messages.js +10 -10
  58. package/dist/core/extensions/builtin/system-messages.js.map +1 -1
  59. package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts +1 -1
  60. package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/todotools/continuation/prompt.js +1 -1
  62. package/dist/core/extensions/builtin/todotools/continuation/prompt.js.map +1 -1
  63. package/dist/core/extensions/builtin/todotools/state.d.ts +1 -1
  64. package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/todotools/state.js +2 -2
  66. package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
  67. package/dist/core/extensions/builtin/todotools/system-messages.d.ts +3 -3
  68. package/dist/core/extensions/builtin/todotools/system-messages.d.ts.map +1 -1
  69. package/dist/core/extensions/builtin/todotools/system-messages.js +6 -6
  70. package/dist/core/extensions/builtin/todotools/system-messages.js.map +1 -1
  71. package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts +1 -1
  72. package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts.map +1 -1
  73. package/dist/core/extensions/builtin/tool-pair-guard/index.js +8 -4
  74. package/dist/core/extensions/builtin/tool-pair-guard/index.js.map +1 -1
  75. package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts +3 -0
  76. package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts.map +1 -0
  77. package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js +89 -0
  78. package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js.map +1 -0
  79. package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts +3 -0
  80. package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts.map +1 -0
  81. package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js +122 -0
  82. package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js.map +1 -0
  83. package/dist/core/extensions/loader.d.ts.map +1 -1
  84. package/dist/core/extensions/loader.js +2 -0
  85. package/dist/core/extensions/loader.js.map +1 -1
  86. package/dist/core/extensions/runner.d.ts +3 -0
  87. package/dist/core/extensions/runner.d.ts.map +1 -1
  88. package/dist/core/extensions/runner.js +18 -0
  89. package/dist/core/extensions/runner.js.map +1 -1
  90. package/dist/core/extensions/types.d.ts +22 -0
  91. package/dist/core/extensions/types.d.ts.map +1 -1
  92. package/dist/core/extensions/types.js.map +1 -1
  93. package/dist/core/messages.d.ts +3 -3
  94. package/dist/core/messages.d.ts.map +1 -1
  95. package/dist/core/messages.js +5 -10
  96. package/dist/core/messages.js.map +1 -1
  97. package/dist/core/resource-loader.d.ts.map +1 -1
  98. package/dist/core/resource-loader.js +0 -9
  99. package/dist/core/resource-loader.js.map +1 -1
  100. package/dist/core/sdk.d.ts +2 -2
  101. package/dist/core/sdk.d.ts.map +1 -1
  102. package/dist/core/sdk.js +8 -23
  103. package/dist/core/sdk.js.map +1 -1
  104. package/dist/core/session-manager.d.ts.map +1 -1
  105. package/dist/core/session-manager.js +1 -1
  106. package/dist/core/session-manager.js.map +1 -1
  107. package/dist/core/settings-manager.d.ts +0 -5
  108. package/dist/core/settings-manager.d.ts.map +1 -1
  109. package/dist/core/settings-manager.js.map +1 -1
  110. package/dist/core/thinking-levels.d.ts +6 -0
  111. package/dist/core/thinking-levels.d.ts.map +1 -0
  112. package/dist/core/thinking-levels.js +36 -0
  113. package/dist/core/thinking-levels.js.map +1 -0
  114. package/dist/core/tools/bash.d.ts.map +1 -1
  115. package/dist/core/tools/bash.js +15 -1
  116. package/dist/core/tools/bash.js.map +1 -1
  117. package/dist/core/tools/render-utils.d.ts.map +1 -1
  118. package/dist/core/tools/render-utils.js +1 -1
  119. package/dist/core/tools/render-utils.js.map +1 -1
  120. package/dist/main.d.ts.map +1 -1
  121. package/dist/main.js +3 -2
  122. package/dist/main.js.map +1 -1
  123. package/dist/modes/interactive/components/assistant-message.d.ts +0 -3
  124. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  125. package/dist/modes/interactive/components/assistant-message.js +3 -22
  126. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  127. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  128. package/dist/modes/interactive/components/bash-execution.js +1 -1
  129. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  130. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  131. package/dist/modes/interactive/components/compaction-summary-message.js +20 -2
  132. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  133. package/dist/modes/interactive/components/extension-selector.d.ts +2 -0
  134. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  135. package/dist/modes/interactive/components/extension-selector.js +6 -1
  136. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  137. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  138. package/dist/modes/interactive/components/keybinding-hints.js +3 -1
  139. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  140. package/dist/modes/interactive/interactive-mode.d.ts +23 -0
  141. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  142. package/dist/modes/interactive/interactive-mode.js +139 -54
  143. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  144. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  145. package/dist/modes/interactive/theme/theme.js +2 -2
  146. package/dist/modes/interactive/theme/theme.js.map +1 -1
  147. package/dist/modes/print-mode.d.ts.map +1 -1
  148. package/dist/modes/print-mode.js +3 -11
  149. package/dist/modes/print-mode.js.map +1 -1
  150. package/dist/modes/provider-native-rendering.d.ts +5 -0
  151. package/dist/modes/provider-native-rendering.d.ts.map +1 -0
  152. package/dist/modes/provider-native-rendering.js +247 -0
  153. package/dist/modes/provider-native-rendering.js.map +1 -0
  154. package/dist/utils/ansi.d.ts +2 -0
  155. package/dist/utils/ansi.d.ts.map +1 -0
  156. package/dist/utils/ansi.js +52 -0
  157. package/dist/utils/ansi.js.map +1 -0
  158. package/dist/utils/html.d.ts +7 -0
  159. package/dist/utils/html.d.ts.map +1 -0
  160. package/dist/utils/html.js +40 -0
  161. package/dist/utils/html.js.map +1 -0
  162. package/dist/utils/mime.d.ts +1 -0
  163. package/dist/utils/mime.d.ts.map +1 -1
  164. package/dist/utils/mime.js +59 -16
  165. package/dist/utils/mime.js.map +1 -1
  166. package/dist/utils/syntax-highlight.d.ts +12 -0
  167. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  168. package/dist/utils/syntax-highlight.js +118 -0
  169. package/dist/utils/syntax-highlight.js.map +1 -0
  170. package/dist/utils/tools-manager.d.ts.map +1 -1
  171. package/dist/utils/tools-manager.js +76 -7
  172. package/dist/utils/tools-manager.js.map +1 -1
  173. package/docs/extensions.md +0 -1
  174. package/docs/index.md +0 -1
  175. package/docs/sdk.md +25 -44
  176. package/docs/settings.md +1 -29
  177. package/docs/termux.md +2 -2
  178. package/docs/usage.md +1 -1
  179. package/examples/README.md +1 -1
  180. package/examples/extensions/README.md +0 -1
  181. package/examples/extensions/overlay-qa-tests.ts +1 -1
  182. package/examples/sdk/01-minimal.ts +14 -10
  183. package/examples/sdk/02-custom-model.ts +12 -8
  184. package/examples/sdk/03-custom-prompt.ts +24 -16
  185. package/examples/sdk/04-skills.ts +2 -2
  186. package/examples/sdk/05-tools.ts +8 -4
  187. package/examples/sdk/06-extensions.ts +11 -7
  188. package/examples/sdk/07-context-files.ts +2 -2
  189. package/examples/sdk/08-prompt-templates.ts +2 -2
  190. package/examples/sdk/09-api-keys-and-oauth.ts +8 -4
  191. package/examples/sdk/10-settings.ts +4 -4
  192. package/examples/sdk/11-sessions.ts +4 -0
  193. package/examples/sdk/12-full-control.ts +11 -7
  194. package/examples/sdk/README.md +6 -9
  195. package/package.json +7 -12
  196. package/dist/core/extensions/builtin/anthropic-code-execution/index.d.ts +0 -7
  197. package/dist/core/extensions/builtin/anthropic-code-execution/index.d.ts.map +0 -1
  198. package/dist/core/extensions/builtin/anthropic-code-execution/index.js +0 -79
  199. package/dist/core/extensions/builtin/anthropic-code-execution/index.js.map +0 -1
  200. package/dist/core/extensions/builtin/anthropic-computer-use/index.d.ts +0 -53
  201. package/dist/core/extensions/builtin/anthropic-computer-use/index.d.ts.map +0 -1
  202. package/dist/core/extensions/builtin/anthropic-computer-use/index.js +0 -676
  203. package/dist/core/extensions/builtin/anthropic-computer-use/index.js.map +0 -1
  204. package/dist/core/extensions/builtin/anthropic-text-editor/index.d.ts +0 -25
  205. package/dist/core/extensions/builtin/anthropic-text-editor/index.d.ts.map +0 -1
  206. package/dist/core/extensions/builtin/anthropic-text-editor/index.js +0 -244
  207. package/dist/core/extensions/builtin/anthropic-text-editor/index.js.map +0 -1
  208. package/dist/core/extensions/builtin/anthropic-tool-search/index.d.ts +0 -6
  209. package/dist/core/extensions/builtin/anthropic-tool-search/index.d.ts.map +0 -1
  210. package/dist/core/extensions/builtin/anthropic-tool-search/index.js +0 -112
  211. package/dist/core/extensions/builtin/anthropic-tool-search/index.js.map +0 -1
  212. package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts +0 -10
  213. package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts.map +0 -1
  214. package/dist/core/extensions/builtin/background-task/cancel-tool.js +0 -109
  215. package/dist/core/extensions/builtin/background-task/cancel-tool.js.map +0 -1
  216. package/dist/core/extensions/builtin/background-task/index.d.ts +0 -3
  217. package/dist/core/extensions/builtin/background-task/index.d.ts.map +0 -1
  218. package/dist/core/extensions/builtin/background-task/index.js +0 -207
  219. package/dist/core/extensions/builtin/background-task/index.js.map +0 -1
  220. package/dist/core/extensions/builtin/background-task/manager.d.ts +0 -17
  221. package/dist/core/extensions/builtin/background-task/manager.d.ts.map +0 -1
  222. package/dist/core/extensions/builtin/background-task/manager.js +0 -114
  223. package/dist/core/extensions/builtin/background-task/manager.js.map +0 -1
  224. package/dist/core/extensions/builtin/background-task/notification.d.ts +0 -22
  225. package/dist/core/extensions/builtin/background-task/notification.d.ts.map +0 -1
  226. package/dist/core/extensions/builtin/background-task/notification.js +0 -105
  227. package/dist/core/extensions/builtin/background-task/notification.js.map +0 -1
  228. package/dist/core/extensions/builtin/background-task/output-tool.d.ts +0 -11
  229. package/dist/core/extensions/builtin/background-task/output-tool.d.ts.map +0 -1
  230. package/dist/core/extensions/builtin/background-task/output-tool.js +0 -127
  231. package/dist/core/extensions/builtin/background-task/output-tool.js.map +0 -1
  232. package/dist/core/extensions/builtin/background-task/spawner.d.ts +0 -8
  233. package/dist/core/extensions/builtin/background-task/spawner.d.ts.map +0 -1
  234. package/dist/core/extensions/builtin/background-task/spawner.js +0 -207
  235. package/dist/core/extensions/builtin/background-task/spawner.js.map +0 -1
  236. package/dist/core/extensions/builtin/background-task/task-tool.d.ts +0 -20
  237. package/dist/core/extensions/builtin/background-task/task-tool.d.ts.map +0 -1
  238. package/dist/core/extensions/builtin/background-task/task-tool.js +0 -302
  239. package/dist/core/extensions/builtin/background-task/task-tool.js.map +0 -1
  240. package/dist/core/extensions/builtin/background-task/types.d.ts +0 -72
  241. package/dist/core/extensions/builtin/background-task/types.d.ts.map +0 -1
  242. package/dist/core/extensions/builtin/background-task/types.js +0 -32
  243. package/dist/core/extensions/builtin/background-task/types.js.map +0 -1
  244. package/dist/core/extensions/builtin/google-code-execution/index.d.ts +0 -7
  245. package/dist/core/extensions/builtin/google-code-execution/index.d.ts.map +0 -1
  246. package/dist/core/extensions/builtin/google-code-execution/index.js +0 -73
  247. package/dist/core/extensions/builtin/google-code-execution/index.js.map +0 -1
  248. package/dist/core/extensions/builtin/google-google-search/index.d.ts +0 -7
  249. package/dist/core/extensions/builtin/google-google-search/index.d.ts.map +0 -1
  250. package/dist/core/extensions/builtin/google-google-search/index.js +0 -83
  251. package/dist/core/extensions/builtin/google-google-search/index.js.map +0 -1
  252. package/dist/core/extensions/builtin/google-url-context/index.d.ts +0 -7
  253. package/dist/core/extensions/builtin/google-url-context/index.d.ts.map +0 -1
  254. package/dist/core/extensions/builtin/google-url-context/index.js +0 -82
  255. package/dist/core/extensions/builtin/google-url-context/index.js.map +0 -1
  256. package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.d.ts +0 -6
  257. package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.d.ts.map +0 -1
  258. package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.js +0 -57
  259. package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.js.map +0 -1
  260. package/dist/core/extensions/builtin/openai-code-interpreter/index.d.ts +0 -10
  261. package/dist/core/extensions/builtin/openai-code-interpreter/index.d.ts.map +0 -1
  262. package/dist/core/extensions/builtin/openai-code-interpreter/index.js +0 -95
  263. package/dist/core/extensions/builtin/openai-code-interpreter/index.js.map +0 -1
  264. package/docs/agents.md +0 -348
  265. package/examples/extensions/subagent/README.md +0 -172
  266. package/examples/extensions/subagent/agents/planner.md +0 -37
  267. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  268. package/examples/extensions/subagent/agents/scout.md +0 -50
  269. package/examples/extensions/subagent/agents/worker.md +0 -24
  270. package/examples/extensions/subagent/agents.ts +0 -126
  271. package/examples/extensions/subagent/index.ts +0 -987
  272. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  273. package/examples/extensions/subagent/prompts/implement.md +0 -10
  274. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
@@ -15,7 +15,8 @@
15
15
  import { randomUUID } from "node:crypto";
16
16
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
17
  import { basename, dirname, resolve } from "node:path";
18
- import { cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, modelsAreEqual, resetApiProviders, supportsMax, supportsXhigh, } from "@earendil-works/pi-ai";
18
+ import { cleanupSessionResources, isContextOverflow, modelsAreEqual, resetApiProviders } from "@earendil-works/pi-ai";
19
+ import { expandTildePath } from "../config.js";
19
20
  import { theme } from "../modes/interactive/theme/theme.js";
20
21
  import { stripFrontmatter } from "../utils/frontmatter.js";
21
22
  import { sleep } from "../utils/sleep.js";
@@ -33,6 +34,7 @@ import { getModelNarrowingPatterns, resolveModelScope } from "./model-resolver.j
33
34
  import { expandPromptTemplate } from "./prompt-templates.js";
34
35
  import { buildSessionContext, CURRENT_SESSION_VERSION, getLatestCompactionEntry, } from "./session-manager.js";
35
36
  import { createSyntheticSourceInfo } from "./source-info.js";
37
+ import { getSupportedThinkingLevels, supportsMax, supportsXhigh } from "./thinking-levels.js";
36
38
  import { createLocalBashOperations } from "./tools/bash.js";
37
39
  import { createAllToolDefinitions } from "./tools/index.js";
38
40
  import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
@@ -1376,8 +1378,11 @@ export class AgentSession {
1376
1378
  if (options.expectedRevision !== undefined && options.expectedRevision !== this._messageRevision) {
1377
1379
  return { applied: false, reason: "stale" };
1378
1380
  }
1379
- this._compactionAbortController = new AbortController();
1380
- this._emit({ type: "compaction_start", reason: options.reason });
1381
+ const ownsController = this._compactionAbortController === undefined;
1382
+ if (ownsController) {
1383
+ this._compactionAbortController = new AbortController();
1384
+ this._emit({ type: "compaction_start", reason: options.reason });
1385
+ }
1381
1386
  try {
1382
1387
  const execution = await this._executeCompaction({
1383
1388
  reason: options.reason,
@@ -1406,6 +1411,38 @@ export class AgentSession {
1406
1411
  this._compactionAbortController = undefined;
1407
1412
  }
1408
1413
  }
1414
+ _beginExtensionCompactionFeedback(reason) {
1415
+ if (!this._compactionAbortController) {
1416
+ this._compactionAbortController = new AbortController();
1417
+ this._emit({ type: "compaction_start", reason });
1418
+ }
1419
+ return this._compactionAbortController.signal;
1420
+ }
1421
+ _updateExtensionCompactionFeedback(options) {
1422
+ if (!this._compactionAbortController && !this._autoCompactionAbortController)
1423
+ return;
1424
+ this._emit({
1425
+ type: "compaction_progress",
1426
+ reason: options.reason,
1427
+ ...(options.delta !== undefined ? { delta: options.delta } : {}),
1428
+ ...(options.text !== undefined ? { text: options.text } : {}),
1429
+ });
1430
+ }
1431
+ _endExtensionCompactionFeedback(options) {
1432
+ const controller = this._compactionAbortController;
1433
+ if (!controller)
1434
+ return;
1435
+ const aborted = options.aborted ?? controller.signal.aborted;
1436
+ this._emit({
1437
+ type: "compaction_end",
1438
+ reason: options.reason,
1439
+ result: undefined,
1440
+ aborted,
1441
+ willRetry: false,
1442
+ errorMessage: aborted ? undefined : options.errorMessage,
1443
+ });
1444
+ this._compactionAbortController = undefined;
1445
+ }
1409
1446
  async _executeCompaction(request) {
1410
1447
  if (!this.model) {
1411
1448
  throw new Error(formatNoModelSelectedMessage());
@@ -1563,8 +1600,14 @@ export class AgentSession {
1563
1600
  if (assistantIsFromBeforeCompaction) {
1564
1601
  return;
1565
1602
  }
1566
- // Case 1: Overflow - LLM returned context overflow error
1567
- if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
1603
+ // Case 1: Overflow - LLM returned context overflow error.
1604
+ // If the saved assistant provider differs from the currently selected provider alias,
1605
+ // still recover as overflow when the current context is also at the compaction limit.
1606
+ const contextUsage = this.getContextUsage();
1607
+ const currentContextNeedsCompaction = contextUsage !== undefined &&
1608
+ contextUsage.tokens !== null &&
1609
+ shouldCompact(contextUsage.tokens, contextUsage.contextWindow, settings);
1610
+ if (isContextOverflow(assistantMessage, contextWindow) && (sameModel || currentContextNeedsCompaction)) {
1568
1611
  if (this._overflowRecoveryAttempted) {
1569
1612
  this._emit({
1570
1613
  type: "compaction_end",
@@ -1628,14 +1671,20 @@ export class AgentSession {
1628
1671
  this._emit({ type: "compaction_start", reason: "pre_prompt" });
1629
1672
  this._compactionAbortController = new AbortController();
1630
1673
  try {
1631
- await this._executeCompaction({
1674
+ const execution = await this._executeCompaction({
1632
1675
  reason: "pre_prompt",
1633
1676
  willRetry: false,
1634
1677
  lastAssistantMessage,
1635
1678
  skipAbortedCheck,
1636
1679
  });
1680
+ if (!execution.accepted && isContextOverflow(lastAssistantMessage, this.model?.contextWindow ?? 0)) {
1681
+ this._overflowRecoveryAttempted = false;
1682
+ }
1637
1683
  }
1638
1684
  catch (error) {
1685
+ if (isContextOverflow(lastAssistantMessage, this.model?.contextWindow ?? 0)) {
1686
+ this._overflowRecoveryAttempted = false;
1687
+ }
1639
1688
  const errorMessage = error instanceof Error ? error.message : "compaction failed";
1640
1689
  const aborted = errorMessage === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
1641
1690
  this._emit({
@@ -1659,6 +1708,8 @@ export class AgentSession {
1659
1708
  this._autoCompactionAbortController = new AbortController();
1660
1709
  try {
1661
1710
  if (!this.model) {
1711
+ if (reason === "overflow")
1712
+ this._overflowRecoveryAttempted = false;
1662
1713
  this._emit({
1663
1714
  type: "compaction_end",
1664
1715
  reason,
@@ -1670,6 +1721,8 @@ export class AgentSession {
1670
1721
  }
1671
1722
  const authResult = await this._modelRegistry.getApiKeyAndHeaders(this.model);
1672
1723
  if (!authResult.ok || !authResult.apiKey) {
1724
+ if (reason === "overflow")
1725
+ this._overflowRecoveryAttempted = false;
1673
1726
  this._emit({
1674
1727
  type: "compaction_end",
1675
1728
  reason,
@@ -1681,6 +1734,8 @@ export class AgentSession {
1681
1734
  }
1682
1735
  const preparation = prepareCompaction(this.sessionManager.getBranch(), this.settingsManager.getCompactionSettings());
1683
1736
  if (!preparation) {
1737
+ if (reason === "overflow")
1738
+ this._overflowRecoveryAttempted = false;
1684
1739
  this._emit({
1685
1740
  type: "compaction_end",
1686
1741
  reason,
@@ -1692,6 +1747,8 @@ export class AgentSession {
1692
1747
  }
1693
1748
  const execution = await this._executeCompaction({ reason, willRetry });
1694
1749
  if (!execution.accepted) {
1750
+ if (reason === "overflow")
1751
+ this._overflowRecoveryAttempted = false;
1695
1752
  return;
1696
1753
  }
1697
1754
  if (willRetry) {
@@ -1714,6 +1771,8 @@ export class AgentSession {
1714
1771
  }
1715
1772
  }
1716
1773
  catch (error) {
1774
+ if (reason === "overflow")
1775
+ this._overflowRecoveryAttempted = false;
1717
1776
  const errorMessage = error instanceof Error ? error.message : "compaction failed";
1718
1777
  const aborted = errorMessage === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
1719
1778
  this._emit({
@@ -1936,6 +1995,9 @@ export class AgentSession {
1936
1995
  }
1937
1996
  })();
1938
1997
  },
1998
+ beginCompaction: (options) => this._beginExtensionCompactionFeedback(options.reason),
1999
+ updateCompaction: (options) => this._updateExtensionCompactionFeedback(options),
2000
+ endCompaction: (options) => this._endExtensionCompactionFeedback(options),
1939
2001
  getMessageRevision: () => this.getMessageRevision(),
1940
2002
  applyCompaction: (precomputed, options) => this.applyCompaction(precomputed, options),
1941
2003
  getSystemPrompt: () => this.systemPrompt,
@@ -2094,15 +2156,48 @@ export class AgentSession {
2094
2156
  * Context overflow errors are NOT retryable (handled by compaction instead).
2095
2157
  */
2096
2158
  _isRetryableError(message) {
2097
- if (message.stopReason !== "error" || !message.errorMessage)
2159
+ if (!message.errorMessage)
2098
2160
  return false;
2099
2161
  // Context overflow is handled by compaction, not retry
2100
2162
  const contextWindow = this.model?.contextWindow ?? 0;
2101
2163
  if (isContextOverflow(message, contextWindow))
2102
2164
  return false;
2103
2165
  const err = message.errorMessage;
2104
- // Match: overloaded_error, provider returned error, rate limit, 429, 500, 502, 503, 504, service unavailable, network/connection errors (including connection lost), WebSocket transport closes/errors, fetch failed, request ended without sending chunks, HTTP/2 closed before response, terminated, retry delay exceeded
2105
- return /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i.test(err);
2166
+ if (message.stopReason === "aborted") {
2167
+ return /timed? out|timeout/i.test(err);
2168
+ }
2169
+ if (message.stopReason !== "error")
2170
+ return false;
2171
+ // Match: overloaded_error, provider returned error, rate limit, 429, 500, 502, 503, 504, service unavailable, network/connection errors (including connection lost), WebSocket transport closes/errors, fetch failed, premature stream endings, HTTP/2 closed before response, terminated, retry delay exceeded
2172
+ return /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i.test(err);
2173
+ }
2174
+ _getProviderRetryDelayMs(errorMessage) {
2175
+ const retryAfterMsMatch = errorMessage.match(/\bretry[-_ ]?after[-_ ]?ms\s*[:=]\s*(\d+(?:\.\d+)?)/i);
2176
+ if (retryAfterMsMatch) {
2177
+ const delayMs = Math.ceil(Number(retryAfterMsMatch[1]));
2178
+ return Number.isFinite(delayMs) && delayMs > 0 ? delayMs : undefined;
2179
+ }
2180
+ const retryAfterSecondsMatch = errorMessage.match(/\bretry[-_ ]?after\s*[:=]\s*(\d+(?:\.\d+)?)/i);
2181
+ if (retryAfterSecondsMatch) {
2182
+ const delayMs = Math.ceil(Number(retryAfterSecondsMatch[1]) * 1000);
2183
+ return Number.isFinite(delayMs) && delayMs > 0 ? delayMs : undefined;
2184
+ }
2185
+ const retryInMatch = errorMessage.match(/\b(?:retry|try again|wait)\s+(?:after|in)\s*(\d+(?:\.\d+)?)\s*(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m)\b/i);
2186
+ if (!retryInMatch) {
2187
+ return undefined;
2188
+ }
2189
+ const value = Number(retryInMatch[1]);
2190
+ if (!Number.isFinite(value) || value <= 0) {
2191
+ return undefined;
2192
+ }
2193
+ const unit = retryInMatch[2].toLowerCase();
2194
+ if (unit === "m" || unit.startsWith("min")) {
2195
+ return Math.ceil(value * 60_000);
2196
+ }
2197
+ if (unit.startsWith("s")) {
2198
+ return Math.ceil(value * 1000);
2199
+ }
2200
+ return Math.ceil(value);
2106
2201
  }
2107
2202
  /**
2108
2203
  * Handle retryable errors with exponential backoff.
@@ -2134,13 +2229,27 @@ export class AgentSession {
2134
2229
  this._resolveRetry(); // Resolve so waitForRetry() completes
2135
2230
  return false;
2136
2231
  }
2137
- const delayMs = settings.baseDelayMs * 2 ** (this._retryAttempt - 1);
2232
+ const errorMessage = message.errorMessage || "Unknown error";
2233
+ const providerDelayMs = this._getProviderRetryDelayMs(errorMessage);
2234
+ const maxRetryDelayMs = this.settingsManager.getProviderRetrySettings().maxRetryDelayMs;
2235
+ if (providerDelayMs !== undefined && providerDelayMs > maxRetryDelayMs) {
2236
+ this._emit({
2237
+ type: "auto_retry_end",
2238
+ success: false,
2239
+ attempt: this._retryAttempt,
2240
+ finalError: `Provider requested retry delay ${providerDelayMs}ms, exceeding configured maximum ${maxRetryDelayMs}ms`,
2241
+ });
2242
+ this._retryAttempt = 0;
2243
+ this._resolveRetry();
2244
+ return false;
2245
+ }
2246
+ const delayMs = providerDelayMs ?? settings.baseDelayMs * 2 ** (this._retryAttempt - 1);
2138
2247
  this._emit({
2139
2248
  type: "auto_retry_start",
2140
2249
  attempt: this._retryAttempt,
2141
2250
  maxAttempts: settings.maxRetries,
2142
2251
  delayMs,
2143
- errorMessage: message.errorMessage || "Unknown error",
2252
+ errorMessage,
2144
2253
  });
2145
2254
  // Remove error message from agent state (keep in session for history)
2146
2255
  const messages = this.agent.state.messages;
@@ -2622,7 +2731,7 @@ export class AgentSession {
2622
2731
  * @returns The resolved output file path.
2623
2732
  */
2624
2733
  exportToJsonl(outputPath) {
2625
- const filePath = resolve(outputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, "-")}.jsonl`);
2734
+ const filePath = resolve(expandTildePath(outputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, "-")}.jsonl`));
2626
2735
  const dir = dirname(filePath);
2627
2736
  if (!existsSync(dir)) {
2628
2737
  mkdirSync(dir, { recursive: true });