@bastani/atomic 0.9.5-alpha.9 → 0.9.5

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 (377) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/cursor/CHANGELOG.md +12 -0
  4. package/dist/builtin/cursor/package.json +3 -3
  5. package/dist/builtin/cursor/src/model-mapper.ts +6 -3
  6. package/dist/builtin/intercom/CHANGELOG.md +37 -0
  7. package/dist/builtin/intercom/README.md +4 -2
  8. package/dist/builtin/intercom/broker/broker.ts +6 -114
  9. package/dist/builtin/intercom/broker/client.ts +29 -54
  10. package/dist/builtin/intercom/broker/delivered-message-cache.ts +44 -0
  11. package/dist/builtin/intercom/broker/pending-send-registry.ts +142 -0
  12. package/dist/builtin/intercom/broker/send-handler.ts +106 -0
  13. package/dist/builtin/intercom/broker/send-signature.ts +37 -0
  14. package/dist/builtin/intercom/foreground-detach-handoff.ts +136 -0
  15. package/dist/builtin/intercom/index-heavy.ts +49 -53
  16. package/dist/builtin/intercom/index.ts +278 -262
  17. package/dist/builtin/intercom/lazy-heavy-proxy.ts +114 -0
  18. package/dist/builtin/intercom/lazy-subagent-ack.ts +20 -0
  19. package/dist/builtin/intercom/lazy-tool-execution.ts +39 -0
  20. package/dist/builtin/intercom/lifecycle-lease.ts +51 -0
  21. package/dist/builtin/intercom/lifecycle.ts +37 -20
  22. package/dist/builtin/intercom/package.json +3 -6
  23. package/dist/builtin/intercom/reply-routing.ts +17 -0
  24. package/dist/builtin/intercom/subagent-relay.ts +58 -12
  25. package/dist/builtin/intercom/types.ts +3 -3
  26. package/dist/builtin/mcp/CHANGELOG.md +27 -0
  27. package/dist/builtin/mcp/OAUTH.md +1 -0
  28. package/dist/builtin/mcp/README.md +4 -0
  29. package/dist/builtin/mcp/apps-cancellation.ts +32 -0
  30. package/dist/builtin/mcp/call-tool-result.ts +9 -0
  31. package/dist/builtin/mcp/caller-wait.ts +50 -0
  32. package/dist/builtin/mcp/command-registration.ts +82 -0
  33. package/dist/builtin/mcp/direct-tool-executor.ts +279 -0
  34. package/dist/builtin/mcp/direct-tools.ts +6 -239
  35. package/dist/builtin/mcp/host-html-template.ts +4 -2
  36. package/dist/builtin/mcp/index.ts +258 -250
  37. package/dist/builtin/mcp/init.ts +96 -87
  38. package/dist/builtin/mcp/mcp-auth-flow.ts +247 -237
  39. package/dist/builtin/mcp/mcp-callback-server.ts +89 -68
  40. package/dist/builtin/mcp/mcp-oauth-provider.ts +23 -1
  41. package/dist/builtin/mcp/metadata-hydration.ts +21 -6
  42. package/dist/builtin/mcp/package.json +3 -3
  43. package/dist/builtin/mcp/proxy-auth.ts +4 -4
  44. package/dist/builtin/mcp/proxy-call.ts +111 -40
  45. package/dist/builtin/mcp/proxy-connect.ts +35 -15
  46. package/dist/builtin/mcp/proxy-info-modes.ts +49 -19
  47. package/dist/builtin/mcp/proxy-modes.ts +3 -3
  48. package/dist/builtin/mcp/session-cleanup-barrier.ts +43 -0
  49. package/dist/builtin/mcp/state-lease.ts +12 -0
  50. package/dist/builtin/mcp/ui-server.ts +8 -8
  51. package/dist/builtin/mcp/ui-session.ts +9 -18
  52. package/dist/builtin/subagents/CHANGELOG.md +66 -0
  53. package/dist/builtin/subagents/README.md +30 -29
  54. package/dist/builtin/subagents/agents/code-simplifier.md +2 -2
  55. package/dist/builtin/subagents/agents/codebase-analyzer.md +2 -2
  56. package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
  57. package/dist/builtin/subagents/agents/codebase-online-researcher.md +2 -2
  58. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
  59. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +2 -2
  60. package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
  61. package/dist/builtin/subagents/agents/debugger.md +2 -2
  62. package/dist/builtin/subagents/agents/worker.md +2 -2
  63. package/dist/builtin/subagents/package.json +5 -5
  64. package/dist/builtin/subagents/prompts/review-loop.md +1 -1
  65. package/dist/builtin/subagents/skills/subagent/SKILL.md +37 -36
  66. package/dist/builtin/subagents/src/extension/api-lifecycle.ts +64 -0
  67. package/dist/builtin/subagents/src/extension/fanout-child.ts +44 -51
  68. package/dist/builtin/subagents/src/extension/index.ts +287 -307
  69. package/dist/builtin/subagents/src/extension/prompt-guidance.ts +7 -10
  70. package/dist/builtin/subagents/src/extension/schemas.ts +22 -5
  71. package/dist/builtin/subagents/src/extension/tool-description.ts +29 -0
  72. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +13 -2
  73. package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -4
  74. package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +106 -0
  75. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +3 -2
  76. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +13 -2
  77. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +3 -0
  78. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +1 -1
  79. package/dist/builtin/subagents/src/runs/background/completion-claims.ts +189 -0
  80. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +44 -7
  81. package/dist/builtin/subagents/src/runs/background/completion-notification.ts +34 -0
  82. package/dist/builtin/subagents/src/runs/background/notify.ts +72 -22
  83. package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +232 -0
  84. package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +151 -0
  85. package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +72 -0
  86. package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +48 -0
  87. package/dist/builtin/subagents/src/runs/background/result-status.ts +81 -0
  88. package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +59 -0
  89. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +172 -238
  90. package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +3 -2
  91. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +73 -14
  92. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +17 -13
  93. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +1 -2
  94. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +1 -0
  95. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +1 -0
  96. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +1 -0
  97. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +7 -9
  98. package/dist/builtin/subagents/src/runs/foreground/chain-execution-types.ts +3 -13
  99. package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +2 -15
  100. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +2 -2
  101. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +53 -44
  102. package/dist/builtin/subagents/src/runs/foreground/execution-detach-reservations.ts +48 -0
  103. package/dist/builtin/subagents/src/runs/foreground/execution-detach-route.ts +17 -0
  104. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +39 -26
  105. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +3 -1
  106. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +3 -51
  107. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +6 -11
  108. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-input.ts +11 -2
  109. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
  110. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +5 -112
  111. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +2 -0
  112. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +68 -118
  113. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +79 -7
  114. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +2 -2
  115. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +3 -0
  116. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -2
  117. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +27 -11
  118. package/dist/builtin/subagents/src/shared/artifacts.ts +22 -11
  119. package/dist/builtin/subagents/src/shared/event-jsonl-writer.ts +294 -0
  120. package/dist/builtin/subagents/src/shared/exclusive-file-publication.ts +44 -0
  121. package/dist/builtin/subagents/src/shared/jsonl-writer.ts +1 -0
  122. package/dist/builtin/subagents/src/shared/model-info.ts +2 -2
  123. package/dist/builtin/subagents/src/shared/settings.ts +20 -10
  124. package/dist/builtin/subagents/src/shared/types-async.ts +3 -1
  125. package/dist/builtin/subagents/src/shared/types-config.ts +2 -0
  126. package/dist/builtin/subagents/src/shared/types-runtime.ts +3 -2
  127. package/dist/builtin/subagents/src/slash/slash-commands.ts +9 -12
  128. package/dist/builtin/subagents/src/slash/slash-live-state.ts +63 -32
  129. package/dist/builtin/subagents/src/tui/render-result.ts +7 -0
  130. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -0
  131. package/dist/builtin/subagents/src/tui/render-widget.ts +128 -89
  132. package/dist/builtin/web-access/CHANGELOG.md +28 -0
  133. package/dist/builtin/web-access/README.md +4 -0
  134. package/dist/builtin/web-access/content-tools.ts +8 -3
  135. package/dist/builtin/web-access/index-heavy.ts +1 -1
  136. package/dist/builtin/web-access/index.ts +190 -46
  137. package/dist/builtin/web-access/lifecycle-lease.ts +38 -0
  138. package/dist/builtin/web-access/package.json +2 -2
  139. package/dist/builtin/web-access/result-renderers.ts +1 -1
  140. package/dist/builtin/web-access/summary-review.ts +1 -1
  141. package/dist/builtin/web-access/web-search-activity.ts +1 -1
  142. package/dist/builtin/web-access/web-search-return.ts +7 -0
  143. package/dist/builtin/web-access/web-search-summary.ts +1 -1
  144. package/dist/builtin/web-access/web-search-tool.ts +4 -2
  145. package/dist/builtin/workflows/CHANGELOG.md +68 -0
  146. package/dist/builtin/workflows/README.md +4 -4
  147. package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +27 -4
  148. package/dist/builtin/workflows/builtin/goal-runner.ts +47 -26
  149. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +10 -0
  150. package/dist/builtin/workflows/builtin/ralph-core.ts +9 -9
  151. package/dist/builtin/workflows/builtin/ralph-models.ts +71 -36
  152. package/dist/builtin/workflows/builtin/ralph-runner.ts +20 -31
  153. package/dist/builtin/workflows/package.json +2 -2
  154. package/dist/builtin/workflows/src/durable/stage-primitive.ts +2 -1
  155. package/dist/builtin/workflows/src/engine/primitives/task.ts +2 -1
  156. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +17 -22
  157. package/dist/builtin/workflows/src/extension/workflow-schema.ts +15 -2
  158. package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +1 -2
  159. package/dist/builtin/workflows/src/runs/shared/model-fallback-candidates.ts +1 -1
  160. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -2
  161. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +2 -2
  162. package/dist/builtin/workflows/src/shared/resume-continuation.ts +2 -0
  163. package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +1 -23
  164. package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +54 -9
  165. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +5 -2
  166. package/dist/cli/args.d.ts.map +1 -1
  167. package/dist/cli/args.js +2 -2
  168. package/dist/cli/args.js.map +1 -1
  169. package/dist/core/agent-session-events.d.ts.map +1 -1
  170. package/dist/core/agent-session-events.js +2 -1
  171. package/dist/core/agent-session-events.js.map +1 -1
  172. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  173. package/dist/core/agent-session-message-queue.js +1 -1
  174. package/dist/core/agent-session-message-queue.js.map +1 -1
  175. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  176. package/dist/core/agent-session-prompt.js +1 -1
  177. package/dist/core/agent-session-prompt.js.map +1 -1
  178. package/dist/core/agent-session-retry.d.ts.map +1 -1
  179. package/dist/core/agent-session-retry.js +1 -1
  180. package/dist/core/agent-session-retry.js.map +1 -1
  181. package/dist/core/agent-session-services.d.ts.map +1 -1
  182. package/dist/core/agent-session-services.js +3 -2
  183. package/dist/core/agent-session-services.js.map +1 -1
  184. package/dist/core/agent-session-types.d.ts.map +1 -1
  185. package/dist/core/agent-session-types.js +1 -1
  186. package/dist/core/agent-session-types.js.map +1 -1
  187. package/dist/core/anthropic-thinking-guard.d.ts +5 -5
  188. package/dist/core/anthropic-thinking-guard.d.ts.map +1 -1
  189. package/dist/core/anthropic-thinking-guard.js +42 -32
  190. package/dist/core/anthropic-thinking-guard.js.map +1 -1
  191. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  192. package/dist/core/atomic-guide-command.js +15 -15
  193. package/dist/core/atomic-guide-command.js.map +1 -1
  194. package/dist/core/auth-storage.d.ts.map +1 -1
  195. package/dist/core/auth-storage.js +14 -9
  196. package/dist/core/auth-storage.js.map +1 -1
  197. package/dist/core/compaction/compaction.d.ts +2 -0
  198. package/dist/core/compaction/compaction.d.ts.map +1 -1
  199. package/dist/core/compaction/compaction.js +79 -46
  200. package/dist/core/compaction/compaction.js.map +1 -1
  201. package/dist/core/compaction/context-assistant-turns.d.ts +42 -0
  202. package/dist/core/compaction/context-assistant-turns.d.ts.map +1 -0
  203. package/dist/core/compaction/context-assistant-turns.js +87 -0
  204. package/dist/core/compaction/context-assistant-turns.js.map +1 -0
  205. package/dist/core/compaction/context-compaction-critical.d.ts +1 -1
  206. package/dist/core/compaction/context-compaction-critical.d.ts.map +1 -1
  207. package/dist/core/compaction/context-compaction-critical.js +2 -2
  208. package/dist/core/compaction/context-compaction-critical.js.map +1 -1
  209. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts +18 -0
  210. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts.map +1 -0
  211. package/dist/core/compaction/context-compaction-eviction-alternates.js +186 -0
  212. package/dist/core/compaction/context-compaction-eviction-alternates.js.map +1 -0
  213. package/dist/core/compaction/context-compaction-eviction.d.ts +10 -2
  214. package/dist/core/compaction/context-compaction-eviction.d.ts.map +1 -1
  215. package/dist/core/compaction/context-compaction-eviction.js +196 -146
  216. package/dist/core/compaction/context-compaction-eviction.js.map +1 -1
  217. package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
  218. package/dist/core/compaction/context-compaction-prompt.js +1 -1
  219. package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
  220. package/dist/core/compaction/context-compaction-types.d.ts +2 -0
  221. package/dist/core/compaction/context-compaction-types.d.ts.map +1 -1
  222. package/dist/core/compaction/context-compaction-types.js.map +1 -1
  223. package/dist/core/compaction/context-deletion-application.d.ts +5 -4
  224. package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
  225. package/dist/core/compaction/context-deletion-application.js +17 -15
  226. package/dist/core/compaction/context-deletion-application.js.map +1 -1
  227. package/dist/core/compaction/context-deletion-store.d.ts.map +1 -1
  228. package/dist/core/compaction/context-deletion-store.js +1 -1
  229. package/dist/core/compaction/context-deletion-store.js.map +1 -1
  230. package/dist/core/compaction/context-deletion-targets.d.ts +2 -1
  231. package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
  232. package/dist/core/compaction/context-deletion-targets.js +36 -31
  233. package/dist/core/compaction/context-deletion-targets.js.map +1 -1
  234. package/dist/core/compaction/context-deletion-tool-helpers.d.ts.map +1 -1
  235. package/dist/core/compaction/context-deletion-tool-helpers.js +116 -43
  236. package/dist/core/compaction/context-deletion-tool-helpers.js.map +1 -1
  237. package/dist/core/compaction/context-transcript-analysis.d.ts +1 -2
  238. package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
  239. package/dist/core/compaction/context-transcript-analysis.js +33 -37
  240. package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
  241. package/dist/core/copilot-model-synthesis.d.ts.map +1 -1
  242. package/dist/core/copilot-model-synthesis.js +3 -1
  243. package/dist/core/copilot-model-synthesis.js.map +1 -1
  244. package/dist/core/extensions/provider-types.d.ts +2 -7
  245. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  246. package/dist/core/extensions/provider-types.js.map +1 -1
  247. package/dist/core/messages.d.ts +9 -0
  248. package/dist/core/messages.d.ts.map +1 -1
  249. package/dist/core/messages.js +100 -18
  250. package/dist/core/messages.js.map +1 -1
  251. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  252. package/dist/core/model-registry-builtins.js +5 -0
  253. package/dist/core/model-registry-builtins.js.map +1 -1
  254. package/dist/core/model-registry-custom-loader.d.ts.map +1 -1
  255. package/dist/core/model-registry-custom-loader.js +49 -8
  256. package/dist/core/model-registry-custom-loader.js.map +1 -1
  257. package/dist/core/model-registry-dynamic.d.ts.map +1 -1
  258. package/dist/core/model-registry-dynamic.js +11 -5
  259. package/dist/core/model-registry-dynamic.js.map +1 -1
  260. package/dist/core/model-registry-loader.d.ts.map +1 -1
  261. package/dist/core/model-registry-loader.js +8 -0
  262. package/dist/core/model-registry-loader.js.map +1 -1
  263. package/dist/core/model-registry-schemas.d.ts +93 -8
  264. package/dist/core/model-registry-schemas.d.ts.map +1 -1
  265. package/dist/core/model-registry-schemas.js +24 -12
  266. package/dist/core/model-registry-schemas.js.map +1 -1
  267. package/dist/core/model-registry-types.d.ts +7 -6
  268. package/dist/core/model-registry-types.d.ts.map +1 -1
  269. package/dist/core/model-registry-types.js.map +1 -1
  270. package/dist/core/model-registry.d.ts +5 -0
  271. package/dist/core/model-registry.d.ts.map +1 -1
  272. package/dist/core/model-registry.js +23 -0
  273. package/dist/core/model-registry.js.map +1 -1
  274. package/dist/core/model-resolver-cli.d.ts.map +1 -1
  275. package/dist/core/model-resolver-cli.js +33 -5
  276. package/dist/core/model-resolver-cli.js.map +1 -1
  277. package/dist/core/model-resolver-initial.d.ts +6 -1
  278. package/dist/core/model-resolver-initial.d.ts.map +1 -1
  279. package/dist/core/model-resolver-initial.js +12 -7
  280. package/dist/core/model-resolver-initial.js.map +1 -1
  281. package/dist/core/model-resolver.d.ts +1 -1
  282. package/dist/core/model-resolver.d.ts.map +1 -1
  283. package/dist/core/model-resolver.js +1 -1
  284. package/dist/core/model-resolver.js.map +1 -1
  285. package/dist/core/resource-loader-context-files.d.ts +1 -0
  286. package/dist/core/resource-loader-context-files.d.ts.map +1 -1
  287. package/dist/core/resource-loader-context-files.js +13 -10
  288. package/dist/core/resource-loader-context-files.js.map +1 -1
  289. package/dist/core/sdk.d.ts.map +1 -1
  290. package/dist/core/sdk.js +2 -2
  291. package/dist/core/sdk.js.map +1 -1
  292. package/dist/core/session-entry-normalization.d.ts +7 -0
  293. package/dist/core/session-entry-normalization.d.ts.map +1 -0
  294. package/dist/core/session-entry-normalization.js +14 -0
  295. package/dist/core/session-entry-normalization.js.map +1 -0
  296. package/dist/core/session-manager-core.d.ts.map +1 -1
  297. package/dist/core/session-manager-core.js +1 -0
  298. package/dist/core/session-manager-core.js.map +1 -1
  299. package/dist/core/session-manager-history.d.ts +2 -2
  300. package/dist/core/session-manager-history.d.ts.map +1 -1
  301. package/dist/core/session-manager-history.js +127 -108
  302. package/dist/core/session-manager-history.js.map +1 -1
  303. package/dist/core/settings-manager-basic-accessors.d.ts +2 -2
  304. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  305. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  306. package/dist/core/settings-types.d.ts +1 -1
  307. package/dist/core/settings-types.d.ts.map +1 -1
  308. package/dist/core/settings-types.js.map +1 -1
  309. package/dist/core/tools/bash.d.ts.map +1 -1
  310. package/dist/core/tools/bash.js +11 -8
  311. package/dist/core/tools/bash.js.map +1 -1
  312. package/dist/main-session.d.ts.map +1 -1
  313. package/dist/main-session.js +1 -0
  314. package/dist/main-session.js.map +1 -1
  315. package/dist/modes/interactive/components/settings-selector-options.d.ts.map +1 -1
  316. package/dist/modes/interactive/components/settings-selector-options.js +3 -1
  317. package/dist/modes/interactive/components/settings-selector-options.js.map +1 -1
  318. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/thinking-selector.js +2 -1
  320. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  321. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  322. package/dist/modes/interactive/interactive-agent-events.js +2 -1
  323. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  324. package/dist/modes/interactive/interactive-child-ordering.d.ts +7 -0
  325. package/dist/modes/interactive/interactive-child-ordering.d.ts.map +1 -0
  326. package/dist/modes/interactive/interactive-child-ordering.js +26 -0
  327. package/dist/modes/interactive/interactive-child-ordering.js.map +1 -0
  328. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
  329. package/dist/modes/interactive/interactive-deferred-startup.js +2 -2
  330. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
  331. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  332. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  333. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  334. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  335. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  336. package/dist/modes/interactive/interactive-model-routing.js +8 -3
  337. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  338. package/dist/modes/interactive/theme/theme-class.d.ts +1 -1
  339. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  340. package/dist/modes/interactive/theme/theme-class.js +2 -0
  341. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  342. package/dist/utils/clipboard-image.d.ts.map +1 -1
  343. package/dist/utils/clipboard-image.js +3 -0
  344. package/dist/utils/clipboard-image.js.map +1 -1
  345. package/docs/changelog.mdx +19 -0
  346. package/docs/compaction.md +55 -48
  347. package/docs/custom-provider.md +18 -5
  348. package/docs/extensions.md +7 -3
  349. package/docs/models.md +69 -10
  350. package/docs/providers.md +1 -1
  351. package/docs/quickstart.md +11 -7
  352. package/docs/rpc.md +2 -2
  353. package/docs/sdk.md +1 -1
  354. package/docs/settings.md +3 -3
  355. package/docs/subagents.md +36 -5
  356. package/docs/tools.md +1 -1
  357. package/docs/usage.md +4 -2
  358. package/docs/workflows.md +26 -43
  359. package/examples/extensions/preset.ts +2 -2
  360. package/examples/extensions/subagent/README.md +2 -2
  361. package/examples/extensions/subagent/index.ts +1 -2
  362. package/examples/extensions/subagent/schemas.ts +4 -1
  363. package/examples/sdk/12-full-control.ts +1 -1
  364. package/npm-shrinkwrap.json +48 -51
  365. package/package.json +7 -7
  366. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-behavior.ts +0 -75
  367. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-component.ts +0 -202
  368. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-edit.ts +0 -97
  369. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-editor.ts +0 -160
  370. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-frame.ts +0 -72
  371. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-modes.ts +0 -161
  372. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-selectors.ts +0 -203
  373. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-selectors.ts +0 -234
  374. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-state.ts +0 -103
  375. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-types.ts +0 -29
  376. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +0 -9
  377. package/dist/builtin/subagents/src/runs/foreground/chain-execution-clarify.ts +0 -117
@@ -1 +1 @@
1
- {"version":3,"file":"context-compaction-critical.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-critical.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAKpI,eAAO,MAAM,4CAA4C,IAAI,CAAC;AAE9D,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,2BAA2B,GAAG,2BAA2B,CAKjH;AAED,wBAAgB,yCAAyC,CACxD,KAAK,EAAE,0BAA0B,EACjC,UAAU,EAAE,qBAAqB,GAC/B,OAAO,CAUT;AAED;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CAAC,UAAU,EAAE,qBAAqB,GAAG,qBAAqB,CAgB3G;AAED,eAAO,MAAM,2CAA2C,0iCAK9B,CAAC","sourcesContent":["import type { CompactableTranscript, CompactableTranscriptEntry, ContextCompactionParameters } from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { isTaskBearingEntry } from \"./context-deletion-targets.ts\";\nimport { hasAssistantError, hasFailedBashExecution, hasToolResultError } from \"./context-transcript-analysis.ts\";\n\nexport const CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT = 5;\n\nexport function criticalCompactionParameters(parameters: ContextCompactionParameters): ContextCompactionParameters {\n\treturn {\n\t\t...parameters,\n\t\tpreserve_recent: Math.max(parameters.preserve_recent, CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT),\n\t};\n}\n\nexport function isCriticalOverflowProtectedEntryDeletable(\n\tentry: CompactableTranscriptEntry,\n\ttranscript: CompactableTranscript,\n): boolean {\n\tif (!entry.protected) return true;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\tif (entryIndex < 0) return false;\n\tconst recentBoundary = Math.max(0, transcript.entries.length - CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT);\n\tif (entryIndex >= recentBoundary) return false;\n\tif (hasAssistantError(entry.message) || hasToolResultError(entry.message) || hasFailedBashExecution(entry.message)) {\n\t\treturn false;\n\t}\n\treturn isTaskBearingEntry(entry);\n}\n\n/**\n * Return a transcript for critical overflow passes. The effective recent guard is\n * widened to max(configured preserve_recent, 5) over all entries, restoring the\n * pre-#1399 critical-overflow last-5 floor through the existing recent-target\n * validation path. Only stale protected task-bearing entries outside that floor\n * are relaxed; `protectedEntryIds` is rebuilt from still-protected entries so\n * persisted results/events stay disjoint from deleted targets.\n */\nexport function relaxTranscriptForCriticalEviction(transcript: CompactableTranscript): CompactableTranscript {\n\tconst entries = transcript.entries.map((entry) => {\n\t\tif (!entry.protected || !isCriticalOverflowProtectedEntryDeletable(entry, transcript)) return entry;\n\t\treturn {\n\t\t\t...entry,\n\t\t\tprotected: false,\n\t\t\tcontentBlocks: entry.contentBlocks.map((block) => ({ ...block, protected: false })),\n\t\t};\n\t});\n\tconst parameters = criticalCompactionParameters(getTranscriptCompactionParameters(transcript));\n\treturn {\n\t\t...transcript,\n\t\tentries,\n\t\tparameters,\n\t\tprotectedEntryIds: entries.filter((entry) => entry.protected).map((entry) => entry.entryId),\n\t};\n}\n\nexport const CONTEXT_COMPACTION_CRITICAL_OVERFLOW_PROMPT = `\n<critical-overflow-mode>\nThe previous model request overflowed its context window. This is a critical LRU-style compaction pass. First delete stale unprotected context. If that is not enough, you may also delete the earliest formerly-protected entries or protected content shown in the manifest. Evict old low-signal context first, including old reasoning/thinking traces when they are not part of the latest retained assistant message, then older user/custom/summary context while preserving recent entries, unresolved errors, failed commands, and enough task-bearing context for the assistant to continue.\n\nSafety invariant: the latest retained assistant message cannot be modified when it contains content blocks with type \"thinking\" or \"redacted_thinking\". Do not delete, target, or suggest any content block in that latest thinking-bearing assistant message, including sibling text or tool-call blocks. Older non-latest thinking/redacted_thinking blocks may be deleted during critical overflow when validation allows it.\n</critical-overflow-mode>`;\n"]}
1
+ {"version":3,"file":"context-compaction-critical.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-critical.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAKpI,eAAO,MAAM,4CAA4C,IAAI,CAAC;AAE9D,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,2BAA2B,GAAG,2BAA2B,CAKjH;AAED,wBAAgB,yCAAyC,CACxD,KAAK,EAAE,0BAA0B,EACjC,UAAU,EAAE,qBAAqB,GAC/B,OAAO,CAUT;AAED;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CAAC,UAAU,EAAE,qBAAqB,GAAG,qBAAqB,CAgB3G;AAED,eAAO,MAAM,2CAA2C,w5CAK9B,CAAC","sourcesContent":["import type { CompactableTranscript, CompactableTranscriptEntry, ContextCompactionParameters } from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { isTaskBearingEntry } from \"./context-deletion-targets.ts\";\nimport { hasAssistantError, hasFailedBashExecution, hasToolResultError } from \"./context-transcript-analysis.ts\";\n\nexport const CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT = 5;\n\nexport function criticalCompactionParameters(parameters: ContextCompactionParameters): ContextCompactionParameters {\n\treturn {\n\t\t...parameters,\n\t\tpreserve_recent: Math.max(parameters.preserve_recent, CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT),\n\t};\n}\n\nexport function isCriticalOverflowProtectedEntryDeletable(\n\tentry: CompactableTranscriptEntry,\n\ttranscript: CompactableTranscript,\n): boolean {\n\tif (!entry.protected) return true;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\tif (entryIndex < 0) return false;\n\tconst recentBoundary = Math.max(0, transcript.entries.length - CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT);\n\tif (entryIndex >= recentBoundary) return false;\n\tif (hasAssistantError(entry.message) || hasToolResultError(entry.message) || hasFailedBashExecution(entry.message)) {\n\t\treturn false;\n\t}\n\treturn isTaskBearingEntry(entry);\n}\n\n/**\n * Return a transcript for critical overflow passes. The effective recent guard is\n * widened to max(configured preserve_recent, 5) over all entries, restoring the\n * pre-#1399 critical-overflow last-5 floor through the existing recent-target\n * validation path. Only stale protected task-bearing entries outside that floor\n * are relaxed; `protectedEntryIds` is rebuilt from still-protected entries so\n * persisted results/events stay disjoint from deleted targets.\n */\nexport function relaxTranscriptForCriticalEviction(transcript: CompactableTranscript): CompactableTranscript {\n\tconst entries = transcript.entries.map((entry) => {\n\t\tif (!entry.protected || !isCriticalOverflowProtectedEntryDeletable(entry, transcript)) return entry;\n\t\treturn {\n\t\t\t...entry,\n\t\t\tprotected: false,\n\t\t\tcontentBlocks: entry.contentBlocks.map((block) => ({ ...block, protected: false })),\n\t\t};\n\t});\n\tconst parameters = criticalCompactionParameters(getTranscriptCompactionParameters(transcript));\n\treturn {\n\t\t...transcript,\n\t\tentries,\n\t\tparameters,\n\t\tprotectedEntryIds: entries.filter((entry) => entry.protected).map((entry) => entry.entryId),\n\t};\n}\n\nexport const CONTEXT_COMPACTION_CRITICAL_OVERFLOW_PROMPT = `\n<critical-overflow-mode>\nThe previous model request overflowed its context window. This is a critical LRU-style compaction pass. First delete stale unprotected context. If that is not enough, you may also delete the earliest formerly-protected entries or protected content shown in the manifest. Evict old low-signal context first, then older user/custom/summary context while preserving recent entries, unresolved errors, failed commands, and enough task-bearing context for the assistant to continue.\n\nSafety invariant: each provider-visible user-like input starts a logical assistant tool-use turn: a non-empty user/custom input, a context-eligible bash execution, or a non-empty branch summary. Empty or whitespace-only user/custom inputs and empty branch summaries do not split turns; whitespace-only branch summaries remain visible through their wrapper. Assistant messages and intervening tool results remain in the turn until the next visible input. Never delete a thinking/redacted_thinking-bearing assistant entry from the current final logical turn; a trailing visible input without an assistant response makes the preceding assistant turn historical. For a completed historical turn, retain every thinking/redacted_thinking-bearing assistant entry or delete all of them as whole entries. Never retain a proper subset or partially delete a retained thinking-bearing assistant message.\n</critical-overflow-mode>`;\n"]}
@@ -50,8 +50,8 @@ export function relaxTranscriptForCriticalEviction(transcript) {
50
50
  }
51
51
  export const CONTEXT_COMPACTION_CRITICAL_OVERFLOW_PROMPT = `
52
52
  <critical-overflow-mode>
53
- The previous model request overflowed its context window. This is a critical LRU-style compaction pass. First delete stale unprotected context. If that is not enough, you may also delete the earliest formerly-protected entries or protected content shown in the manifest. Evict old low-signal context first, including old reasoning/thinking traces when they are not part of the latest retained assistant message, then older user/custom/summary context while preserving recent entries, unresolved errors, failed commands, and enough task-bearing context for the assistant to continue.
53
+ The previous model request overflowed its context window. This is a critical LRU-style compaction pass. First delete stale unprotected context. If that is not enough, you may also delete the earliest formerly-protected entries or protected content shown in the manifest. Evict old low-signal context first, then older user/custom/summary context while preserving recent entries, unresolved errors, failed commands, and enough task-bearing context for the assistant to continue.
54
54
 
55
- Safety invariant: the latest retained assistant message cannot be modified when it contains content blocks with type "thinking" or "redacted_thinking". Do not delete, target, or suggest any content block in that latest thinking-bearing assistant message, including sibling text or tool-call blocks. Older non-latest thinking/redacted_thinking blocks may be deleted during critical overflow when validation allows it.
55
+ Safety invariant: each provider-visible user-like input starts a logical assistant tool-use turn: a non-empty user/custom input, a context-eligible bash execution, or a non-empty branch summary. Empty or whitespace-only user/custom inputs and empty branch summaries do not split turns; whitespace-only branch summaries remain visible through their wrapper. Assistant messages and intervening tool results remain in the turn until the next visible input. Never delete a thinking/redacted_thinking-bearing assistant entry from the current final logical turn; a trailing visible input without an assistant response makes the preceding assistant turn historical. For a completed historical turn, retain every thinking/redacted_thinking-bearing assistant entry or delete all of them as whole entries. Never retain a proper subset or partially delete a retained thinking-bearing assistant message.
56
56
  </critical-overflow-mode>`;
57
57
  //# sourceMappingURL=context-compaction-critical.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-compaction-critical.js","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-critical.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEjH,MAAM,CAAC,MAAM,4CAA4C,GAAG,CAAC,CAAC;AAE9D,MAAM,UAAU,4BAA4B,CAAC,UAAuC;IACnF,OAAO;QACN,GAAG,UAAU;QACb,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,EAAE,4CAA4C,CAAC;KACnG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yCAAyC,CACxD,KAAiC,EACjC,UAAiC;IAEjC,IAAI,CAAC,KAAK,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAClC,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC;IACpG,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,4CAA4C,CAAC,CAAC;IAC7G,IAAI,UAAU,IAAI,cAAc;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACpH,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kCAAkC,CAAC,UAAiC;IACnF,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAChD,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,yCAAyC,CAAC,KAAK,EAAE,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QACpG,OAAO;YACN,GAAG,KAAK;YACR,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;SACnF,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,4BAA4B,CAAC,iCAAiC,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/F,OAAO;QACN,GAAG,UAAU;QACb,OAAO;QACP,UAAU;QACV,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;KAC3F,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,2CAA2C,GAAG;;;;;0BAKjC,CAAC","sourcesContent":["import type { CompactableTranscript, CompactableTranscriptEntry, ContextCompactionParameters } from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { isTaskBearingEntry } from \"./context-deletion-targets.ts\";\nimport { hasAssistantError, hasFailedBashExecution, hasToolResultError } from \"./context-transcript-analysis.ts\";\n\nexport const CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT = 5;\n\nexport function criticalCompactionParameters(parameters: ContextCompactionParameters): ContextCompactionParameters {\n\treturn {\n\t\t...parameters,\n\t\tpreserve_recent: Math.max(parameters.preserve_recent, CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT),\n\t};\n}\n\nexport function isCriticalOverflowProtectedEntryDeletable(\n\tentry: CompactableTranscriptEntry,\n\ttranscript: CompactableTranscript,\n): boolean {\n\tif (!entry.protected) return true;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\tif (entryIndex < 0) return false;\n\tconst recentBoundary = Math.max(0, transcript.entries.length - CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT);\n\tif (entryIndex >= recentBoundary) return false;\n\tif (hasAssistantError(entry.message) || hasToolResultError(entry.message) || hasFailedBashExecution(entry.message)) {\n\t\treturn false;\n\t}\n\treturn isTaskBearingEntry(entry);\n}\n\n/**\n * Return a transcript for critical overflow passes. The effective recent guard is\n * widened to max(configured preserve_recent, 5) over all entries, restoring the\n * pre-#1399 critical-overflow last-5 floor through the existing recent-target\n * validation path. Only stale protected task-bearing entries outside that floor\n * are relaxed; `protectedEntryIds` is rebuilt from still-protected entries so\n * persisted results/events stay disjoint from deleted targets.\n */\nexport function relaxTranscriptForCriticalEviction(transcript: CompactableTranscript): CompactableTranscript {\n\tconst entries = transcript.entries.map((entry) => {\n\t\tif (!entry.protected || !isCriticalOverflowProtectedEntryDeletable(entry, transcript)) return entry;\n\t\treturn {\n\t\t\t...entry,\n\t\t\tprotected: false,\n\t\t\tcontentBlocks: entry.contentBlocks.map((block) => ({ ...block, protected: false })),\n\t\t};\n\t});\n\tconst parameters = criticalCompactionParameters(getTranscriptCompactionParameters(transcript));\n\treturn {\n\t\t...transcript,\n\t\tentries,\n\t\tparameters,\n\t\tprotectedEntryIds: entries.filter((entry) => entry.protected).map((entry) => entry.entryId),\n\t};\n}\n\nexport const CONTEXT_COMPACTION_CRITICAL_OVERFLOW_PROMPT = `\n<critical-overflow-mode>\nThe previous model request overflowed its context window. This is a critical LRU-style compaction pass. First delete stale unprotected context. If that is not enough, you may also delete the earliest formerly-protected entries or protected content shown in the manifest. Evict old low-signal context first, including old reasoning/thinking traces when they are not part of the latest retained assistant message, then older user/custom/summary context while preserving recent entries, unresolved errors, failed commands, and enough task-bearing context for the assistant to continue.\n\nSafety invariant: the latest retained assistant message cannot be modified when it contains content blocks with type \"thinking\" or \"redacted_thinking\". Do not delete, target, or suggest any content block in that latest thinking-bearing assistant message, including sibling text or tool-call blocks. Older non-latest thinking/redacted_thinking blocks may be deleted during critical overflow when validation allows it.\n</critical-overflow-mode>`;\n"]}
1
+ {"version":3,"file":"context-compaction-critical.js","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-critical.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEjH,MAAM,CAAC,MAAM,4CAA4C,GAAG,CAAC,CAAC;AAE9D,MAAM,UAAU,4BAA4B,CAAC,UAAuC;IACnF,OAAO;QACN,GAAG,UAAU;QACb,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,EAAE,4CAA4C,CAAC;KACnG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yCAAyC,CACxD,KAAiC,EACjC,UAAiC;IAEjC,IAAI,CAAC,KAAK,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAClC,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC;IACpG,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,4CAA4C,CAAC,CAAC;IAC7G,IAAI,UAAU,IAAI,cAAc;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACpH,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kCAAkC,CAAC,UAAiC;IACnF,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAChD,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,yCAAyC,CAAC,KAAK,EAAE,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QACpG,OAAO;YACN,GAAG,KAAK;YACR,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;SACnF,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,4BAA4B,CAAC,iCAAiC,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/F,OAAO;QACN,GAAG,UAAU;QACb,OAAO;QACP,UAAU;QACV,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;KAC3F,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,2CAA2C,GAAG;;;;;0BAKjC,CAAC","sourcesContent":["import type { CompactableTranscript, CompactableTranscriptEntry, ContextCompactionParameters } from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { isTaskBearingEntry } from \"./context-deletion-targets.ts\";\nimport { hasAssistantError, hasFailedBashExecution, hasToolResultError } from \"./context-transcript-analysis.ts\";\n\nexport const CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT = 5;\n\nexport function criticalCompactionParameters(parameters: ContextCompactionParameters): ContextCompactionParameters {\n\treturn {\n\t\t...parameters,\n\t\tpreserve_recent: Math.max(parameters.preserve_recent, CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT),\n\t};\n}\n\nexport function isCriticalOverflowProtectedEntryDeletable(\n\tentry: CompactableTranscriptEntry,\n\ttranscript: CompactableTranscript,\n): boolean {\n\tif (!entry.protected) return true;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\tif (entryIndex < 0) return false;\n\tconst recentBoundary = Math.max(0, transcript.entries.length - CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT);\n\tif (entryIndex >= recentBoundary) return false;\n\tif (hasAssistantError(entry.message) || hasToolResultError(entry.message) || hasFailedBashExecution(entry.message)) {\n\t\treturn false;\n\t}\n\treturn isTaskBearingEntry(entry);\n}\n\n/**\n * Return a transcript for critical overflow passes. The effective recent guard is\n * widened to max(configured preserve_recent, 5) over all entries, restoring the\n * pre-#1399 critical-overflow last-5 floor through the existing recent-target\n * validation path. Only stale protected task-bearing entries outside that floor\n * are relaxed; `protectedEntryIds` is rebuilt from still-protected entries so\n * persisted results/events stay disjoint from deleted targets.\n */\nexport function relaxTranscriptForCriticalEviction(transcript: CompactableTranscript): CompactableTranscript {\n\tconst entries = transcript.entries.map((entry) => {\n\t\tif (!entry.protected || !isCriticalOverflowProtectedEntryDeletable(entry, transcript)) return entry;\n\t\treturn {\n\t\t\t...entry,\n\t\t\tprotected: false,\n\t\t\tcontentBlocks: entry.contentBlocks.map((block) => ({ ...block, protected: false })),\n\t\t};\n\t});\n\tconst parameters = criticalCompactionParameters(getTranscriptCompactionParameters(transcript));\n\treturn {\n\t\t...transcript,\n\t\tentries,\n\t\tparameters,\n\t\tprotectedEntryIds: entries.filter((entry) => entry.protected).map((entry) => entry.entryId),\n\t};\n}\n\nexport const CONTEXT_COMPACTION_CRITICAL_OVERFLOW_PROMPT = `\n<critical-overflow-mode>\nThe previous model request overflowed its context window. This is a critical LRU-style compaction pass. First delete stale unprotected context. If that is not enough, you may also delete the earliest formerly-protected entries or protected content shown in the manifest. Evict old low-signal context first, then older user/custom/summary context while preserving recent entries, unresolved errors, failed commands, and enough task-bearing context for the assistant to continue.\n\nSafety invariant: each provider-visible user-like input starts a logical assistant tool-use turn: a non-empty user/custom input, a context-eligible bash execution, or a non-empty branch summary. Empty or whitespace-only user/custom inputs and empty branch summaries do not split turns; whitespace-only branch summaries remain visible through their wrapper. Assistant messages and intervening tool results remain in the turn until the next visible input. Never delete a thinking/redacted_thinking-bearing assistant entry from the current final logical turn; a trailing visible input without an assistant response makes the preceding assistant turn historical. For a completed historical turn, retain every thinking/redacted_thinking-bearing assistant entry or delete all of them as whole entries. Never retain a proper subset or partially delete a retained thinking-bearing assistant message.\n</critical-overflow-mode>`;\n"]}
@@ -0,0 +1,18 @@
1
+ import type { ContextDeletionTarget } from "../session-manager.js";
2
+ import type { CompactableTranscript, ValidatedContextDeletionResult } from "./context-compaction-types.js";
3
+ export interface EvictionGroup {
4
+ entryIds: string[];
5
+ order: number;
6
+ tokens: number;
7
+ boundary: boolean;
8
+ }
9
+ export declare function hasFitBudget(result: ValidatedContextDeletionResult | undefined, tokenBudget: number): result is ValidatedContextDeletionResult;
10
+ export declare function assistantTurnsForTargets(transcript: CompactableTranscript, targets: readonly ContextDeletionTarget[]): import("./context-assistant-turns.js").AssistantToolUseTurn[];
11
+ export declare function repairSignedTurnTargets(transcript: CompactableTranscript, targets: readonly ContextDeletionTarget[]): ContextDeletionTarget[];
12
+ export declare function targetsWithGroup(planned: readonly ContextDeletionTarget[], entryIds: readonly string[]): ContextDeletionTarget[];
13
+ export declare function validateTargets(transcript: CompactableTranscript, targets: readonly ContextDeletionTarget[]): ValidatedContextDeletionResult | undefined;
14
+ export declare function tryGroup(transcript: CompactableTranscript, planned: readonly ContextDeletionTarget[], group: EvictionGroup, repairBoundary: boolean): ValidatedContextDeletionResult | undefined;
15
+ export declare function currentHistoricalSignedGroups(transcript: CompactableTranscript, planned: readonly ContextDeletionTarget[]): EvictionGroup[];
16
+ export declare function skippedBoundaryRestorationGroups(transcript: CompactableTranscript, planned: readonly ContextDeletionTarget[], skipped: readonly EvictionGroup[]): EvictionGroup[][];
17
+ export declare function alternateBoundaryPlan(transcript: CompactableTranscript, initialTargets: readonly ContextDeletionTarget[], initialResult: ValidatedContextDeletionResult | undefined, groups: readonly EvictionGroup[], tokenBudget: number): ValidatedContextDeletionResult | undefined;
18
+ //# sourceMappingURL=context-compaction-eviction-alternates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-compaction-eviction-alternates.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-eviction-alternates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAQ3G,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,YAAY,CAC3B,MAAM,EAAE,8BAA8B,GAAG,SAAS,EAClD,WAAW,EAAE,MAAM,GACjB,MAAM,IAAI,8BAA8B,CAE1C;AAED,wBAAgB,wBAAwB,CACvC,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,iEAGzC;AAED,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,GACvC,qBAAqB,EAAE,CA0BzB;AAED,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,QAAQ,EAAE,SAAS,MAAM,EAAE,GACzB,qBAAqB,EAAE,CAQzB;AAED,wBAAgB,eAAe,CAC9B,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,GACvC,8BAA8B,GAAG,SAAS,CAmB5C;AAED,wBAAgB,QAAQ,CACvB,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,KAAK,EAAE,aAAa,EACpB,cAAc,EAAE,OAAO,GACrB,8BAA8B,GAAG,SAAS,CAU5C;AAED,wBAAgB,6BAA6B,CAC5C,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,GACvC,aAAa,EAAE,CAejB;AA0BD,wBAAgB,gCAAgC,CAC/C,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,OAAO,EAAE,SAAS,aAAa,EAAE,GAC/B,aAAa,EAAE,EAAE,CAUnB;AA8BD,wBAAgB,qBAAqB,CACpC,UAAU,EAAE,qBAAqB,EACjC,cAAc,EAAE,SAAS,qBAAqB,EAAE,EAChD,aAAa,EAAE,8BAA8B,GAAG,SAAS,EACzD,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,WAAW,EAAE,MAAM,GACjB,8BAA8B,GAAG,SAAS,CAuC5C","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.js\";\nimport { analyzeCompactableAssistantTurns } from \"./context-assistant-turns.js\";\nimport type { CompactableTranscript, ValidatedContextDeletionResult } from \"./context-compaction-types.js\";\nimport { reconcileToolDependencies, validateContextDeletionRequest } from \"./context-deletion-application.js\";\nimport {\n\tcanDeleteTarget,\n\tdeletionRequestFromTargets,\n\tgetDeletedEntryIds,\n} from \"./context-deletion-targets.js\";\n\nexport interface EvictionGroup {\n\tentryIds: string[];\n\torder: number;\n\ttokens: number;\n\tboundary: boolean;\n}\n\nexport function hasFitBudget(\n\tresult: ValidatedContextDeletionResult | undefined,\n\ttokenBudget: number,\n): result is ValidatedContextDeletionResult {\n\treturn result !== undefined && result.deletedTargets.length > 0 && result.stats.tokensAfter <= tokenBudget;\n}\n\nexport function assistantTurnsForTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n) {\n\treturn analyzeCompactableAssistantTurns(transcript, targets).turns;\n}\n\nexport function repairSignedTurnTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget[] {\n\tconst reconciled = reconcileToolDependencies(transcript, targets);\n\tconst deletedEntryIds = getDeletedEntryIds(reconciled);\n\tconst restoredSignedIds = new Set<string>();\n\tfor (const turn of assistantTurnsForTargets(transcript, reconciled)) {\n\t\tconst deleted = turn.signedThinkingEntryIds.filter((entryId) => deletedEntryIds.has(entryId));\n\t\tif (deleted.length === 0) continue;\n\t\tif (!turn.active && deleted.length === turn.signedThinkingEntryIds.length) continue;\n\t\tfor (const entryId of turn.signedThinkingEntryIds) restoredSignedIds.add(entryId);\n\t}\n\tif (restoredSignedIds.size === 0) return reconciled;\n\n\tconst restoredCallIds = new Set<string>();\n\tfor (const entry of transcript.entries) {\n\t\tif (!restoredSignedIds.has(entry.entryId)) continue;\n\t\tfor (const callId of entry.toolCallIds) restoredCallIds.add(callId);\n\t}\n\tconst restoredResultIds = new Set(\n\t\ttranscript.entries\n\t\t\t.filter((entry) => entry.toolResultFor && restoredCallIds.has(entry.toolResultFor))\n\t\t\t.map((entry) => entry.entryId),\n\t);\n\treturn reconcileToolDependencies(\n\t\ttranscript,\n\t\treconciled.filter((target) => !restoredSignedIds.has(target.entryId) && !restoredResultIds.has(target.entryId)),\n\t);\n}\n\nexport function targetsWithGroup(\n\tplanned: readonly ContextDeletionTarget[],\n\tentryIds: readonly string[],\n): ContextDeletionTarget[] {\n\tconst deleted = getDeletedEntryIds(planned);\n\treturn [\n\t\t...planned,\n\t\t...entryIds\n\t\t\t.filter((entryId) => !deleted.has(entryId))\n\t\t\t.map((entryId): ContextDeletionTarget => ({ kind: \"entry\", entryId })),\n\t];\n}\n\nexport function validateTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ValidatedContextDeletionResult | undefined {\n\ttry {\n\t\tconst result = validateContextDeletionRequest(deletionRequestFromTargets(targets), transcript);\n\t\tconst order = new Map(transcript.entries.map((entry, index) => [entry.entryId, index]));\n\t\treturn {\n\t\t\t...result,\n\t\t\tdeletedTargets: [...result.deletedTargets].sort((left, right) => {\n\t\t\t\tconst entryDelta =\n\t\t\t\t\t(order.get(left.entryId) ?? Number.MAX_SAFE_INTEGER) -\n\t\t\t\t\t(order.get(right.entryId) ?? Number.MAX_SAFE_INTEGER);\n\t\t\t\tif (entryDelta !== 0) return entryDelta;\n\t\t\t\tconst leftBlock = left.kind === \"content_block\" ? left.blockIndex : -1;\n\t\t\t\tconst rightBlock = right.kind === \"content_block\" ? right.blockIndex : -1;\n\t\t\t\treturn leftBlock - rightBlock;\n\t\t\t}),\n\t\t};\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function tryGroup(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tgroup: EvictionGroup,\n\trepairBoundary: boolean,\n): ValidatedContextDeletionResult | undefined {\n\tconst directTargets = targetsWithGroup(planned, group.entryIds);\n\tconst direct = validateTargets(transcript, directTargets);\n\tif (direct) return direct;\n\tif (!repairBoundary) return undefined;\n\tconst repaired = repairSignedTurnTargets(transcript, directTargets);\n\tconst result = validateTargets(transcript, repaired);\n\tif (!result) return undefined;\n\tconst deleted = getDeletedEntryIds(result.deletedTargets);\n\treturn group.entryIds.every((entryId) => deleted.has(entryId)) ? result : undefined;\n}\n\nexport function currentHistoricalSignedGroups(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n): EvictionGroup[] {\n\tconst deleted = getDeletedEntryIds(planned);\n\tconst order = new Map(transcript.entries.map((entry, index) => [entry.entryId, index]));\n\tconst tokens = new Map(transcript.entries.map((entry) => [entry.entryId, entry.tokenEstimate]));\n\treturn assistantTurnsForTargets(transcript, planned)\n\t\t.filter((turn) => !turn.active)\n\t\t.map((turn) => turn.signedThinkingEntryIds.filter((entryId) => !deleted.has(entryId)))\n\t\t.filter((entryIds) => entryIds.length > 0)\n\t\t.filter((entryIds) => entryIds.every((entryId) => canDeleteTarget(transcript, { kind: \"entry\", entryId })))\n\t\t.map((entryIds) => ({\n\t\t\tentryIds,\n\t\t\torder: order.get(entryIds[0]!) ?? Number.MAX_SAFE_INTEGER,\n\t\t\ttokens: entryIds.reduce((sum, entryId) => sum + (tokens.get(entryId) ?? 0), 0),\n\t\t\tboundary: false,\n\t\t}));\n}\n\nfunction targetIdentity(target: ContextDeletionTarget): string {\n\treturn target.kind === \"entry\"\n\t\t? `entry:${target.entryId}`\n\t\t: `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nfunction boundaryRestorationSignature(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tgroup: EvictionGroup,\n): string | undefined {\n\ttry {\n\t\tconst repaired = repairSignedTurnTargets(transcript, targetsWithGroup(planned, group.entryIds));\n\t\tconst retainedKeys = new Set(repaired.map(targetIdentity));\n\t\tconst restoredKeys = planned\n\t\t\t.map(targetIdentity)\n\t\t\t.filter((key) => !retainedKeys.has(key))\n\t\t\t.sort();\n\t\treturn restoredKeys.length > 0 ? restoredKeys.join(\"|\") : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function skippedBoundaryRestorationGroups(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tskipped: readonly EvictionGroup[],\n): EvictionGroup[][] {\n\tconst bySignature = new Map<string, EvictionGroup[]>();\n\tfor (const group of skipped) {\n\t\tconst signature = boundaryRestorationSignature(transcript, planned, group);\n\t\tif (!signature) continue;\n\t\tconst matches = bySignature.get(signature) ?? [];\n\t\tmatches.push(group);\n\t\tbySignature.set(signature, matches);\n\t}\n\treturn [...bySignature.values()].filter((groups) => groups.length > 1);\n}\n\ninterface AlternateBoundaryState {\n\ttargets: ContextDeletionTarget[];\n\ttokensAfter: number;\n\tsignature: string;\n}\n\nfunction deletionPlanSignature(targets: readonly ContextDeletionTarget[]): string {\n\treturn targets.map(targetIdentity).sort().join(\"|\");\n}\n\nconst ALTERNATE_BOUNDARY_STATE_LIMIT = 16;\n\nfunction retainBoundedAlternateStates(states: readonly AlternateBoundaryState[]): AlternateBoundaryState[] {\n\tconst deduplicated = [...new Map(states.map((state) => [state.signature, state])).values()].sort(\n\t\t(left, right) => left.tokensAfter - right.tokensAfter || left.signature.localeCompare(right.signature),\n\t);\n\t// Retain both near-fit and less-committed plans so different turn topologies survive the bounded search.\n\tif (deduplicated.length <= ALTERNATE_BOUNDARY_STATE_LIMIT) return deduplicated;\n\n\tconst retained: AlternateBoundaryState[] = [];\n\tfor (let index = 0; index < ALTERNATE_BOUNDARY_STATE_LIMIT / 2; index++) {\n\t\tretained.push(deduplicated[index]!, deduplicated[deduplicated.length - 1 - index]!);\n\t}\n\treturn retained.sort(\n\t\t(left, right) => left.tokensAfter - right.tokensAfter || left.signature.localeCompare(right.signature),\n\t);\n}\n\nexport function alternateBoundaryPlan(\n\ttranscript: CompactableTranscript,\n\tinitialTargets: readonly ContextDeletionTarget[],\n\tinitialResult: ValidatedContextDeletionResult | undefined,\n\tgroups: readonly EvictionGroup[],\n\ttokenBudget: number,\n): ValidatedContextDeletionResult | undefined {\n\tlet states: AlternateBoundaryState[] = [\n\t\t{\n\t\t\ttargets: [...initialTargets],\n\t\t\ttokensAfter: initialResult?.stats.tokensAfter ?? transcript.tokensBefore,\n\t\t\tsignature: deletionPlanSignature(initialTargets),\n\t\t},\n\t];\n\n\tfor (const group of groups) {\n\t\tconst expanded = [...states];\n\t\tlet fitting: ValidatedContextDeletionResult | undefined;\n\t\tfor (const state of states) {\n\t\t\tconst result = tryGroup(transcript, state.targets, group, true);\n\t\t\tif (!result) continue;\n\t\t\tif (result.deletedTargets.length > 0 && result.stats.tokensAfter <= tokenBudget) {\n\t\t\t\tif (!fitting || result.stats.tokensAfter > fitting.stats.tokensAfter) fitting = result;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\texpanded.push({\n\t\t\t\ttargets: [...result.deletedTargets],\n\t\t\t\ttokensAfter: result.stats.tokensAfter,\n\t\t\t\tsignature: deletionPlanSignature(result.deletedTargets),\n\t\t\t});\n\t\t}\n\t\tif (fitting) return fitting;\n\t\tstates = retainBoundedAlternateStates(expanded);\n\t}\n\n\tfor (const state of states) {\n\t\tlet targets = state.targets;\n\t\tfor (const group of currentHistoricalSignedGroups(transcript, targets)) {\n\t\t\tconst result = tryGroup(transcript, targets, group, false);\n\t\t\tif (!result) continue;\n\t\t\ttargets = [...result.deletedTargets];\n\t\t\tif (hasFitBudget(result, tokenBudget)) return result;\n\t\t}\n\t}\n\treturn undefined;\n}\n"]}
@@ -0,0 +1,186 @@
1
+ import { analyzeCompactableAssistantTurns } from "./context-assistant-turns.js";
2
+ import { reconcileToolDependencies, validateContextDeletionRequest } from "./context-deletion-application.js";
3
+ import { canDeleteTarget, deletionRequestFromTargets, getDeletedEntryIds, } from "./context-deletion-targets.js";
4
+ export function hasFitBudget(result, tokenBudget) {
5
+ return result !== undefined && result.deletedTargets.length > 0 && result.stats.tokensAfter <= tokenBudget;
6
+ }
7
+ export function assistantTurnsForTargets(transcript, targets) {
8
+ return analyzeCompactableAssistantTurns(transcript, targets).turns;
9
+ }
10
+ export function repairSignedTurnTargets(transcript, targets) {
11
+ const reconciled = reconcileToolDependencies(transcript, targets);
12
+ const deletedEntryIds = getDeletedEntryIds(reconciled);
13
+ const restoredSignedIds = new Set();
14
+ for (const turn of assistantTurnsForTargets(transcript, reconciled)) {
15
+ const deleted = turn.signedThinkingEntryIds.filter((entryId) => deletedEntryIds.has(entryId));
16
+ if (deleted.length === 0)
17
+ continue;
18
+ if (!turn.active && deleted.length === turn.signedThinkingEntryIds.length)
19
+ continue;
20
+ for (const entryId of turn.signedThinkingEntryIds)
21
+ restoredSignedIds.add(entryId);
22
+ }
23
+ if (restoredSignedIds.size === 0)
24
+ return reconciled;
25
+ const restoredCallIds = new Set();
26
+ for (const entry of transcript.entries) {
27
+ if (!restoredSignedIds.has(entry.entryId))
28
+ continue;
29
+ for (const callId of entry.toolCallIds)
30
+ restoredCallIds.add(callId);
31
+ }
32
+ const restoredResultIds = new Set(transcript.entries
33
+ .filter((entry) => entry.toolResultFor && restoredCallIds.has(entry.toolResultFor))
34
+ .map((entry) => entry.entryId));
35
+ return reconcileToolDependencies(transcript, reconciled.filter((target) => !restoredSignedIds.has(target.entryId) && !restoredResultIds.has(target.entryId)));
36
+ }
37
+ export function targetsWithGroup(planned, entryIds) {
38
+ const deleted = getDeletedEntryIds(planned);
39
+ return [
40
+ ...planned,
41
+ ...entryIds
42
+ .filter((entryId) => !deleted.has(entryId))
43
+ .map((entryId) => ({ kind: "entry", entryId })),
44
+ ];
45
+ }
46
+ export function validateTargets(transcript, targets) {
47
+ try {
48
+ const result = validateContextDeletionRequest(deletionRequestFromTargets(targets), transcript);
49
+ const order = new Map(transcript.entries.map((entry, index) => [entry.entryId, index]));
50
+ return {
51
+ ...result,
52
+ deletedTargets: [...result.deletedTargets].sort((left, right) => {
53
+ const entryDelta = (order.get(left.entryId) ?? Number.MAX_SAFE_INTEGER) -
54
+ (order.get(right.entryId) ?? Number.MAX_SAFE_INTEGER);
55
+ if (entryDelta !== 0)
56
+ return entryDelta;
57
+ const leftBlock = left.kind === "content_block" ? left.blockIndex : -1;
58
+ const rightBlock = right.kind === "content_block" ? right.blockIndex : -1;
59
+ return leftBlock - rightBlock;
60
+ }),
61
+ };
62
+ }
63
+ catch {
64
+ return undefined;
65
+ }
66
+ }
67
+ export function tryGroup(transcript, planned, group, repairBoundary) {
68
+ const directTargets = targetsWithGroup(planned, group.entryIds);
69
+ const direct = validateTargets(transcript, directTargets);
70
+ if (direct)
71
+ return direct;
72
+ if (!repairBoundary)
73
+ return undefined;
74
+ const repaired = repairSignedTurnTargets(transcript, directTargets);
75
+ const result = validateTargets(transcript, repaired);
76
+ if (!result)
77
+ return undefined;
78
+ const deleted = getDeletedEntryIds(result.deletedTargets);
79
+ return group.entryIds.every((entryId) => deleted.has(entryId)) ? result : undefined;
80
+ }
81
+ export function currentHistoricalSignedGroups(transcript, planned) {
82
+ const deleted = getDeletedEntryIds(planned);
83
+ const order = new Map(transcript.entries.map((entry, index) => [entry.entryId, index]));
84
+ const tokens = new Map(transcript.entries.map((entry) => [entry.entryId, entry.tokenEstimate]));
85
+ return assistantTurnsForTargets(transcript, planned)
86
+ .filter((turn) => !turn.active)
87
+ .map((turn) => turn.signedThinkingEntryIds.filter((entryId) => !deleted.has(entryId)))
88
+ .filter((entryIds) => entryIds.length > 0)
89
+ .filter((entryIds) => entryIds.every((entryId) => canDeleteTarget(transcript, { kind: "entry", entryId })))
90
+ .map((entryIds) => ({
91
+ entryIds,
92
+ order: order.get(entryIds[0]) ?? Number.MAX_SAFE_INTEGER,
93
+ tokens: entryIds.reduce((sum, entryId) => sum + (tokens.get(entryId) ?? 0), 0),
94
+ boundary: false,
95
+ }));
96
+ }
97
+ function targetIdentity(target) {
98
+ return target.kind === "entry"
99
+ ? `entry:${target.entryId}`
100
+ : `content_block:${target.entryId}:${target.blockIndex}`;
101
+ }
102
+ function boundaryRestorationSignature(transcript, planned, group) {
103
+ try {
104
+ const repaired = repairSignedTurnTargets(transcript, targetsWithGroup(planned, group.entryIds));
105
+ const retainedKeys = new Set(repaired.map(targetIdentity));
106
+ const restoredKeys = planned
107
+ .map(targetIdentity)
108
+ .filter((key) => !retainedKeys.has(key))
109
+ .sort();
110
+ return restoredKeys.length > 0 ? restoredKeys.join("|") : undefined;
111
+ }
112
+ catch {
113
+ return undefined;
114
+ }
115
+ }
116
+ export function skippedBoundaryRestorationGroups(transcript, planned, skipped) {
117
+ const bySignature = new Map();
118
+ for (const group of skipped) {
119
+ const signature = boundaryRestorationSignature(transcript, planned, group);
120
+ if (!signature)
121
+ continue;
122
+ const matches = bySignature.get(signature) ?? [];
123
+ matches.push(group);
124
+ bySignature.set(signature, matches);
125
+ }
126
+ return [...bySignature.values()].filter((groups) => groups.length > 1);
127
+ }
128
+ function deletionPlanSignature(targets) {
129
+ return targets.map(targetIdentity).sort().join("|");
130
+ }
131
+ const ALTERNATE_BOUNDARY_STATE_LIMIT = 16;
132
+ function retainBoundedAlternateStates(states) {
133
+ const deduplicated = [...new Map(states.map((state) => [state.signature, state])).values()].sort((left, right) => left.tokensAfter - right.tokensAfter || left.signature.localeCompare(right.signature));
134
+ // Retain both near-fit and less-committed plans so different turn topologies survive the bounded search.
135
+ if (deduplicated.length <= ALTERNATE_BOUNDARY_STATE_LIMIT)
136
+ return deduplicated;
137
+ const retained = [];
138
+ for (let index = 0; index < ALTERNATE_BOUNDARY_STATE_LIMIT / 2; index++) {
139
+ retained.push(deduplicated[index], deduplicated[deduplicated.length - 1 - index]);
140
+ }
141
+ return retained.sort((left, right) => left.tokensAfter - right.tokensAfter || left.signature.localeCompare(right.signature));
142
+ }
143
+ export function alternateBoundaryPlan(transcript, initialTargets, initialResult, groups, tokenBudget) {
144
+ let states = [
145
+ {
146
+ targets: [...initialTargets],
147
+ tokensAfter: initialResult?.stats.tokensAfter ?? transcript.tokensBefore,
148
+ signature: deletionPlanSignature(initialTargets),
149
+ },
150
+ ];
151
+ for (const group of groups) {
152
+ const expanded = [...states];
153
+ let fitting;
154
+ for (const state of states) {
155
+ const result = tryGroup(transcript, state.targets, group, true);
156
+ if (!result)
157
+ continue;
158
+ if (result.deletedTargets.length > 0 && result.stats.tokensAfter <= tokenBudget) {
159
+ if (!fitting || result.stats.tokensAfter > fitting.stats.tokensAfter)
160
+ fitting = result;
161
+ continue;
162
+ }
163
+ expanded.push({
164
+ targets: [...result.deletedTargets],
165
+ tokensAfter: result.stats.tokensAfter,
166
+ signature: deletionPlanSignature(result.deletedTargets),
167
+ });
168
+ }
169
+ if (fitting)
170
+ return fitting;
171
+ states = retainBoundedAlternateStates(expanded);
172
+ }
173
+ for (const state of states) {
174
+ let targets = state.targets;
175
+ for (const group of currentHistoricalSignedGroups(transcript, targets)) {
176
+ const result = tryGroup(transcript, targets, group, false);
177
+ if (!result)
178
+ continue;
179
+ targets = [...result.deletedTargets];
180
+ if (hasFitBudget(result, tokenBudget))
181
+ return result;
182
+ }
183
+ }
184
+ return undefined;
185
+ }
186
+ //# sourceMappingURL=context-compaction-eviction-alternates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-compaction-eviction-alternates.js","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-eviction-alternates.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.js\";\nimport { analyzeCompactableAssistantTurns } from \"./context-assistant-turns.js\";\nimport type { CompactableTranscript, ValidatedContextDeletionResult } from \"./context-compaction-types.js\";\nimport { reconcileToolDependencies, validateContextDeletionRequest } from \"./context-deletion-application.js\";\nimport {\n\tcanDeleteTarget,\n\tdeletionRequestFromTargets,\n\tgetDeletedEntryIds,\n} from \"./context-deletion-targets.js\";\n\nexport interface EvictionGroup {\n\tentryIds: string[];\n\torder: number;\n\ttokens: number;\n\tboundary: boolean;\n}\n\nexport function hasFitBudget(\n\tresult: ValidatedContextDeletionResult | undefined,\n\ttokenBudget: number,\n): result is ValidatedContextDeletionResult {\n\treturn result !== undefined && result.deletedTargets.length > 0 && result.stats.tokensAfter <= tokenBudget;\n}\n\nexport function assistantTurnsForTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n) {\n\treturn analyzeCompactableAssistantTurns(transcript, targets).turns;\n}\n\nexport function repairSignedTurnTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget[] {\n\tconst reconciled = reconcileToolDependencies(transcript, targets);\n\tconst deletedEntryIds = getDeletedEntryIds(reconciled);\n\tconst restoredSignedIds = new Set<string>();\n\tfor (const turn of assistantTurnsForTargets(transcript, reconciled)) {\n\t\tconst deleted = turn.signedThinkingEntryIds.filter((entryId) => deletedEntryIds.has(entryId));\n\t\tif (deleted.length === 0) continue;\n\t\tif (!turn.active && deleted.length === turn.signedThinkingEntryIds.length) continue;\n\t\tfor (const entryId of turn.signedThinkingEntryIds) restoredSignedIds.add(entryId);\n\t}\n\tif (restoredSignedIds.size === 0) return reconciled;\n\n\tconst restoredCallIds = new Set<string>();\n\tfor (const entry of transcript.entries) {\n\t\tif (!restoredSignedIds.has(entry.entryId)) continue;\n\t\tfor (const callId of entry.toolCallIds) restoredCallIds.add(callId);\n\t}\n\tconst restoredResultIds = new Set(\n\t\ttranscript.entries\n\t\t\t.filter((entry) => entry.toolResultFor && restoredCallIds.has(entry.toolResultFor))\n\t\t\t.map((entry) => entry.entryId),\n\t);\n\treturn reconcileToolDependencies(\n\t\ttranscript,\n\t\treconciled.filter((target) => !restoredSignedIds.has(target.entryId) && !restoredResultIds.has(target.entryId)),\n\t);\n}\n\nexport function targetsWithGroup(\n\tplanned: readonly ContextDeletionTarget[],\n\tentryIds: readonly string[],\n): ContextDeletionTarget[] {\n\tconst deleted = getDeletedEntryIds(planned);\n\treturn [\n\t\t...planned,\n\t\t...entryIds\n\t\t\t.filter((entryId) => !deleted.has(entryId))\n\t\t\t.map((entryId): ContextDeletionTarget => ({ kind: \"entry\", entryId })),\n\t];\n}\n\nexport function validateTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ValidatedContextDeletionResult | undefined {\n\ttry {\n\t\tconst result = validateContextDeletionRequest(deletionRequestFromTargets(targets), transcript);\n\t\tconst order = new Map(transcript.entries.map((entry, index) => [entry.entryId, index]));\n\t\treturn {\n\t\t\t...result,\n\t\t\tdeletedTargets: [...result.deletedTargets].sort((left, right) => {\n\t\t\t\tconst entryDelta =\n\t\t\t\t\t(order.get(left.entryId) ?? Number.MAX_SAFE_INTEGER) -\n\t\t\t\t\t(order.get(right.entryId) ?? Number.MAX_SAFE_INTEGER);\n\t\t\t\tif (entryDelta !== 0) return entryDelta;\n\t\t\t\tconst leftBlock = left.kind === \"content_block\" ? left.blockIndex : -1;\n\t\t\t\tconst rightBlock = right.kind === \"content_block\" ? right.blockIndex : -1;\n\t\t\t\treturn leftBlock - rightBlock;\n\t\t\t}),\n\t\t};\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function tryGroup(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tgroup: EvictionGroup,\n\trepairBoundary: boolean,\n): ValidatedContextDeletionResult | undefined {\n\tconst directTargets = targetsWithGroup(planned, group.entryIds);\n\tconst direct = validateTargets(transcript, directTargets);\n\tif (direct) return direct;\n\tif (!repairBoundary) return undefined;\n\tconst repaired = repairSignedTurnTargets(transcript, directTargets);\n\tconst result = validateTargets(transcript, repaired);\n\tif (!result) return undefined;\n\tconst deleted = getDeletedEntryIds(result.deletedTargets);\n\treturn group.entryIds.every((entryId) => deleted.has(entryId)) ? result : undefined;\n}\n\nexport function currentHistoricalSignedGroups(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n): EvictionGroup[] {\n\tconst deleted = getDeletedEntryIds(planned);\n\tconst order = new Map(transcript.entries.map((entry, index) => [entry.entryId, index]));\n\tconst tokens = new Map(transcript.entries.map((entry) => [entry.entryId, entry.tokenEstimate]));\n\treturn assistantTurnsForTargets(transcript, planned)\n\t\t.filter((turn) => !turn.active)\n\t\t.map((turn) => turn.signedThinkingEntryIds.filter((entryId) => !deleted.has(entryId)))\n\t\t.filter((entryIds) => entryIds.length > 0)\n\t\t.filter((entryIds) => entryIds.every((entryId) => canDeleteTarget(transcript, { kind: \"entry\", entryId })))\n\t\t.map((entryIds) => ({\n\t\t\tentryIds,\n\t\t\torder: order.get(entryIds[0]!) ?? Number.MAX_SAFE_INTEGER,\n\t\t\ttokens: entryIds.reduce((sum, entryId) => sum + (tokens.get(entryId) ?? 0), 0),\n\t\t\tboundary: false,\n\t\t}));\n}\n\nfunction targetIdentity(target: ContextDeletionTarget): string {\n\treturn target.kind === \"entry\"\n\t\t? `entry:${target.entryId}`\n\t\t: `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nfunction boundaryRestorationSignature(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tgroup: EvictionGroup,\n): string | undefined {\n\ttry {\n\t\tconst repaired = repairSignedTurnTargets(transcript, targetsWithGroup(planned, group.entryIds));\n\t\tconst retainedKeys = new Set(repaired.map(targetIdentity));\n\t\tconst restoredKeys = planned\n\t\t\t.map(targetIdentity)\n\t\t\t.filter((key) => !retainedKeys.has(key))\n\t\t\t.sort();\n\t\treturn restoredKeys.length > 0 ? restoredKeys.join(\"|\") : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function skippedBoundaryRestorationGroups(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tskipped: readonly EvictionGroup[],\n): EvictionGroup[][] {\n\tconst bySignature = new Map<string, EvictionGroup[]>();\n\tfor (const group of skipped) {\n\t\tconst signature = boundaryRestorationSignature(transcript, planned, group);\n\t\tif (!signature) continue;\n\t\tconst matches = bySignature.get(signature) ?? [];\n\t\tmatches.push(group);\n\t\tbySignature.set(signature, matches);\n\t}\n\treturn [...bySignature.values()].filter((groups) => groups.length > 1);\n}\n\ninterface AlternateBoundaryState {\n\ttargets: ContextDeletionTarget[];\n\ttokensAfter: number;\n\tsignature: string;\n}\n\nfunction deletionPlanSignature(targets: readonly ContextDeletionTarget[]): string {\n\treturn targets.map(targetIdentity).sort().join(\"|\");\n}\n\nconst ALTERNATE_BOUNDARY_STATE_LIMIT = 16;\n\nfunction retainBoundedAlternateStates(states: readonly AlternateBoundaryState[]): AlternateBoundaryState[] {\n\tconst deduplicated = [...new Map(states.map((state) => [state.signature, state])).values()].sort(\n\t\t(left, right) => left.tokensAfter - right.tokensAfter || left.signature.localeCompare(right.signature),\n\t);\n\t// Retain both near-fit and less-committed plans so different turn topologies survive the bounded search.\n\tif (deduplicated.length <= ALTERNATE_BOUNDARY_STATE_LIMIT) return deduplicated;\n\n\tconst retained: AlternateBoundaryState[] = [];\n\tfor (let index = 0; index < ALTERNATE_BOUNDARY_STATE_LIMIT / 2; index++) {\n\t\tretained.push(deduplicated[index]!, deduplicated[deduplicated.length - 1 - index]!);\n\t}\n\treturn retained.sort(\n\t\t(left, right) => left.tokensAfter - right.tokensAfter || left.signature.localeCompare(right.signature),\n\t);\n}\n\nexport function alternateBoundaryPlan(\n\ttranscript: CompactableTranscript,\n\tinitialTargets: readonly ContextDeletionTarget[],\n\tinitialResult: ValidatedContextDeletionResult | undefined,\n\tgroups: readonly EvictionGroup[],\n\ttokenBudget: number,\n): ValidatedContextDeletionResult | undefined {\n\tlet states: AlternateBoundaryState[] = [\n\t\t{\n\t\t\ttargets: [...initialTargets],\n\t\t\ttokensAfter: initialResult?.stats.tokensAfter ?? transcript.tokensBefore,\n\t\t\tsignature: deletionPlanSignature(initialTargets),\n\t\t},\n\t];\n\n\tfor (const group of groups) {\n\t\tconst expanded = [...states];\n\t\tlet fitting: ValidatedContextDeletionResult | undefined;\n\t\tfor (const state of states) {\n\t\t\tconst result = tryGroup(transcript, state.targets, group, true);\n\t\t\tif (!result) continue;\n\t\t\tif (result.deletedTargets.length > 0 && result.stats.tokensAfter <= tokenBudget) {\n\t\t\t\tif (!fitting || result.stats.tokensAfter > fitting.stats.tokensAfter) fitting = result;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\texpanded.push({\n\t\t\t\ttargets: [...result.deletedTargets],\n\t\t\t\ttokensAfter: result.stats.tokensAfter,\n\t\t\t\tsignature: deletionPlanSignature(result.deletedTargets),\n\t\t\t});\n\t\t}\n\t\tif (fitting) return fitting;\n\t\tstates = retainBoundedAlternateStates(expanded);\n\t}\n\n\tfor (const state of states) {\n\t\tlet targets = state.targets;\n\t\tfor (const group of currentHistoricalSignedGroups(transcript, targets)) {\n\t\t\tconst result = tryGroup(transcript, targets, group, false);\n\t\t\tif (!result) continue;\n\t\t\ttargets = [...result.deletedTargets];\n\t\t\tif (hasFitBudget(result, tokenBudget)) return result;\n\t\t}\n\t}\n\treturn undefined;\n}\n"]}
@@ -1,4 +1,12 @@
1
- import type { CompactableTranscript, ValidatedContextDeletionResult } from "./context-compaction-types.ts";
2
- export declare const CONTEXT_COMPACTION_MAX_EVICTION_PASSES = 50;
1
+ import type { CompactableTranscript, ValidatedContextDeletionResult } from "./context-compaction-types.js";
2
+ /**
3
+ * Finite deterministic eviction phases:
4
+ * 1. Batch or sweep non-boundary groups in transcript order.
5
+ * 2. Try repaired boundary prefixes, then individual boundaries by token value.
6
+ * 3. Sweep newly historical signed groups exposed by those deletions.
7
+ * 4. Retry skipped boundaries by shared restoration component, then individually.
8
+ * 5. Search bounded alternate boundary states (at most 16 per boundary) and their signed groups.
9
+ * 6. Fail with the best validated stats after every finite candidate set is exhausted.
10
+ */
3
11
  export declare function runDeterministicContextEviction(transcript: CompactableTranscript, tokenBudget: number): ValidatedContextDeletionResult;
4
12
  //# sourceMappingURL=context-compaction-eviction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-compaction-eviction.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-eviction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAM3G,eAAO,MAAM,sCAAsC,KAAK,CAAC;AAgKzD,wBAAgB,+BAA+B,CAC9C,UAAU,EAAE,qBAAqB,EACjC,WAAW,EAAE,MAAM,GACjB,8BAA8B,CAmDhC","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { CompactableTranscript, ValidatedContextDeletionResult } from \"./context-compaction-types.ts\";\nimport { validateContextDeletionRequest } from \"./context-deletion-application.ts\";\nimport { canDeleteTarget, deletionRequestFromTargets, isTaskBearingEntry } from \"./context-deletion-targets.ts\";\nimport { relaxTranscriptForCriticalEviction } from \"./context-compaction-critical.ts\";\nimport { assistantEntryHasThinkingContentBlock } from \"./context-transcript-analysis.ts\";\n\nexport const CONTEXT_COMPACTION_MAX_EVICTION_PASSES = 50;\n\nfunction terminalDeterministicEvictionError(\n\treason: string,\n\tlastValidated: ValidatedContextDeletionResult | undefined,\n\ttokenBudget: number,\n): Error {\n\tconst statsText = lastValidated\n\t\t? `achieved tokensAfter=${lastValidated.stats.tokensAfter}, reduction=${lastValidated.stats.percentReduction}%, deletionTargets=${lastValidated.deletedTargets.length}`\n\t\t: \"achieved no validated deletion targets\";\n\treturn new Error(\n\t\t`Context deterministic overflow eviction failed: ${reason}; ${statsText}; budget=${tokenBudget}; nothing more was safely deletable`,\n\t);\n}\n\n\nfunction hasFitBudget(result: ValidatedContextDeletionResult | undefined, tokenBudget: number): result is ValidatedContextDeletionResult {\n\treturn result !== undefined && result.deletedTargets.length > 0 && result.stats.tokensAfter <= tokenBudget;\n}\n\nfunction isThinkingAssistantEntryTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tif (target.kind !== \"entry\") return false;\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\treturn entry?.role === \"assistant\" && assistantEntryHasThinkingContentBlock(entry);\n}\n\nfunction isTaskBearingEntryTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tif (target.kind !== \"entry\") return false;\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\treturn entry !== undefined && isTaskBearingEntry(entry);\n}\n\nfunction targetSignature(targets: readonly ContextDeletionTarget[]): string {\n\treturn targets\n\t\t.map((target) => `${target.kind}:${target.entryId}:${target.kind === \"content_block\" ? target.blockIndex : \"\"}`)\n\t\t.join(\"|\");\n}\n\nfunction entryOrder(transcript: CompactableTranscript, entryId: string): number {\n\tconst index = transcript.entries.findIndex((entry) => entry.entryId === entryId);\n\treturn index < 0 ? Number.MAX_SAFE_INTEGER : index;\n}\n\nfunction entryTokenEstimate(transcript: CompactableTranscript, entryId: string): number {\n\treturn transcript.entries.find((entry) => entry.entryId === entryId)?.tokenEstimate ?? 0;\n}\n\nfunction smallestTaskTarget(transcript: CompactableTranscript, targets: readonly ContextDeletionTarget[]): ContextDeletionTarget | undefined {\n\treturn [...targets]\n\t\t.filter((target) => isTaskBearingEntryTarget(transcript, target))\n\t\t.sort((left: ContextDeletionTarget, right: ContextDeletionTarget) => {\n\t\t\tconst tokenDelta = entryTokenEstimate(transcript, left.entryId) - entryTokenEstimate(transcript, right.entryId);\n\t\t\tif (tokenDelta !== 0) return tokenDelta;\n\t\t\treturn entryOrder(transcript, left.entryId) - entryOrder(transcript, right.entryId);\n\t\t})[0];\n}\n\nfunction newestThinkingTarget(transcript: CompactableTranscript, targets: readonly ContextDeletionTarget[]): ContextDeletionTarget | undefined {\n\treturn [...targets]\n\t\t.filter((target) => isThinkingAssistantEntryTarget(transcript, target))\n\t\t.sort((left: ContextDeletionTarget, right: ContextDeletionTarget) => entryOrder(transcript, right.entryId) - entryOrder(transcript, left.entryId))[0];\n}\n\ntype ThinkingExchange = \"keep-all\" | \"drop-all\" | \"retain-newest\";\ntype TaskExchange = \"keep-all\" | \"drop-all\" | \"retain-smallest\";\n\nconst THINKING_EXCHANGES: readonly ThinkingExchange[] = [\"keep-all\", \"drop-all\", \"retain-newest\"];\nconst TASK_EXCHANGES: readonly TaskExchange[] = [\"keep-all\", \"drop-all\", \"retain-smallest\"];\n\nfunction shouldDeleteTarget(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n\tthinkingExchange: ThinkingExchange,\n\ttaskExchange: TaskExchange,\n\tretainedThinking: ContextDeletionTarget | undefined,\n\tretainedTask: ContextDeletionTarget | undefined,\n): boolean {\n\tif (thinkingExchange === \"drop-all\" && isThinkingAssistantEntryTarget(transcript, target)) return false;\n\tif (thinkingExchange === \"retain-newest\" && retainedThinking !== undefined && targetSignature([target]) === targetSignature([retainedThinking])) return false;\n\tif (taskExchange === \"drop-all\" && isTaskBearingEntryTarget(transcript, target)) return false;\n\tif (taskExchange === \"retain-smallest\" && retainedTask !== undefined && targetSignature([target]) === targetSignature([retainedTask])) return false;\n\treturn true;\n}\n\nfunction buildExchangePlan(\n\ttranscript: CompactableTranscript,\n\twithCandidate: readonly ContextDeletionTarget[],\n\tthinkingExchange: ThinkingExchange,\n\ttaskExchange: TaskExchange,\n): ContextDeletionTarget[] {\n\tconst retainedThinking = thinkingExchange === \"retain-newest\" ? newestThinkingTarget(transcript, withCandidate) : undefined;\n\tconst retainedTask = taskExchange === \"retain-smallest\" ? smallestTaskTarget(transcript, withCandidate) : undefined;\n\treturn withCandidate.filter((target) =>\n\t\tshouldDeleteTarget(transcript, target, thinkingExchange, taskExchange, retainedThinking, retainedTask),\n\t);\n}\n\nfunction shouldBuildExchangePlan(\n\twithCandidate: readonly ContextDeletionTarget[],\n\tthinkingExchange: ThinkingExchange,\n\ttaskExchange: TaskExchange,\n): boolean {\n\tif (thinkingExchange === \"keep-all\" && taskExchange === \"keep-all\") return false;\n\tif (thinkingExchange === \"retain-newest\" && withCandidate.filter((target) => target.kind === \"entry\").length === 0) return false;\n\treturn true;\n}\n\nfunction addExchangePlan(\n\tplans: ContextDeletionTarget[][],\n\tseen: Set<string>,\n\toriginalTargets: readonly ContextDeletionTarget[],\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tif (targetSignature(targets) === targetSignature(originalTargets)) return;\n\tconst signature = targetSignature(targets);\n\tif (seen.has(signature)) return;\n\tseen.add(signature);\n\tplans.push([...targets]);\n}\n\nfunction exchangePlans(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tentryId: string,\n): ContextDeletionTarget[][] {\n\tconst currentTarget: ContextDeletionTarget = { kind: \"entry\", entryId };\n\tconst withCandidate = [...planned, currentTarget];\n\tconst plans: ContextDeletionTarget[][] = [];\n\tconst seen = new Set<string>();\n\t// Deterministic cross-product order: thinking handling outermost, then task handling.\n\t// Variants are keep/drop-all/retain-one for each non-monotone category, minus the\n\t// keep-all/keep-all no-op; signature dedup collapses degenerate variants.\n\tfor (const thinkingExchange of THINKING_EXCHANGES) {\n\t\tfor (const taskExchange of TASK_EXCHANGES) {\n\t\t\tif (!shouldBuildExchangePlan(withCandidate, thinkingExchange, taskExchange)) continue;\n\t\t\taddExchangePlan(plans, seen, withCandidate, buildExchangePlan(transcript, withCandidate, thinkingExchange, taskExchange));\n\t\t}\n\t}\n\treturn plans;\n}\n\nfunction validatedExchange(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tentryId: string,\n\tlastValidated: ValidatedContextDeletionResult | undefined,\n): ValidatedContextDeletionResult | undefined {\n\tlet best: ValidatedContextDeletionResult | undefined;\n\tfor (const retryTargets of exchangePlans(transcript, planned, entryId)) {\n\t\ttry {\n\t\t\tconst result = validateContextDeletionRequest(deletionRequestFromTargets(retryTargets), transcript);\n\t\t\tif (lastValidated !== undefined && result.stats.tokensAfter >= lastValidated.stats.tokensAfter) continue;\n\t\t\tif (best === undefined || result.stats.tokensAfter < best.stats.tokensAfter) best = result;\n\t\t} catch {\n\t\t\t// Try the next deterministic exchange variant.\n\t\t}\n\t}\n\treturn best;\n}\n\nexport function runDeterministicContextEviction(\n\ttranscript: CompactableTranscript,\n\ttokenBudget: number,\n): ValidatedContextDeletionResult {\n\tconst relaxed = relaxTranscriptForCriticalEviction(transcript);\n\tconst latestAssistant = [...relaxed.entries].reverse().find((entry) => entry.role === \"assistant\");\n\tconst protectedThinkingAssistant = latestAssistant && assistantEntryHasThinkingContentBlock(latestAssistant) ? latestAssistant.entryId : undefined;\n\tconst candidates = relaxed.entries\n\t\t.filter((entry) => entry.entryId !== protectedThinkingAssistant)\n\t\t.filter((entry) => canDeleteTarget(relaxed, { kind: \"entry\", entryId: entry.entryId }))\n\t\t.map((entry) => entry.entryId);\n\tconst planned: ContextDeletionTarget[] = [];\n\tconst excluded = new Set<string>();\n\tlet lastValidated: ValidatedContextDeletionResult | undefined;\n\n\t// Hard iteration cap required by the compaction-ladder design: every compaction loop must be\n\t// bounded (max 50) so no tier can spin indefinitely. Non-monotone validation rules can require\n\t// local exchange: a prior thinking-bearing or task-bearing deletion can make a newer candidate\n\t// invalid, even though replacing the prior deletion with that candidate is safe and fits better.\n\t// Exchanges are deterministic and adopted only when validation succeeds and tokensAfter strictly\n\t// decreases; exclusions grow monotonically, so no oscillation is possible, and the pass cap remains\n\t// the terminal safety belt.\n\tfor (let pass = 0; pass < CONTEXT_COMPACTION_MAX_EVICTION_PASSES; pass++) {\n\t\tif (hasFitBudget(lastValidated, tokenBudget)) return lastValidated;\n\t\tlet changed = false;\n\t\tfor (const entryId of candidates) {\n\t\t\tif (hasFitBudget(lastValidated, tokenBudget)) return lastValidated;\n\t\t\tif (planned.some((target) => target.entryId === entryId) || excluded.has(entryId)) continue;\n\t\t\tconst nextPlanned: ContextDeletionTarget[] = [...planned, { kind: \"entry\", entryId }];\n\t\t\ttry {\n\t\t\t\tlastValidated = validateContextDeletionRequest(deletionRequestFromTargets(nextPlanned), relaxed);\n\t\t\t\tplanned.splice(0, planned.length, ...lastValidated.deletedTargets);\n\t\t\t\tchanged = true;\n\t\t\t} catch {\n\t\t\t\tconst exchanged = validatedExchange(relaxed, planned, entryId, lastValidated);\n\t\t\t\tif (exchanged !== undefined) {\n\t\t\t\t\tlastValidated = exchanged;\n\t\t\t\t\tplanned.splice(0, planned.length, ...lastValidated.deletedTargets);\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\texcluded.add(entryId);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\t\tif (!changed) {\n\t\t\tthrow terminalDeterministicEvictionError(\"candidate sweep exhausted\", lastValidated, tokenBudget);\n\t\t}\n\t}\n\tthrow terminalDeterministicEvictionError(\n\t\t`reached ${CONTEXT_COMPACTION_MAX_EVICTION_PASSES} eviction pass cap`,\n\t\tlastValidated,\n\t\ttokenBudget,\n\t);\n}\n"]}
1
+ {"version":3,"file":"context-compaction-eviction.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-eviction.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAgH3G;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAC9C,UAAU,EAAE,qBAAqB,EACjC,WAAW,EAAE,MAAM,GACjB,8BAA8B,CAmHhC","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.js\";\nimport { relaxTranscriptForCriticalEviction } from \"./context-compaction-critical.js\";\nimport {\n\talternateBoundaryPlan,\n\tassistantTurnsForTargets,\n\tcurrentHistoricalSignedGroups,\n\ttype EvictionGroup,\n\thasFitBudget,\n\trepairSignedTurnTargets,\n\tskippedBoundaryRestorationGroups,\n\ttargetsWithGroup,\n\ttryGroup,\n\tvalidateTargets,\n} from \"./context-compaction-eviction-alternates.js\";\nimport type { CompactableTranscript, ValidatedContextDeletionResult } from \"./context-compaction-types.js\";\nimport { transcriptEntryStartsNewTurn } from \"./context-assistant-turns.js\";\nimport { canDeleteTarget, getDeletedEntryIds } from \"./context-deletion-targets.js\";\n\nfunction terminalDeterministicEvictionError(\n\treason: string,\n\tlastValidated: ValidatedContextDeletionResult | undefined,\n\ttokenBudget: number,\n): Error {\n\tconst statsText = lastValidated\n\t\t? `achieved tokensAfter=${lastValidated.stats.tokensAfter}, reduction=${lastValidated.stats.percentReduction}%, deletionTargets=${lastValidated.deletedTargets.length}`\n\t\t: \"achieved no validated deletion targets\";\n\treturn new Error(\n\t\t`Context deterministic overflow eviction failed: ${reason}; ${statsText}; budget=${tokenBudget}; nothing more was safely deletable`,\n\t);\n}\n\nfunction initialEvictionGroups(transcript: CompactableTranscript): EvictionGroup[] {\n\tconst turns = assistantTurnsForTargets(transcript, []);\n\tconst signedGroupByEntryId = new Map<string, string[]>();\n\tconst activeSignedIds = new Set<string>();\n\tfor (const turn of turns) {\n\t\tif (turn.active) {\n\t\t\tfor (const entryId of turn.signedThinkingEntryIds) activeSignedIds.add(entryId);\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const entryId of turn.signedThinkingEntryIds) {\n\t\t\tsignedGroupByEntryId.set(entryId, turn.signedThinkingEntryIds);\n\t\t}\n\t}\n\n\tconst entryById = new Map(transcript.entries.map((entry, index) => [entry.entryId, { entry, index }]));\n\tconst grouped = new Set<string>();\n\tconst groups: EvictionGroup[] = [];\n\tfor (let index = 0; index < transcript.entries.length; index++) {\n\t\tconst entry = transcript.entries[index]!;\n\t\tif (activeSignedIds.has(entry.entryId) || grouped.has(entry.entryId)) continue;\n\t\tconst entryIds = signedGroupByEntryId.get(entry.entryId) ?? [entry.entryId];\n\t\tfor (const entryId of entryIds) grouped.add(entryId);\n\t\tif (!entryIds.every((entryId) => canDeleteTarget(transcript, { kind: \"entry\", entryId }))) continue;\n\t\tgroups.push({\n\t\t\tentryIds: [...entryIds],\n\t\t\torder: index,\n\t\t\ttokens: entryIds.reduce((sum, entryId) => sum + (entryById.get(entryId)?.entry.tokenEstimate ?? 0), 0),\n\t\t\tboundary: entryIds.length === 1 && transcriptEntryStartsNewTurn(entry),\n\t\t});\n\t}\n\treturn groups;\n}\n\nfunction repairedFittingBoundaryPrefix(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tgroups: readonly EvictionGroup[],\n\ttokenBudget: number,\n\tcurrentTokens: number,\n): ValidatedContextDeletionResult | undefined {\n\tconst required = currentTokens - tokenBudget;\n\tif (required <= 0) return undefined;\n\tlet rawRemoved = 0;\n\tlet lowerBound = 0;\n\twhile (lowerBound < groups.length && rawRemoved < required) {\n\t\trawRemoved += groups[lowerBound]!.tokens;\n\t\tlowerBound += 1;\n\t}\n\tif (rawRemoved < required) return undefined;\n\n\tlet prospective = [...planned];\n\tfor (let index = 0; index < groups.length; index++) {\n\t\tprospective = targetsWithGroup(prospective, groups[index]!.entryIds);\n\t\tif (index + 1 < lowerBound) continue;\n\t\tconst repaired = repairSignedTurnTargets(transcript, prospective);\n\t\tconst validated = validateTargets(transcript, repaired);\n\t\tif (!validated || !hasFitBudget(validated, tokenBudget)) continue;\n\t\tconst deleted = getDeletedEntryIds(validated.deletedTargets);\n\t\tconst prefixRetained = groups\n\t\t\t.slice(0, index + 1)\n\t\t\t.some((group) => group.entryIds.some((entryId) => !deleted.has(entryId)));\n\t\tif (!prefixRetained) return validated;\n\t}\n\treturn undefined;\n}\n\nfunction adoptSmallestFittingPrefix(\n\ttranscript: CompactableTranscript,\n\tplanned: readonly ContextDeletionTarget[],\n\tgroups: readonly EvictionGroup[],\n\ttokenBudget: number,\n): ValidatedContextDeletionResult | undefined {\n\tif (groups.length === 0) return undefined;\n\tconst prefixTargets = (count: number): ContextDeletionTarget[] =>\n\t\tgroups.slice(0, count).reduce((targets, group) => targetsWithGroup(targets, group.entryIds), [...planned]);\n\tconst full = validateTargets(transcript, prefixTargets(groups.length));\n\tif (!full) return undefined;\n\tif (!hasFitBudget(full, tokenBudget)) return full;\n\n\tlet low = 1;\n\tlet high = groups.length;\n\tlet best = full;\n\twhile (low <= high) {\n\t\tconst middle = Math.floor((low + high) / 2);\n\t\tconst result = validateTargets(transcript, prefixTargets(middle));\n\t\tif (result && hasFitBudget(result, tokenBudget)) {\n\t\t\tbest = result;\n\t\t\thigh = middle - 1;\n\t\t} else {\n\t\t\tlow = middle + 1;\n\t\t}\n\t}\n\treturn best;\n}\n\n/**\n * Finite deterministic eviction phases:\n * 1. Batch or sweep non-boundary groups in transcript order.\n * 2. Try repaired boundary prefixes, then individual boundaries by token value.\n * 3. Sweep newly historical signed groups exposed by those deletions.\n * 4. Retry skipped boundaries by shared restoration component, then individually.\n * 5. Search bounded alternate boundary states (at most 16 per boundary) and their signed groups.\n * 6. Fail with the best validated stats after every finite candidate set is exhausted.\n */\nexport function runDeterministicContextEviction(\n\ttranscript: CompactableTranscript,\n\ttokenBudget: number,\n): ValidatedContextDeletionResult {\n\tconst relaxed = relaxTranscriptForCriticalEviction(transcript);\n\tconst groups = initialEvictionGroups(relaxed);\n\tconst nonBoundaries = groups.filter((group) => !group.boundary).sort((left, right) => left.order - right.order);\n\tconst boundaries = groups\n\t\t.filter((group) => group.boundary)\n\t\t.sort((left, right) => right.tokens - left.tokens || left.order - right.order);\n\tlet planned: ContextDeletionTarget[] = [];\n\tlet lastValidated: ValidatedContextDeletionResult | undefined;\n\tconst skippedBoundaries: EvictionGroup[] = [];\n\n\tif (relaxed.tokensBefore > tokenBudget) {\n\t\tconst batch = adoptSmallestFittingPrefix(relaxed, planned, nonBoundaries, tokenBudget);\n\t\tif (batch) {\n\t\t\tplanned = [...batch.deletedTargets];\n\t\t\tlastValidated = batch;\n\t\t\tif (hasFitBudget(lastValidated, tokenBudget)) return lastValidated;\n\t\t} else {\n\t\t\tfor (const group of nonBoundaries) {\n\t\t\t\tconst result = tryGroup(relaxed, planned, group, false);\n\t\t\t\tif (!result) continue;\n\t\t\t\tplanned = [...result.deletedTargets];\n\t\t\t\tlastValidated = result;\n\t\t\t\tif (hasFitBudget(lastValidated, tokenBudget)) return lastValidated;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (const group of nonBoundaries) {\n\t\t\tconst result = tryGroup(relaxed, planned, group, false);\n\t\t\tif (!result) continue;\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tconst boundaryBaseTargets = [...planned];\n\tconst boundaryBaseResult = lastValidated;\n\tconst boundaryBatch = repairedFittingBoundaryPrefix(\n\t\trelaxed,\n\t\tplanned,\n\t\tboundaries,\n\t\ttokenBudget,\n\t\tlastValidated?.stats.tokensAfter ?? relaxed.tokensBefore,\n\t);\n\tif (boundaryBatch) {\n\t\tconst standalone = boundaries[0] ? tryGroup(relaxed, [], boundaries[0], true) : undefined;\n\t\treturn standalone && hasFitBudget(standalone, tokenBudget) && standalone.stats.tokensAfter > boundaryBatch.stats.tokensAfter\n\t\t\t? standalone\n\t\t\t: boundaryBatch;\n\t}\n\n\tfor (const group of boundaries) {\n\t\tconst result = tryGroup(relaxed, planned, group, true);\n\t\tif (!result || (lastValidated && result.stats.tokensAfter >= lastValidated.stats.tokensAfter)) {\n\t\t\tskippedBoundaries.push(group);\n\t\t\tcontinue;\n\t\t}\n\t\tplanned = [...result.deletedTargets];\n\t\tlastValidated = result;\n\t\tif (hasFitBudget(lastValidated, tokenBudget)) {\n\t\t\tconst standalone = tryGroup(relaxed, [], group, true);\n\t\t\treturn standalone && hasFitBudget(standalone, tokenBudget) && standalone.stats.tokensAfter > result.stats.tokensAfter\n\t\t\t\t? standalone\n\t\t\t\t: result;\n\t\t}\n\t}\n\n\tfor (const group of currentHistoricalSignedGroups(relaxed, planned)) {\n\t\tconst result = tryGroup(relaxed, planned, group, false);\n\t\tif (!result) continue;\n\t\tplanned = [...result.deletedTargets];\n\t\tlastValidated = result;\n\t\tif (hasFitBudget(lastValidated, tokenBudget)) return lastValidated;\n\t}\n\n\tconst groupedRetryIds = new Set<string>();\n\tfor (const component of skippedBoundaryRestorationGroups(relaxed, planned, skippedBoundaries)) {\n\t\tconst entryIds = component.flatMap((group) => group.entryIds);\n\t\tfor (const entryId of entryIds) groupedRetryIds.add(entryId);\n\t\tconst combined: EvictionGroup = {\n\t\t\tentryIds,\n\t\t\torder: Math.min(...component.map((group) => group.order)),\n\t\t\ttokens: component.reduce((sum, group) => sum + group.tokens, 0),\n\t\t\tboundary: true,\n\t\t};\n\t\tconst result = tryGroup(relaxed, planned, combined, true);\n\t\tif (!result) continue;\n\t\tconst deleted = getDeletedEntryIds(result.deletedTargets);\n\t\tif (!entryIds.every((entryId) => deleted.has(entryId))) continue;\n\t\tif (lastValidated && result.stats.tokensAfter >= lastValidated.stats.tokensAfter && !hasFitBudget(result, tokenBudget)) {\n\t\t\tcontinue;\n\t\t}\n\t\tplanned = [...result.deletedTargets];\n\t\tlastValidated = result;\n\t\tif (hasFitBudget(lastValidated, tokenBudget)) return lastValidated;\n\t}\n\n\tfor (const group of skippedBoundaries) {\n\t\tif (group.entryIds.some((entryId) => groupedRetryIds.has(entryId))) continue;\n\t\tconst result = tryGroup(relaxed, planned, group, true);\n\t\tif (!result || (lastValidated && result.stats.tokensAfter >= lastValidated.stats.tokensAfter)) continue;\n\t\tplanned = [...result.deletedTargets];\n\t\tlastValidated = result;\n\t\tif (hasFitBudget(lastValidated, tokenBudget)) return lastValidated;\n\t}\n\n\tconst alternate = alternateBoundaryPlan(\n\t\trelaxed,\n\t\tboundaryBaseTargets,\n\t\tboundaryBaseResult,\n\t\tboundaries,\n\t\ttokenBudget,\n\t);\n\tif (alternate) return alternate;\n\n\tthrow terminalDeterministicEvictionError(\"candidate sweep exhausted\", lastValidated, tokenBudget);\n}\n"]}