@bastani/atomic 0.8.26-alpha.6 → 0.8.26-alpha.8

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 (260) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +5 -5
  3. package/dist/builtin/intercom/CHANGELOG.md +12 -0
  4. package/dist/builtin/intercom/package.json +2 -2
  5. package/dist/builtin/mcp/CHANGELOG.md +12 -0
  6. package/dist/builtin/mcp/package.json +3 -3
  7. package/dist/builtin/subagents/CHANGELOG.md +12 -0
  8. package/dist/builtin/subagents/agents/codebase-online-researcher.md +9 -9
  9. package/dist/builtin/subagents/agents/debugger.md +6 -6
  10. package/dist/builtin/subagents/package.json +4 -4
  11. package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +1 -1
  12. package/dist/builtin/subagents/skills/browser/EXAMPLES.md +151 -0
  13. package/dist/builtin/subagents/skills/browser/LICENSE.txt +21 -0
  14. package/dist/builtin/subagents/skills/browser/REFERENCE.md +451 -0
  15. package/dist/builtin/subagents/skills/browser/SKILL.md +170 -0
  16. package/dist/builtin/subagents/skills/subagent/SKILL.md +4 -4
  17. package/dist/builtin/web-access/CHANGELOG.md +12 -0
  18. package/dist/builtin/web-access/package.json +2 -2
  19. package/dist/builtin/workflows/CHANGELOG.md +17 -0
  20. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +4 -1
  21. package/dist/builtin/workflows/builtin/goal.ts +127 -99
  22. package/dist/builtin/workflows/builtin/open-claude-design.ts +224 -147
  23. package/dist/builtin/workflows/builtin/ralph.ts +160 -197
  24. package/dist/builtin/workflows/package.json +2 -2
  25. package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
  26. package/dist/builtin/workflows/src/extension/wiring.ts +13 -1
  27. package/dist/builtin/workflows/src/runs/foreground/executor.ts +12 -6
  28. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +2 -2
  29. package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +2 -2
  30. package/dist/builtin/workflows/src/shared/types.ts +3 -3
  31. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +2 -1
  32. package/dist/core/agent-session.d.ts +33 -6
  33. package/dist/core/agent-session.d.ts.map +1 -1
  34. package/dist/core/agent-session.js +155 -182
  35. package/dist/core/agent-session.js.map +1 -1
  36. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  37. package/dist/core/atomic-guide-command.js +1 -1
  38. package/dist/core/atomic-guide-command.js.map +1 -1
  39. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  40. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  41. package/dist/core/compaction/branch-summarization.js +6 -3
  42. package/dist/core/compaction/branch-summarization.js.map +1 -1
  43. package/dist/core/compaction/compaction.d.ts.map +1 -1
  44. package/dist/core/compaction/compaction.js +23 -10
  45. package/dist/core/compaction/compaction.js.map +1 -1
  46. package/dist/core/compaction/context-compaction.d.ts +61 -0
  47. package/dist/core/compaction/context-compaction.d.ts.map +1 -0
  48. package/dist/core/compaction/context-compaction.js +602 -0
  49. package/dist/core/compaction/context-compaction.js.map +1 -0
  50. package/dist/core/compaction/index.d.ts +1 -0
  51. package/dist/core/compaction/index.d.ts.map +1 -1
  52. package/dist/core/compaction/index.js +1 -0
  53. package/dist/core/compaction/index.js.map +1 -1
  54. package/dist/core/extensions/types.d.ts +3 -2
  55. package/dist/core/extensions/types.d.ts.map +1 -1
  56. package/dist/core/extensions/types.js.map +1 -1
  57. package/dist/core/index.d.ts +1 -1
  58. package/dist/core/index.d.ts.map +1 -1
  59. package/dist/core/index.js.map +1 -1
  60. package/dist/core/session-manager.d.ts +41 -1
  61. package/dist/core/session-manager.d.ts.map +1 -1
  62. package/dist/core/session-manager.js +146 -7
  63. package/dist/core/session-manager.js.map +1 -1
  64. package/dist/core/slash-commands.d.ts.map +1 -1
  65. package/dist/core/slash-commands.js +1 -1
  66. package/dist/core/slash-commands.js.map +1 -1
  67. package/dist/index.d.ts +3 -3
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +2 -2
  70. package/dist/index.js.map +1 -1
  71. package/dist/modes/index.d.ts +1 -1
  72. package/dist/modes/index.d.ts.map +1 -1
  73. package/dist/modes/index.js.map +1 -1
  74. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  75. package/dist/modes/interactive/components/chat-session-host.js +17 -0
  76. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  77. package/dist/modes/interactive/components/context-compaction-summary-message.d.ts +17 -0
  78. package/dist/modes/interactive/components/context-compaction-summary-message.d.ts.map +1 -0
  79. package/dist/modes/interactive/components/context-compaction-summary-message.js +83 -0
  80. package/dist/modes/interactive/components/context-compaction-summary-message.js.map +1 -0
  81. package/dist/modes/interactive/components/index.d.ts +1 -0
  82. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  83. package/dist/modes/interactive/components/index.js +1 -0
  84. package/dist/modes/interactive/components/index.js.map +1 -1
  85. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  86. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  87. package/dist/modes/interactive/interactive-mode.js +72 -8
  88. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  89. package/dist/modes/rpc/rpc-client.d.ts +13 -8
  90. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  91. package/dist/modes/rpc/rpc-client.js +8 -1
  92. package/dist/modes/rpc/rpc-client.js.map +1 -1
  93. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  94. package/dist/modes/rpc/rpc-mode.js +4 -0
  95. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  96. package/dist/modes/rpc/rpc-types.d.ts +14 -3
  97. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  98. package/dist/modes/rpc/rpc-types.js.map +1 -1
  99. package/docs/compaction.md +89 -37
  100. package/docs/custom-provider.md +11 -9
  101. package/docs/extensions.md +44 -40
  102. package/docs/index.md +2 -9
  103. package/docs/json.md +15 -12
  104. package/docs/packages.md +2 -0
  105. package/docs/providers.md +4 -1
  106. package/docs/quickstart.md +5 -12
  107. package/docs/rpc.md +38 -23
  108. package/docs/sdk.md +3 -10
  109. package/docs/session-format.md +26 -13
  110. package/docs/sessions.md +3 -3
  111. package/docs/settings.md +2 -2
  112. package/docs/skills.md +1 -15
  113. package/docs/termux.md +9 -10
  114. package/docs/themes.md +2 -2
  115. package/docs/tmux.md +3 -3
  116. package/docs/tui.md +19 -32
  117. package/docs/usage.md +2 -2
  118. package/docs/workflows.md +44 -2
  119. package/package.json +4 -12
  120. package/dist/builtin/subagents/skills/browser-use/SKILL.md +0 -234
  121. package/dist/builtin/subagents/skills/browser-use/references/cdp-python.md +0 -76
  122. package/dist/builtin/subagents/skills/browser-use/references/multi-session.md +0 -92
  123. package/node_modules/@earendil-works/pi-tui/README.md +0 -779
  124. package/node_modules/@earendil-works/pi-tui/dist/autocomplete.d.ts +0 -54
  125. package/node_modules/@earendil-works/pi-tui/dist/autocomplete.d.ts.map +0 -1
  126. package/node_modules/@earendil-works/pi-tui/dist/autocomplete.js +0 -632
  127. package/node_modules/@earendil-works/pi-tui/dist/autocomplete.js.map +0 -1
  128. package/node_modules/@earendil-works/pi-tui/dist/components/box.d.ts +0 -22
  129. package/node_modules/@earendil-works/pi-tui/dist/components/box.d.ts.map +0 -1
  130. package/node_modules/@earendil-works/pi-tui/dist/components/box.js +0 -104
  131. package/node_modules/@earendil-works/pi-tui/dist/components/box.js.map +0 -1
  132. package/node_modules/@earendil-works/pi-tui/dist/components/cancellable-loader.d.ts +0 -22
  133. package/node_modules/@earendil-works/pi-tui/dist/components/cancellable-loader.d.ts.map +0 -1
  134. package/node_modules/@earendil-works/pi-tui/dist/components/cancellable-loader.js +0 -35
  135. package/node_modules/@earendil-works/pi-tui/dist/components/cancellable-loader.js.map +0 -1
  136. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +0 -249
  137. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +0 -1
  138. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +0 -1857
  139. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +0 -1
  140. package/node_modules/@earendil-works/pi-tui/dist/components/image.d.ts +0 -28
  141. package/node_modules/@earendil-works/pi-tui/dist/components/image.d.ts.map +0 -1
  142. package/node_modules/@earendil-works/pi-tui/dist/components/image.js +0 -89
  143. package/node_modules/@earendil-works/pi-tui/dist/components/image.js.map +0 -1
  144. package/node_modules/@earendil-works/pi-tui/dist/components/input.d.ts +0 -37
  145. package/node_modules/@earendil-works/pi-tui/dist/components/input.d.ts.map +0 -1
  146. package/node_modules/@earendil-works/pi-tui/dist/components/input.js +0 -378
  147. package/node_modules/@earendil-works/pi-tui/dist/components/input.js.map +0 -1
  148. package/node_modules/@earendil-works/pi-tui/dist/components/loader.d.ts +0 -31
  149. package/node_modules/@earendil-works/pi-tui/dist/components/loader.d.ts.map +0 -1
  150. package/node_modules/@earendil-works/pi-tui/dist/components/loader.js +0 -69
  151. package/node_modules/@earendil-works/pi-tui/dist/components/loader.js.map +0 -1
  152. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts +0 -96
  153. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts.map +0 -1
  154. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +0 -644
  155. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js.map +0 -1
  156. package/node_modules/@earendil-works/pi-tui/dist/components/select-list.d.ts +0 -50
  157. package/node_modules/@earendil-works/pi-tui/dist/components/select-list.d.ts.map +0 -1
  158. package/node_modules/@earendil-works/pi-tui/dist/components/select-list.js +0 -159
  159. package/node_modules/@earendil-works/pi-tui/dist/components/select-list.js.map +0 -1
  160. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.d.ts +0 -50
  161. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.d.ts.map +0 -1
  162. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.js +0 -185
  163. package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.js.map +0 -1
  164. package/node_modules/@earendil-works/pi-tui/dist/components/spacer.d.ts +0 -12
  165. package/node_modules/@earendil-works/pi-tui/dist/components/spacer.d.ts.map +0 -1
  166. package/node_modules/@earendil-works/pi-tui/dist/components/spacer.js +0 -23
  167. package/node_modules/@earendil-works/pi-tui/dist/components/spacer.js.map +0 -1
  168. package/node_modules/@earendil-works/pi-tui/dist/components/text.d.ts +0 -19
  169. package/node_modules/@earendil-works/pi-tui/dist/components/text.d.ts.map +0 -1
  170. package/node_modules/@earendil-works/pi-tui/dist/components/text.js +0 -89
  171. package/node_modules/@earendil-works/pi-tui/dist/components/text.js.map +0 -1
  172. package/node_modules/@earendil-works/pi-tui/dist/components/truncated-text.d.ts +0 -13
  173. package/node_modules/@earendil-works/pi-tui/dist/components/truncated-text.d.ts.map +0 -1
  174. package/node_modules/@earendil-works/pi-tui/dist/components/truncated-text.js +0 -51
  175. package/node_modules/@earendil-works/pi-tui/dist/components/truncated-text.js.map +0 -1
  176. package/node_modules/@earendil-works/pi-tui/dist/editor-component.d.ts +0 -39
  177. package/node_modules/@earendil-works/pi-tui/dist/editor-component.d.ts.map +0 -1
  178. package/node_modules/@earendil-works/pi-tui/dist/editor-component.js +0 -2
  179. package/node_modules/@earendil-works/pi-tui/dist/editor-component.js.map +0 -1
  180. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.d.ts +0 -16
  181. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.d.ts.map +0 -1
  182. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js +0 -110
  183. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js.map +0 -1
  184. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +0 -23
  185. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +0 -1
  186. package/node_modules/@earendil-works/pi-tui/dist/index.js +0 -32
  187. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +0 -1
  188. package/node_modules/@earendil-works/pi-tui/dist/keybindings.d.ts +0 -193
  189. package/node_modules/@earendil-works/pi-tui/dist/keybindings.d.ts.map +0 -1
  190. package/node_modules/@earendil-works/pi-tui/dist/keybindings.js +0 -174
  191. package/node_modules/@earendil-works/pi-tui/dist/keybindings.js.map +0 -1
  192. package/node_modules/@earendil-works/pi-tui/dist/keys.d.ts +0 -184
  193. package/node_modules/@earendil-works/pi-tui/dist/keys.d.ts.map +0 -1
  194. package/node_modules/@earendil-works/pi-tui/dist/keys.js +0 -1173
  195. package/node_modules/@earendil-works/pi-tui/dist/keys.js.map +0 -1
  196. package/node_modules/@earendil-works/pi-tui/dist/kill-ring.d.ts +0 -28
  197. package/node_modules/@earendil-works/pi-tui/dist/kill-ring.d.ts.map +0 -1
  198. package/node_modules/@earendil-works/pi-tui/dist/kill-ring.js +0 -44
  199. package/node_modules/@earendil-works/pi-tui/dist/kill-ring.js.map +0 -1
  200. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts +0 -3
  201. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts.map +0 -1
  202. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +0 -53
  203. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js.map +0 -1
  204. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts +0 -50
  205. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts.map +0 -1
  206. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js +0 -361
  207. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js.map +0 -1
  208. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts +0 -90
  209. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts.map +0 -1
  210. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +0 -366
  211. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js.map +0 -1
  212. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +0 -113
  213. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +0 -1
  214. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +0 -472
  215. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +0 -1
  216. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +0 -227
  217. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +0 -1
  218. package/node_modules/@earendil-works/pi-tui/dist/tui.js +0 -1106
  219. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +0 -1
  220. package/node_modules/@earendil-works/pi-tui/dist/undo-stack.d.ts +0 -17
  221. package/node_modules/@earendil-works/pi-tui/dist/undo-stack.d.ts.map +0 -1
  222. package/node_modules/@earendil-works/pi-tui/dist/undo-stack.js +0 -25
  223. package/node_modules/@earendil-works/pi-tui/dist/undo-stack.js.map +0 -1
  224. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts +0 -84
  225. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +0 -1
  226. package/node_modules/@earendil-works/pi-tui/dist/utils.js +0 -1029
  227. package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +0 -1
  228. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts +0 -25
  229. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts.map +0 -1
  230. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js +0 -96
  231. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js.map +0 -1
  232. package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  233. package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  234. package/node_modules/@earendil-works/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  235. package/node_modules/@earendil-works/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  236. package/node_modules/@earendil-works/pi-tui/package.json +0 -47
  237. package/node_modules/get-east-asian-width/index.d.ts +0 -60
  238. package/node_modules/get-east-asian-width/index.js +0 -30
  239. package/node_modules/get-east-asian-width/license +0 -9
  240. package/node_modules/get-east-asian-width/lookup-data.js +0 -21
  241. package/node_modules/get-east-asian-width/lookup.js +0 -138
  242. package/node_modules/get-east-asian-width/package.json +0 -71
  243. package/node_modules/get-east-asian-width/readme.md +0 -65
  244. package/node_modules/get-east-asian-width/utilities.js +0 -24
  245. package/node_modules/marked/LICENSE.md +0 -44
  246. package/node_modules/marked/README.md +0 -106
  247. package/node_modules/marked/bin/main.js +0 -282
  248. package/node_modules/marked/bin/marked.js +0 -15
  249. package/node_modules/marked/lib/marked.cjs +0 -2211
  250. package/node_modules/marked/lib/marked.cjs.map +0 -7
  251. package/node_modules/marked/lib/marked.d.cts +0 -728
  252. package/node_modules/marked/lib/marked.d.ts +0 -728
  253. package/node_modules/marked/lib/marked.esm.js +0 -2189
  254. package/node_modules/marked/lib/marked.esm.js.map +0 -7
  255. package/node_modules/marked/lib/marked.umd.js +0 -2213
  256. package/node_modules/marked/lib/marked.umd.js.map +0 -7
  257. package/node_modules/marked/man/marked.1 +0 -111
  258. package/node_modules/marked/man/marked.1.md +0 -92
  259. package/node_modules/marked/marked.min.js +0 -69
  260. package/node_modules/marked/package.json +0 -111
@@ -22,14 +22,14 @@ import { sleep } from "../utils/sleep.js";
22
22
  import { ATOMIC_GUIDE_COMMAND_NAME, ATOMIC_GUIDE_HELP_CHOICES, atomicGuideModeForChoice, getAtomicGuideMessage, isAtomicGuideHelpChoice, normalizeAtomicGuideMode, } from "./atomic-guide-command.js";
23
23
  import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
24
24
  import { executeBashWithOperations } from "./bash-executor.js";
25
- import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, generateBranchSummary, prepareCompaction, shouldCompact, } from "./compaction/index.js";
25
+ import { calculateContextTokens, collectEntriesForBranchSummary, contextCompact as runContextCompact, estimateContextTokens, generateBranchSummary, prepareContextCompaction, shouldCompact, } from "./compaction/index.js";
26
26
  import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
27
27
  import { exportSessionToHtml } from "./export-html/index.js";
28
28
  import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
29
29
  import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
30
30
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
31
31
  import { expandPromptTemplate } from "./prompt-templates.js";
32
- import { CURRENT_SESSION_VERSION, getLatestCompactionEntry } from "./session-manager.js";
32
+ import { CURRENT_SESSION_VERSION, getLatestCompactionBoundaryEntry } from "./session-manager.js";
33
33
  import { createSyntheticSourceInfo } from "./source-info.js";
34
34
  import { buildSystemPrompt } from "./system-prompt.js";
35
35
  import { createLocalBashOperations } from "./tools/bash.js";
@@ -1476,11 +1476,41 @@ export class AgentSession {
1476
1476
  // Compaction
1477
1477
  // =========================================================================
1478
1478
  /**
1479
- * Manually compact the session context.
1480
- * Aborts current agent operation first.
1481
- * @param customInstructions Optional instructions for the compaction summary
1479
+ * Apply validated logical deletions and rebuild active agent context.
1480
+ * Retained transcript entries/content blocks stay verbatim.
1481
+ */
1482
+ async _applyContextVerbatimCompaction(options) {
1483
+ if (!this.model) {
1484
+ throw new Error(formatNoModelSelectedMessage());
1485
+ }
1486
+ const pathEntries = this.sessionManager.getBranch();
1487
+ const settings = this.settingsManager.getCompactionSettings();
1488
+ const preparation = prepareContextCompaction(pathEntries, settings);
1489
+ if (!preparation) {
1490
+ return undefined;
1491
+ }
1492
+ const validated = await runContextCompact(preparation, this.model, options.apiKey, options.headers, options.abortController.signal, this.thinkingLevel);
1493
+ if (options.abortController.signal.aborted) {
1494
+ throw new Error("Compaction cancelled");
1495
+ }
1496
+ const backupPath = this.sessionManager.writeBackupSnapshot(options.backupLabel);
1497
+ this.sessionManager.appendContextCompaction(validated.deletedTargets, validated.protectedEntryIds, validated.stats, backupPath);
1498
+ const sessionContext = this.sessionManager.buildSessionContext();
1499
+ this.agent.state.messages = sessionContext.messages;
1500
+ return {
1501
+ ...validated,
1502
+ promptVersion: 1,
1503
+ ...(backupPath ? { backupPath } : {}),
1504
+ };
1505
+ }
1506
+ /**
1507
+ * Manually compact the session context using deletion-only verbatim context compaction.
1508
+ * Aborts current agent operation first. Custom summary instructions are not accepted.
1482
1509
  */
1483
1510
  async compact(customInstructions) {
1511
+ if (customInstructions?.trim()) {
1512
+ throw new Error("Custom compaction instructions are not supported; use /compact without arguments");
1513
+ }
1484
1514
  this._disconnectFromAgent();
1485
1515
  await this.abort();
1486
1516
  this._compactionAbortController = new AbortController();
@@ -1490,84 +1520,23 @@ export class AgentSession {
1490
1520
  throw new Error(formatNoModelSelectedMessage());
1491
1521
  }
1492
1522
  const { apiKey, headers } = await this._getRequiredRequestAuth(this.model);
1493
- const pathEntries = this.sessionManager.getBranch();
1494
- const settings = this.settingsManager.getCompactionSettings();
1495
- const preparation = prepareCompaction(pathEntries, settings);
1496
- if (!preparation) {
1497
- // Check why we can't compact
1498
- const lastEntry = pathEntries[pathEntries.length - 1];
1499
- if (lastEntry?.type === "compaction") {
1500
- throw new Error("Already compacted");
1501
- }
1523
+ const result = await this._applyContextVerbatimCompaction({
1524
+ apiKey,
1525
+ headers,
1526
+ abortController: this._compactionAbortController,
1527
+ backupLabel: "compact",
1528
+ });
1529
+ if (!result) {
1502
1530
  throw new Error("Nothing to compact (session too small)");
1503
1531
  }
1504
- let extensionCompaction;
1505
- let fromExtension = false;
1506
- if (this._extensionRunner.hasHandlers("session_before_compact")) {
1507
- const result = (await this._extensionRunner.emit({
1508
- type: "session_before_compact",
1509
- preparation,
1510
- branchEntries: pathEntries,
1511
- customInstructions,
1512
- signal: this._compactionAbortController.signal,
1513
- }));
1514
- if (result?.cancel) {
1515
- throw new Error("Compaction cancelled");
1516
- }
1517
- if (result?.compaction) {
1518
- extensionCompaction = result.compaction;
1519
- fromExtension = true;
1520
- }
1521
- }
1522
- let summary;
1523
- let firstKeptEntryId;
1524
- let tokensBefore;
1525
- let details;
1526
- if (extensionCompaction) {
1527
- // Extension provided compaction content
1528
- summary = extensionCompaction.summary;
1529
- firstKeptEntryId = extensionCompaction.firstKeptEntryId;
1530
- tokensBefore = extensionCompaction.tokensBefore;
1531
- details = extensionCompaction.details;
1532
- }
1533
- else {
1534
- // Generate compaction result
1535
- const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel);
1536
- summary = result.summary;
1537
- firstKeptEntryId = result.firstKeptEntryId;
1538
- tokensBefore = result.tokensBefore;
1539
- details = result.details;
1540
- }
1541
- if (this._compactionAbortController.signal.aborted) {
1542
- throw new Error("Compaction cancelled");
1543
- }
1544
- this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
1545
- const newEntries = this.sessionManager.getEntries();
1546
- const sessionContext = this.sessionManager.buildSessionContext();
1547
- this.agent.state.messages = sessionContext.messages;
1548
- // Get the saved compaction entry for the extension event
1549
- const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
1550
- if (this._extensionRunner && savedCompactionEntry) {
1551
- await this._extensionRunner.emit({
1552
- type: "session_compact",
1553
- compactionEntry: savedCompactionEntry,
1554
- fromExtension,
1555
- });
1556
- }
1557
- const compactionResult = {
1558
- summary,
1559
- firstKeptEntryId,
1560
- tokensBefore,
1561
- details,
1562
- };
1563
1532
  this._emit({
1564
1533
  type: "compaction_end",
1565
1534
  reason: "manual",
1566
- result: compactionResult,
1535
+ result,
1567
1536
  aborted: false,
1568
1537
  willRetry: false,
1569
1538
  });
1570
- return compactionResult;
1539
+ return result;
1571
1540
  }
1572
1541
  catch (error) {
1573
1542
  const message = error instanceof Error ? error.message : String(error);
@@ -1587,6 +1556,56 @@ export class AgentSession {
1587
1556
  this._reconnectToAgent();
1588
1557
  }
1589
1558
  }
1559
+ /**
1560
+ * Manually compact the session context by applying validated logical deletions.
1561
+ * Retained transcript entries/content blocks stay verbatim; no user prompt text is accepted.
1562
+ */
1563
+ async contextCompact() {
1564
+ this._disconnectFromAgent();
1565
+ await this.abort();
1566
+ this._compactionAbortController = new AbortController();
1567
+ this._emit({ type: "context_compaction_start", reason: "manual" });
1568
+ try {
1569
+ if (!this.model) {
1570
+ throw new Error(formatNoModelSelectedMessage());
1571
+ }
1572
+ const { apiKey, headers } = await this._getRequiredRequestAuth(this.model);
1573
+ const result = await this._applyContextVerbatimCompaction({
1574
+ apiKey,
1575
+ headers,
1576
+ abortController: this._compactionAbortController,
1577
+ backupLabel: "context-compact",
1578
+ });
1579
+ if (!result) {
1580
+ throw new Error("Nothing to context-compact (session too small)");
1581
+ }
1582
+ this._emit({
1583
+ type: "context_compaction_end",
1584
+ reason: "manual",
1585
+ result,
1586
+ aborted: false,
1587
+ willRetry: false,
1588
+ });
1589
+ return result;
1590
+ }
1591
+ catch (error) {
1592
+ const message = error instanceof Error ? error.message : String(error);
1593
+ const aborted = message === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
1594
+ this._emit({
1595
+ type: "context_compaction_end",
1596
+ reason: "manual",
1597
+ result: undefined,
1598
+ aborted,
1599
+ willRetry: false,
1600
+ errorMessage: aborted ? undefined : `Context compaction failed: ${message}`,
1601
+ });
1602
+ throw error;
1603
+ }
1604
+ finally {
1605
+ this._compactionAbortController = undefined;
1606
+ this._reconnectToAgent();
1607
+ }
1608
+ }
1590
1609
  /**
1591
1610
  * Cancel in-progress compaction (manual or auto).
1592
1611
  */
@@ -1606,7 +1625,7 @@ export class AgentSession {
1606
1625
  *
1607
1626
  * Two cases:
1608
1627
  * 1. Overflow: LLM returned context overflow error, remove error message from agent state, compact, auto-retry
1609
- * 2. Threshold: Context over threshold, compact, NO auto-retry (user continues manually)
1628
+ * 2. Threshold: Context over threshold, compact, resume queued active-turn work if present; otherwise wait for user
1610
1629
  *
1611
1630
  * @param assistantMessage The assistant message to check
1612
1631
  * @param skipAbortedCheck If false, include aborted messages (for pre-prompt check). Default: true
@@ -1627,9 +1646,10 @@ export class AgentSession {
1627
1646
  // Skip compaction checks if this assistant message is older than the latest
1628
1647
  // compaction boundary. This prevents a stale pre-compaction usage/error
1629
1648
  // from retriggering compaction on the first prompt after compaction.
1630
- const compactionEntry = getLatestCompactionEntry(this.sessionManager.getBranch());
1631
- const assistantIsFromBeforeCompaction = compactionEntry !== null && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime();
1632
- if (assistantIsFromBeforeCompaction) {
1649
+ const compactionBoundaryEntry = getLatestCompactionBoundaryEntry(this.sessionManager.getBranch());
1650
+ const assistantIsFromBeforeCompactionBoundary = compactionBoundaryEntry !== null &&
1651
+ assistantMessage.timestamp <= new Date(compactionBoundaryEntry.timestamp).getTime();
1652
+ if (assistantIsFromBeforeCompactionBoundary) {
1633
1653
  return;
1634
1654
  }
1635
1655
  // Case 1: Overflow - LLM returned context overflow error
@@ -1668,9 +1688,9 @@ export class AgentSession {
1668
1688
  // have stale usage reflecting the old (larger) context and would falsely
1669
1689
  // trigger compaction right after one just finished.
1670
1690
  const usageMsg = messages[estimate.lastUsageIndex];
1671
- if (compactionEntry &&
1691
+ if (compactionBoundaryEntry &&
1672
1692
  usageMsg.role === "assistant" &&
1673
- usageMsg.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
1693
+ usageMsg.timestamp <= new Date(compactionBoundaryEntry.timestamp).getTime()) {
1674
1694
  return;
1675
1695
  }
1676
1696
  contextTokens = estimate.tokens;
@@ -1682,11 +1702,44 @@ export class AgentSession {
1682
1702
  await this._runAutoCompaction("threshold", false);
1683
1703
  }
1684
1704
  }
1705
+ /**
1706
+ * Internal: remove the trailing overflow error from retry context if it is still present.
1707
+ */
1708
+ _dropTrailingOverflowAssistantErrorIfPresent() {
1709
+ const messages = this.agent.state.messages;
1710
+ const lastMsg = messages[messages.length - 1];
1711
+ if (lastMsg?.role === "assistant" && lastMsg.stopReason === "error") {
1712
+ this.agent.state.messages = messages.slice(0, -1);
1713
+ }
1714
+ }
1715
+ /**
1716
+ * Internal: schedule a live post-event continuation probe after compaction_end listeners can flush queues.
1717
+ */
1718
+ _schedulePostAutoCompactionContinuationProbe(reason, willRetry) {
1719
+ setTimeout(() => {
1720
+ if (this.isCompacting || this.isStreaming) {
1721
+ return;
1722
+ }
1723
+ if (reason === "overflow" && willRetry) {
1724
+ this._resumeAfterAutoCompaction();
1725
+ return;
1726
+ }
1727
+ if (!this.agent.hasQueuedMessages()) {
1728
+ return;
1729
+ }
1730
+ this._resumeAfterAutoCompaction();
1731
+ }, 100);
1732
+ }
1733
+ /**
1734
+ * Internal: resume generation after successful auto-compaction only when active work remains.
1735
+ */
1736
+ _resumeAfterAutoCompaction() {
1737
+ this.agent.continue().catch(() => { });
1738
+ }
1685
1739
  /**
1686
1740
  * Internal: Run auto-compaction with events.
1687
1741
  */
1688
1742
  async _runAutoCompaction(reason, willRetry) {
1689
- const settings = this.settingsManager.getCompactionSettings();
1690
1743
  this._emit({ type: "compaction_start", reason });
1691
1744
  this._autoCompactionAbortController = new AbortController();
1692
1745
  try {
@@ -1711,10 +1764,13 @@ export class AgentSession {
1711
1764
  });
1712
1765
  return;
1713
1766
  }
1714
- const { apiKey, headers } = authResult;
1715
- const pathEntries = this.sessionManager.getBranch();
1716
- const preparation = prepareCompaction(pathEntries, settings);
1717
- if (!preparation) {
1767
+ const result = await this._applyContextVerbatimCompaction({
1768
+ apiKey: authResult.apiKey,
1769
+ headers: authResult.headers,
1770
+ abortController: this._autoCompactionAbortController,
1771
+ backupLabel: reason === "overflow" ? "overflow-auto-compact" : "auto-compact",
1772
+ });
1773
+ if (!result) {
1718
1774
  this._emit({
1719
1775
  type: "compaction_end",
1720
1776
  reason,
@@ -1724,109 +1780,26 @@ export class AgentSession {
1724
1780
  });
1725
1781
  return;
1726
1782
  }
1727
- let extensionCompaction;
1728
- let fromExtension = false;
1729
- if (this._extensionRunner.hasHandlers("session_before_compact")) {
1730
- const extensionResult = (await this._extensionRunner.emit({
1731
- type: "session_before_compact",
1732
- preparation,
1733
- branchEntries: pathEntries,
1734
- customInstructions: undefined,
1735
- signal: this._autoCompactionAbortController.signal,
1736
- }));
1737
- if (extensionResult?.cancel) {
1738
- this._emit({
1739
- type: "compaction_end",
1740
- reason,
1741
- result: undefined,
1742
- aborted: true,
1743
- willRetry: false,
1744
- });
1745
- return;
1746
- }
1747
- if (extensionResult?.compaction) {
1748
- extensionCompaction = extensionResult.compaction;
1749
- fromExtension = true;
1750
- }
1751
- }
1752
- let summary;
1753
- let firstKeptEntryId;
1754
- let tokensBefore;
1755
- let details;
1756
- if (extensionCompaction) {
1757
- // Extension provided compaction content
1758
- summary = extensionCompaction.summary;
1759
- firstKeptEntryId = extensionCompaction.firstKeptEntryId;
1760
- tokensBefore = extensionCompaction.tokensBefore;
1761
- details = extensionCompaction.details;
1783
+ if (reason === "overflow" && willRetry) {
1784
+ this._dropTrailingOverflowAssistantErrorIfPresent();
1762
1785
  }
1763
- else {
1764
- // Generate compaction result
1765
- const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel);
1766
- summary = compactResult.summary;
1767
- firstKeptEntryId = compactResult.firstKeptEntryId;
1768
- tokensBefore = compactResult.tokensBefore;
1769
- details = compactResult.details;
1770
- }
1771
- if (this._autoCompactionAbortController.signal.aborted) {
1772
- this._emit({
1773
- type: "compaction_end",
1774
- reason,
1775
- result: undefined,
1776
- aborted: true,
1777
- willRetry: false,
1778
- });
1779
- return;
1780
- }
1781
- this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
1782
- const newEntries = this.sessionManager.getEntries();
1783
- const sessionContext = this.sessionManager.buildSessionContext();
1784
- this.agent.state.messages = sessionContext.messages;
1785
- // Get the saved compaction entry for the extension event
1786
- const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
1787
- if (this._extensionRunner && savedCompactionEntry) {
1788
- await this._extensionRunner.emit({
1789
- type: "session_compact",
1790
- compactionEntry: savedCompactionEntry,
1791
- fromExtension,
1792
- });
1793
- }
1794
- const result = {
1795
- summary,
1796
- firstKeptEntryId,
1797
- tokensBefore,
1798
- details,
1799
- };
1800
1786
  this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
1801
- if (willRetry) {
1802
- const messages = this.agent.state.messages;
1803
- const lastMsg = messages[messages.length - 1];
1804
- if (lastMsg?.role === "assistant" && lastMsg.stopReason === "error") {
1805
- this.agent.state.messages = messages.slice(0, -1);
1806
- }
1807
- setTimeout(() => {
1808
- this.agent.continue().catch(() => { });
1809
- }, 100);
1810
- }
1811
- else if (this.agent.hasQueuedMessages()) {
1812
- // Auto-compaction can complete while follow-up/steering/custom messages are waiting.
1813
- // Kick the loop so queued messages are actually delivered.
1814
- setTimeout(() => {
1815
- this.agent.continue().catch(() => { });
1816
- }, 100);
1817
- }
1787
+ this._schedulePostAutoCompactionContinuationProbe(reason, willRetry);
1818
1788
  }
1819
1789
  catch (error) {
1820
1790
  const errorMessage = error instanceof Error ? error.message : "compaction failed";
1791
+ const aborted = errorMessage === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
1821
1792
  this._emit({
1822
1793
  type: "compaction_end",
1823
1794
  reason,
1824
1795
  result: undefined,
1825
- aborted: false,
1796
+ aborted,
1826
1797
  willRetry: false,
1827
- errorMessage: reason === "overflow"
1828
- ? `Context overflow recovery failed: ${errorMessage}`
1829
- : `Auto-compaction failed: ${errorMessage}`,
1798
+ errorMessage: aborted
1799
+ ? undefined
1800
+ : reason === "overflow"
1801
+ ? `Context overflow recovery failed: ${errorMessage}`
1802
+ : `Auto-compaction failed: ${errorMessage}`,
1830
1803
  });
1831
1804
  }
1832
1805
  finally {
@@ -2633,10 +2606,10 @@ export class AgentSession {
2633
2606
  // We can only trust usage from an assistant that responded after the latest compaction.
2634
2607
  // If no such assistant exists, context token count is unknown until the next LLM response.
2635
2608
  const branchEntries = this.sessionManager.getBranch();
2636
- const latestCompaction = getLatestCompactionEntry(branchEntries);
2637
- if (latestCompaction) {
2609
+ const latestCompactionBoundary = getLatestCompactionBoundaryEntry(branchEntries);
2610
+ if (latestCompactionBoundary) {
2638
2611
  // Check if there's a valid assistant usage after the compaction boundary
2639
- const compactionIndex = branchEntries.lastIndexOf(latestCompaction);
2612
+ const compactionIndex = branchEntries.lastIndexOf(latestCompactionBoundary);
2640
2613
  let hasPostCompactionUsage = false;
2641
2614
  for (let i = branchEntries.length - 1; i > compactionIndex; i--) {
2642
2615
  const entry = branchEntries[i];