@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,5 +1,19 @@
1
1
  import { getTranscriptCompactionParameters } from "./context-compaction-strategy.js";
2
- import { assistantEntryHasThinkingContentBlock } from "./context-transcript-analysis.js";
2
+ import { analyzeCompactableAssistantTurns, assistantEntryHasThinkingContentBlock, compactableContentBlockIsLlmVisible, transcriptEntryStartsNewTurn, } from "./context-assistant-turns.js";
3
+ function findAssistantTurnDeletionViolation(transcript, targets) {
4
+ const { deletedEntryIds, turns } = analyzeCompactableAssistantTurns(transcript, targets);
5
+ for (const turn of turns) {
6
+ if (turn.signedThinkingEntryIds.length === 0)
7
+ continue;
8
+ const deleted = turn.signedThinkingEntryIds.filter((entryId) => deletedEntryIds.has(entryId));
9
+ if (turn.active && deleted.length > 0)
10
+ return { entryId: deleted[0], active: true };
11
+ if (!turn.active && deleted.length > 0 && deleted.length < turn.signedThinkingEntryIds.length) {
12
+ return { entryId: deleted[0], active: false };
13
+ }
14
+ }
15
+ return undefined;
16
+ }
3
17
  export function targetKey(target) {
4
18
  return target.kind === "entry" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;
5
19
  }
@@ -96,10 +110,12 @@ export function formatProtectedToolDependencyError(transcript, blockedTarget, co
96
110
  const protectedMessage = formatProtectedDeletionError(transcript, blockedTarget);
97
111
  return `${context} ${protectedMessage}`;
98
112
  }
113
+ // Keep legacy protection phrases recognizable for callers handling errors
114
+ // produced by older compaction plans and extension versions.
99
115
  export function isProtectedContextDeletionErrorMessage(message) {
100
116
  return (/\bprotected\b/i.test(message) ||
101
117
  /Cannot delete (?:recent context entry|content block .* because entry .* is one of the last)/u.test(message) ||
102
- /latest assistant message|thinking\/redacted_thinking block in (?:the latest|a retained) assistant message/u.test(message));
118
+ /latest assistant message|active assistant tool-use turn|completed assistant tool-use turn|thinking\/redacted_thinking block in (?:the latest|a retained) assistant message/u.test(message));
103
119
  }
104
120
  export function assertNoRecentContextDeletionTargets(transcript, targets) {
105
121
  const recentEntryIds = getRecentContextEntryIds(transcript);
@@ -131,26 +147,10 @@ export function findAssistantThinkingContentBlockDeletionViolation(transcript, t
131
147
  return undefined;
132
148
  }
133
149
  export function findLatestAssistantThinkingDeletionViolation(transcript, targets) {
134
- const deletedEntryIds = getDeletedEntryIds(targets);
135
- const latestRetainedAssistant = latestAssistantEntry(transcript, deletedEntryIds);
136
- for (const target of targets) {
137
- if (target.kind === "entry") {
138
- const entry = findTranscriptEntry(transcript, target.entryId);
139
- if (!entry || !assistantEntryHasThinkingContentBlock(entry))
140
- continue;
141
- const deletedEntryIdsIfTargetWereKept = new Set(deletedEntryIds);
142
- deletedEntryIdsIfTargetWereKept.delete(target.entryId);
143
- if (latestAssistantEntry(transcript, deletedEntryIdsIfTargetWereKept)?.entryId === target.entryId) {
144
- return target;
145
- }
146
- continue;
147
- }
148
- if (latestRetainedAssistant?.entryId === target.entryId &&
149
- assistantEntryHasThinkingContentBlock(latestRetainedAssistant)) {
150
- return target;
151
- }
152
- }
153
- return undefined;
150
+ const violation = findAssistantTurnDeletionViolation(transcript, targets);
151
+ if (!violation)
152
+ return undefined;
153
+ return targets.find((target) => target.kind === "entry" && target.entryId === violation.entryId);
154
154
  }
155
155
  export function assertNoAssistantThinkingContentBlockDeletionTargets(transcript, targets) {
156
156
  const violation = findAssistantThinkingContentBlockDeletionViolation(transcript, targets);
@@ -159,13 +159,13 @@ export function assertNoAssistantThinkingContentBlockDeletionTargets(transcript,
159
159
  throw new Error(`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in a retained assistant message must remain unmodified; retained assistant messages containing thinking/redacted_thinking content blocks are all-or-nothing`);
160
160
  }
161
161
  export function assertNoLatestAssistantThinkingDeletionTargets(transcript, targets) {
162
- const violation = findLatestAssistantThinkingDeletionViolation(transcript, targets);
162
+ const violation = findAssistantTurnDeletionViolation(transcript, targets);
163
163
  if (!violation)
164
164
  return;
165
- if (violation.kind === "entry") {
166
- throw new Error(`Cannot delete assistant entry ${violation.entryId} because it is the latest assistant message retained after other deletions and contains thinking/redacted_thinking content blocks`);
165
+ if (violation.active) {
166
+ throw new Error(`Cannot delete assistant entry ${violation.entryId} because the active assistant tool-use turn must retain every thinking/redacted_thinking-bearing assistant entry`);
167
167
  }
168
- throw new Error(`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in the latest assistant message must remain unmodified; the latest retained assistant message contains thinking/redacted_thinking content blocks`);
168
+ throw new Error(`Cannot delete assistant entry ${violation.entryId} because a completed assistant tool-use turn must retain all or omit all thinking/redacted_thinking-bearing assistant entries`);
169
169
  }
170
170
  export function isToolCallBlockDeleted(entry, callId, deletedEntryIds, deletedContentBlocks) {
171
171
  if (deletedEntryIds.has(entry.entryId))
@@ -239,11 +239,13 @@ export function addToolCallDeletion(transcript, targets, entry, callId) {
239
239
  }
240
240
  return canonicalizeEntryTargets(transcript, targets, entry) || changed;
241
241
  }
242
- export function isTaskBearingEntry(entry) {
243
- return (entry.role === "user" ||
242
+ /** Whether a task-bearing entry remains provider-visible after proposed block deletions. */
243
+ export function isTaskBearingEntry(entry, deletedContentBlocks = new Set()) {
244
+ const taskRole = entry.role === "user" ||
244
245
  entry.role === "custom" ||
245
246
  entry.role === "branchSummary" ||
246
- entry.entryType === "branch_summary");
247
+ entry.entryType === "branch_summary";
248
+ return taskRole && transcriptEntryStartsNewTurn(entry, deletedContentBlocks);
247
249
  }
248
250
  export function isRecentTarget(transcript, target) {
249
251
  const entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);
@@ -252,7 +254,8 @@ export function isRecentTarget(transcript, target) {
252
254
  export function isStaleUserImageOnlyEntry(transcript, entry) {
253
255
  if (entry.role !== "user" || isRecentContextEntry(entry, transcript))
254
256
  return false;
255
- if (entry.contentBlocks.length === 0 || !entry.contentBlocks.every((block) => block.type === "image"))
257
+ const visibleBlocks = entry.contentBlocks.filter((block) => compactableContentBlockIsLlmVisible(entry, block));
258
+ if (visibleBlocks.length === 0 || !visibleBlocks.every((block) => block.type === "image"))
256
259
  return false;
257
260
  return transcript.entries.some((candidate) => candidate.entryId !== entry.entryId && isTaskBearingEntry(candidate));
258
261
  }
@@ -265,7 +268,9 @@ export function canDeleteStaleUserImageContentBlock(transcript, target) {
265
268
  const block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);
266
269
  if (!block || block.type !== "image")
267
270
  return false;
268
- return entry.contentBlocks.some((candidate) => candidate.blockIndex !== target.blockIndex && candidate.type !== "image");
271
+ return entry.contentBlocks.some((candidate) => candidate.blockIndex !== target.blockIndex &&
272
+ candidate.type !== "image" &&
273
+ compactableContentBlockIsLlmVisible(entry, candidate));
269
274
  }
270
275
  export function canDeleteTarget(transcript, target) {
271
276
  const entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);
@@ -1 +1 @@
1
- {"version":3,"file":"context-deletion-targets.js","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-targets.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type {\n\tCompactableContentBlock,\n\tCompactableTranscript,\n\tCompactableTranscriptEntry,\n\tContextDeletionRequest,\n} from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { assistantEntryHasThinkingContentBlock } from \"./context-transcript-analysis.ts\";\n\nexport function targetKey(target: ContextDeletionTarget): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function rawTargetKey(target: ContextDeletionRequest[\"deletions\"][number]): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function normalizeRawTarget(target: ContextDeletionRequest[\"deletions\"][number]): ContextDeletionTarget {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex as number };\n}\n\nexport function assertIdOnlyDeletionTarget(target: Record<string, unknown>): void {\n\tconst allowedKeys = target.kind === \"content_block\" ? new Set([\"kind\", \"entryId\", \"blockIndex\"]) : new Set([\"kind\", \"entryId\"]);\n\tfor (const key of Object.keys(target)) {\n\t\tif (!allowedKeys.has(key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Deletion target includes unsupported property ${JSON.stringify(key)}; context deletion targets are id-only and must contain only kind, entryId${target.kind === \"content_block\" ? \", and blockIndex\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function rawDeletionFromTarget(target: ContextDeletionTarget): ContextDeletionRequest[\"deletions\"][number] {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex };\n}\n\nexport function deletionRequestFromTargets(targets: readonly ContextDeletionTarget[]): ContextDeletionRequest {\n\treturn { deletions: targets.map(rawDeletionFromTarget) };\n}\n\nexport function getDeletedEntryIds(targets: readonly ContextDeletionTarget[]): Set<string> {\n\treturn new Set(targets.filter((target) => target.kind === \"entry\").map((target) => target.entryId));\n}\n\nexport function getDeletedContentBlocks(targets: readonly ContextDeletionTarget[]): Map<string, Set<number>> {\n\tconst blocksByEntry = new Map<string, Set<number>>();\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tconst blocks = blocksByEntry.get(target.entryId) ?? new Set<number>();\n\t\tblocks.add(target.blockIndex);\n\t\tblocksByEntry.set(target.entryId, blocks);\n\t}\n\treturn blocksByEntry;\n}\n\nexport function recentContextEntryBoundary(transcript: CompactableTranscript): number {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\treturn preserve_recent > 0 ? Math.max(0, transcript.entries.length - preserve_recent) : transcript.entries.length;\n}\n\nexport function getRecentContextEntryIds(transcript: CompactableTranscript): Set<string> {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return new Set();\n\treturn new Set(transcript.entries.slice(recentContextEntryBoundary(transcript)).map((entry) => entry.entryId));\n}\n\nexport function isRecentContextEntry(entry: CompactableTranscriptEntry, transcript: CompactableTranscript): boolean {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return false;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\treturn entryIndex >= 0 && entryIndex >= recentContextEntryBoundary(transcript);\n}\n\nexport function formatRecentContextDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tconst recentWindow = `last ${preserve_recent} context ${preserve_recent === 1 ? \"entry\" : \"entries\"}`;\n\tif (target.kind === \"entry\") {\n\t\treturn `Cannot delete recent context entry ${target.entryId} because the ${recentWindow} must remain available for active continuity. Choose an older entry.`;\n\t}\n\treturn `Cannot delete content block ${target.entryId}:${target.blockIndex} because entry ${target.entryId} is one of the ${recentWindow} that must remain available for active continuity. Choose an older entry or content block.`;\n}\n\nexport function deletionGuidance(): string {\n\treturn \"Choose another deletion candidate.\";\n}\n\nexport function findTranscriptEntry(transcript: CompactableTranscript, entryId: string): CompactableTranscriptEntry | undefined {\n\treturn transcript.entries.find((entry) => entry.entryId === entryId);\n}\n\nexport function findTranscriptContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): CompactableContentBlock | undefined {\n\tif (target.kind !== \"content_block\") return undefined;\n\treturn findTranscriptEntry(transcript, target.entryId)?.contentBlocks.find((block) => block.blockIndex === target.blockIndex);\n}\n\nexport function firstToolCallBlockTarget(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): ContextDeletionTarget | undefined {\n\tconst blockIndex = toolCallBlockIndexes(entry, callId)[0];\n\treturn blockIndex === undefined ? undefined : { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n}\n\nexport function formatProtectedDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\tif (target.kind === \"entry\") {\n\t\tconst toolResultSuffix = entry?.toolResultFor ? ` for tool call ${entry.toolResultFor}` : \"\";\n\t\tconst toolCallSuffix = entry && entry.toolCallIds.length > 0 ? ` containing tool call ${entry.toolCallIds.join(\", \")}` : \"\";\n\t\treturn `Deletion target ${target.entryId}${toolResultSuffix}${toolCallSuffix} is protected. ${deletionGuidance()}`;\n\t}\n\n\tconst block = findTranscriptContentBlock(transcript, target);\n\tconst toolBlockSuffix = block?.toolCallId ? ` It is a protected tool block for tool call ${block.toolCallId}.` : \"\";\n\treturn `Content block ${target.entryId}:${target.blockIndex} is protected.${toolBlockSuffix} ${deletionGuidance()}`;\n}\n\nexport function formatProtectedToolDependencyError(\n\ttranscript: CompactableTranscript,\n\tblockedTarget: ContextDeletionTarget,\n\tcontext: string,\n): string {\n\tconst protectedMessage = formatProtectedDeletionError(transcript, blockedTarget);\n\treturn `${context} ${protectedMessage}`;\n}\n\nexport function isProtectedContextDeletionErrorMessage(message: string): boolean {\n\treturn (\n\t\t/\\bprotected\\b/i.test(message) ||\n\t\t/Cannot delete (?:recent context entry|content block .* because entry .* is one of the last)/u.test(message) ||\n\t\t/latest assistant message|thinking\\/redacted_thinking block in (?:the latest|a retained) assistant message/u.test(message)\n\t);\n}\n\nexport function assertNoRecentContextDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst recentEntryIds = getRecentContextEntryIds(transcript);\n\tfor (const target of targets) {\n\t\tif (recentEntryIds.has(target.entryId)) {\n\t\t\tthrow new Error(formatRecentContextDeletionError(transcript, target));\n\t\t}\n\t}\n}\n\nexport function latestAssistantEntry(\n\ttranscript: CompactableTranscript,\n\tdeletedEntryIds: ReadonlySet<string> = new Set<string>(),\n): CompactableTranscriptEntry | undefined {\n\tfor (let index = transcript.entries.length - 1; index >= 0; index--) {\n\t\tconst entry = transcript.entries[index];\n\t\tif (entry.role === \"assistant\" && !deletedEntryIds.has(entry.entryId)) return entry;\n\t}\n\treturn undefined;\n}\n\nexport function findAssistantThinkingContentBlockDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): Extract<ContextDeletionTarget, { kind: \"content_block\" }> | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tif (deletedEntryIds.has(target.entryId)) continue;\n\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\tif (entry && assistantEntryHasThinkingContentBlock(entry)) return target;\n\t}\n\treturn undefined;\n}\n\nexport function findLatestAssistantThinkingDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tconst latestRetainedAssistant = latestAssistantEntry(transcript, deletedEntryIds);\n\n\tfor (const target of targets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\t\tif (!entry || !assistantEntryHasThinkingContentBlock(entry)) continue;\n\t\t\tconst deletedEntryIdsIfTargetWereKept = new Set(deletedEntryIds);\n\t\t\tdeletedEntryIdsIfTargetWereKept.delete(target.entryId);\n\t\t\tif (latestAssistantEntry(transcript, deletedEntryIdsIfTargetWereKept)?.entryId === target.entryId) {\n\t\t\t\treturn target;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlatestRetainedAssistant?.entryId === target.entryId &&\n\t\t\tassistantEntryHasThinkingContentBlock(latestRetainedAssistant)\n\t\t) {\n\t\t\treturn target;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport function assertNoAssistantThinkingContentBlockDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findAssistantThinkingContentBlockDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in a retained assistant message must remain unmodified; retained assistant messages containing thinking/redacted_thinking content blocks are all-or-nothing`,\n\t);\n}\n\nexport function assertNoLatestAssistantThinkingDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findLatestAssistantThinkingDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tif (violation.kind === \"entry\") {\n\t\tthrow new Error(\n\t\t\t`Cannot delete assistant entry ${violation.entryId} because it is the latest assistant message retained after other deletions and contains thinking/redacted_thinking content blocks`,\n\t\t);\n\t}\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in the latest assistant message must remain unmodified; the latest retained assistant message contains thinking/redacted_thinking content blocks`,\n\t);\n}\n\nexport function isToolCallBlockDeleted(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n\tdeletedEntryIds: ReadonlySet<string>,\n\tdeletedContentBlocks: ReadonlyMap<string, ReadonlySet<number>>,\n): boolean {\n\tif (deletedEntryIds.has(entry.entryId)) return true;\n\tconst deletedBlocks = deletedContentBlocks.get(entry.entryId);\n\tif (!deletedBlocks) return false;\n\treturn entry.contentBlocks.some((block) => block.toolCallId === callId && deletedBlocks.has(block.blockIndex));\n}\n\nexport function toolCallBlockIndexes(entry: CompactableTranscriptEntry, callId: string): number[] {\n\treturn entry.contentBlocks\n\t\t.filter((block) => block.toolCallId === callId)\n\t\t.map((block) => block.blockIndex);\n}\n\nexport function addTarget(targets: ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tif (targets.some((existing) => targetKey(existing) === targetKey(target))) return false;\n\ttargets.push(target);\n\treturn true;\n}\n\nexport function deleteEntryTarget(targets: ContextDeletionTarget[], entryId: string): boolean {\n\tlet changed = false;\n\tfor (let index = targets.length - 1; index >= 0; index--) {\n\t\tconst target = targets[index];\n\t\tif (target.kind === \"content_block\" && target.entryId === entryId) {\n\t\t\ttargets.splice(index, 1);\n\t\t\tchanged = true;\n\t\t}\n\t}\n\treturn addTarget(targets, { kind: \"entry\", entryId }) || changed;\n}\n\nexport function mergeContextDeletionTargets(\n\tbaseTargets: readonly ContextDeletionTarget[],\n\tadditionalTargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget[] {\n\tconst targets = [...baseTargets];\n\tfor (const target of additionalTargets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tdeleteEntryTarget(targets, target.entryId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!getDeletedEntryIds(targets).has(target.entryId)) {\n\t\t\taddTarget(targets, target);\n\t\t}\n\t}\n\treturn targets;\n}\n\nexport function canonicalizeEntryTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n): boolean {\n\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\tif (getDeletedEntryIds(targets).has(entry.entryId)) return false;\n\tconst deletedBlocks = getDeletedContentBlocks(targets).get(entry.entryId);\n\tif (!deletedBlocks || !entry.contentBlocks.every((block) => deletedBlocks.has(block.blockIndex))) return false;\n\t// Only repair/promote when dependency reconciliation reaches this entry. Non-tool entries that\n\t// request every block individually stay invalid so the assistant must choose explicit entry deletion.\n\treturn deleteEntryTarget(targets, entry.entryId);\n}\n\nexport function addToolCallDeletion(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): boolean {\n\tif (assistantEntryHasThinkingContentBlock(entry)) {\n\t\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\t\treturn deleteEntryTarget(targets, entry.entryId);\n\t}\n\n\tlet changed = false;\n\tfor (const blockIndex of toolCallBlockIndexes(entry, callId)) {\n\t\tconst target: ContextDeletionTarget = { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n\t\tif (!canDeleteTarget(transcript, target)) continue;\n\t\tif (!getDeletedEntryIds(targets).has(entry.entryId)) {\n\t\t\tchanged = addTarget(targets, target) || changed;\n\t\t}\n\t}\n\treturn canonicalizeEntryTargets(transcript, targets, entry) || changed;\n}\n\nexport function isTaskBearingEntry(entry: CompactableTranscriptEntry): boolean {\n\treturn (\n\t\tentry.role === \"user\" ||\n\t\tentry.role === \"custom\" ||\n\t\tentry.role === \"branchSummary\" ||\n\t\tentry.entryType === \"branch_summary\"\n\t);\n}\n\nexport function isRecentTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\treturn entry !== undefined && isRecentContextEntry(entry, transcript);\n}\n\nexport function isStaleUserImageOnlyEntry(transcript: CompactableTranscript, entry: CompactableTranscriptEntry): boolean {\n\tif (entry.role !== \"user\" || isRecentContextEntry(entry, transcript)) return false;\n\tif (entry.contentBlocks.length === 0 || !entry.contentBlocks.every((block) => block.type === \"image\")) return false;\n\treturn transcript.entries.some((candidate) => candidate.entryId !== entry.entryId && isTaskBearingEntry(candidate));\n}\n\nexport function canDeleteStaleUserImageContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): boolean {\n\tif (target.kind !== \"content_block\") return false;\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry || entry.role !== \"user\" || isRecentTarget(transcript, target)) return false;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block || block.type !== \"image\") return false;\n\treturn entry.contentBlocks.some((candidate) => candidate.blockIndex !== target.blockIndex && candidate.type !== \"image\");\n}\n\nexport function canDeleteTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry) return false;\n\tif (isRecentTarget(transcript, target)) return false;\n\tif (target.kind === \"entry\") return isStaleUserImageOnlyEntry(transcript, entry) || !entry.protected;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block) return false;\n\tif (canDeleteStaleUserImageContentBlock(transcript, target)) return true;\n\tif (entry.protected) return false;\n\treturn !block.protected;\n}\n\n"]}
1
+ {"version":3,"file":"context-deletion-targets.js","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-targets.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type {\n\tCompactableContentBlock,\n\tCompactableTranscript,\n\tCompactableTranscriptEntry,\n\tContextDeletionRequest,\n} from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport {\n\tanalyzeCompactableAssistantTurns,\n\tassistantEntryHasThinkingContentBlock,\n\tcompactableContentBlockIsLlmVisible,\n\ttranscriptEntryStartsNewTurn,\n} from \"./context-assistant-turns.js\";\n\ninterface AssistantTurnDeletionViolation {\n\tentryId: string;\n\tactive: boolean;\n}\n\nfunction findAssistantTurnDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): AssistantTurnDeletionViolation | undefined {\n\tconst { deletedEntryIds, turns } = analyzeCompactableAssistantTurns(transcript, targets);\n\tfor (const turn of turns) {\n\t\tif (turn.signedThinkingEntryIds.length === 0) continue;\n\t\tconst deleted = turn.signedThinkingEntryIds.filter((entryId) => deletedEntryIds.has(entryId));\n\t\tif (turn.active && deleted.length > 0) return { entryId: deleted[0]!, active: true };\n\t\tif (!turn.active && deleted.length > 0 && deleted.length < turn.signedThinkingEntryIds.length) {\n\t\t\treturn { entryId: deleted[0]!, active: false };\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport function targetKey(target: ContextDeletionTarget): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function rawTargetKey(target: ContextDeletionRequest[\"deletions\"][number]): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function normalizeRawTarget(target: ContextDeletionRequest[\"deletions\"][number]): ContextDeletionTarget {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex as number };\n}\n\nexport function assertIdOnlyDeletionTarget(target: Record<string, unknown>): void {\n\tconst allowedKeys = target.kind === \"content_block\" ? new Set([\"kind\", \"entryId\", \"blockIndex\"]) : new Set([\"kind\", \"entryId\"]);\n\tfor (const key of Object.keys(target)) {\n\t\tif (!allowedKeys.has(key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Deletion target includes unsupported property ${JSON.stringify(key)}; context deletion targets are id-only and must contain only kind, entryId${target.kind === \"content_block\" ? \", and blockIndex\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function rawDeletionFromTarget(target: ContextDeletionTarget): ContextDeletionRequest[\"deletions\"][number] {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex };\n}\n\nexport function deletionRequestFromTargets(targets: readonly ContextDeletionTarget[]): ContextDeletionRequest {\n\treturn { deletions: targets.map(rawDeletionFromTarget) };\n}\n\nexport function getDeletedEntryIds(targets: readonly ContextDeletionTarget[]): Set<string> {\n\treturn new Set(targets.filter((target) => target.kind === \"entry\").map((target) => target.entryId));\n}\n\nexport function getDeletedContentBlocks(targets: readonly ContextDeletionTarget[]): Map<string, Set<number>> {\n\tconst blocksByEntry = new Map<string, Set<number>>();\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tconst blocks = blocksByEntry.get(target.entryId) ?? new Set<number>();\n\t\tblocks.add(target.blockIndex);\n\t\tblocksByEntry.set(target.entryId, blocks);\n\t}\n\treturn blocksByEntry;\n}\n\nexport function recentContextEntryBoundary(transcript: CompactableTranscript): number {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\treturn preserve_recent > 0 ? Math.max(0, transcript.entries.length - preserve_recent) : transcript.entries.length;\n}\n\nexport function getRecentContextEntryIds(transcript: CompactableTranscript): Set<string> {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return new Set();\n\treturn new Set(transcript.entries.slice(recentContextEntryBoundary(transcript)).map((entry) => entry.entryId));\n}\n\nexport function isRecentContextEntry(entry: CompactableTranscriptEntry, transcript: CompactableTranscript): boolean {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return false;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\treturn entryIndex >= 0 && entryIndex >= recentContextEntryBoundary(transcript);\n}\n\nexport function formatRecentContextDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tconst recentWindow = `last ${preserve_recent} context ${preserve_recent === 1 ? \"entry\" : \"entries\"}`;\n\tif (target.kind === \"entry\") {\n\t\treturn `Cannot delete recent context entry ${target.entryId} because the ${recentWindow} must remain available for active continuity. Choose an older entry.`;\n\t}\n\treturn `Cannot delete content block ${target.entryId}:${target.blockIndex} because entry ${target.entryId} is one of the ${recentWindow} that must remain available for active continuity. Choose an older entry or content block.`;\n}\n\nexport function deletionGuidance(): string {\n\treturn \"Choose another deletion candidate.\";\n}\n\nexport function findTranscriptEntry(transcript: CompactableTranscript, entryId: string): CompactableTranscriptEntry | undefined {\n\treturn transcript.entries.find((entry) => entry.entryId === entryId);\n}\n\nexport function findTranscriptContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): CompactableContentBlock | undefined {\n\tif (target.kind !== \"content_block\") return undefined;\n\treturn findTranscriptEntry(transcript, target.entryId)?.contentBlocks.find((block) => block.blockIndex === target.blockIndex);\n}\n\nexport function firstToolCallBlockTarget(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): ContextDeletionTarget | undefined {\n\tconst blockIndex = toolCallBlockIndexes(entry, callId)[0];\n\treturn blockIndex === undefined ? undefined : { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n}\n\nexport function formatProtectedDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\tif (target.kind === \"entry\") {\n\t\tconst toolResultSuffix = entry?.toolResultFor ? ` for tool call ${entry.toolResultFor}` : \"\";\n\t\tconst toolCallSuffix = entry && entry.toolCallIds.length > 0 ? ` containing tool call ${entry.toolCallIds.join(\", \")}` : \"\";\n\t\treturn `Deletion target ${target.entryId}${toolResultSuffix}${toolCallSuffix} is protected. ${deletionGuidance()}`;\n\t}\n\n\tconst block = findTranscriptContentBlock(transcript, target);\n\tconst toolBlockSuffix = block?.toolCallId ? ` It is a protected tool block for tool call ${block.toolCallId}.` : \"\";\n\treturn `Content block ${target.entryId}:${target.blockIndex} is protected.${toolBlockSuffix} ${deletionGuidance()}`;\n}\n\nexport function formatProtectedToolDependencyError(\n\ttranscript: CompactableTranscript,\n\tblockedTarget: ContextDeletionTarget,\n\tcontext: string,\n): string {\n\tconst protectedMessage = formatProtectedDeletionError(transcript, blockedTarget);\n\treturn `${context} ${protectedMessage}`;\n}\n\n// Keep legacy protection phrases recognizable for callers handling errors\n// produced by older compaction plans and extension versions.\nexport function isProtectedContextDeletionErrorMessage(message: string): boolean {\n\treturn (\n\t\t/\\bprotected\\b/i.test(message) ||\n\t\t/Cannot delete (?:recent context entry|content block .* because entry .* is one of the last)/u.test(message) ||\n\t\t/latest assistant message|active assistant tool-use turn|completed assistant tool-use turn|thinking\\/redacted_thinking block in (?:the latest|a retained) assistant message/u.test(message)\n\t);\n}\n\nexport function assertNoRecentContextDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst recentEntryIds = getRecentContextEntryIds(transcript);\n\tfor (const target of targets) {\n\t\tif (recentEntryIds.has(target.entryId)) {\n\t\t\tthrow new Error(formatRecentContextDeletionError(transcript, target));\n\t\t}\n\t}\n}\n\nexport function latestAssistantEntry(\n\ttranscript: CompactableTranscript,\n\tdeletedEntryIds: ReadonlySet<string> = new Set<string>(),\n): CompactableTranscriptEntry | undefined {\n\tfor (let index = transcript.entries.length - 1; index >= 0; index--) {\n\t\tconst entry = transcript.entries[index];\n\t\tif (entry.role === \"assistant\" && !deletedEntryIds.has(entry.entryId)) return entry;\n\t}\n\treturn undefined;\n}\n\nexport function findAssistantThinkingContentBlockDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): Extract<ContextDeletionTarget, { kind: \"content_block\" }> | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tif (deletedEntryIds.has(target.entryId)) continue;\n\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\tif (entry && assistantEntryHasThinkingContentBlock(entry)) return target;\n\t}\n\treturn undefined;\n}\n\nexport function findLatestAssistantThinkingDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget | undefined {\n\tconst violation = findAssistantTurnDeletionViolation(transcript, targets);\n\tif (!violation) return undefined;\n\treturn targets.find((target) => target.kind === \"entry\" && target.entryId === violation.entryId);\n}\n\nexport function assertNoAssistantThinkingContentBlockDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findAssistantThinkingContentBlockDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in a retained assistant message must remain unmodified; retained assistant messages containing thinking/redacted_thinking content blocks are all-or-nothing`,\n\t);\n}\n\nexport function assertNoLatestAssistantThinkingDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findAssistantTurnDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tif (violation.active) {\n\t\tthrow new Error(\n\t\t\t`Cannot delete assistant entry ${violation.entryId} because the active assistant tool-use turn must retain every thinking/redacted_thinking-bearing assistant entry`,\n\t\t);\n\t}\n\tthrow new Error(\n\t\t`Cannot delete assistant entry ${violation.entryId} because a completed assistant tool-use turn must retain all or omit all thinking/redacted_thinking-bearing assistant entries`,\n\t);\n}\n\nexport function isToolCallBlockDeleted(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n\tdeletedEntryIds: ReadonlySet<string>,\n\tdeletedContentBlocks: ReadonlyMap<string, ReadonlySet<number>>,\n): boolean {\n\tif (deletedEntryIds.has(entry.entryId)) return true;\n\tconst deletedBlocks = deletedContentBlocks.get(entry.entryId);\n\tif (!deletedBlocks) return false;\n\treturn entry.contentBlocks.some((block) => block.toolCallId === callId && deletedBlocks.has(block.blockIndex));\n}\n\nexport function toolCallBlockIndexes(entry: CompactableTranscriptEntry, callId: string): number[] {\n\treturn entry.contentBlocks\n\t\t.filter((block) => block.toolCallId === callId)\n\t\t.map((block) => block.blockIndex);\n}\n\nexport function addTarget(targets: ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tif (targets.some((existing) => targetKey(existing) === targetKey(target))) return false;\n\ttargets.push(target);\n\treturn true;\n}\n\nexport function deleteEntryTarget(targets: ContextDeletionTarget[], entryId: string): boolean {\n\tlet changed = false;\n\tfor (let index = targets.length - 1; index >= 0; index--) {\n\t\tconst target = targets[index];\n\t\tif (target.kind === \"content_block\" && target.entryId === entryId) {\n\t\t\ttargets.splice(index, 1);\n\t\t\tchanged = true;\n\t\t}\n\t}\n\treturn addTarget(targets, { kind: \"entry\", entryId }) || changed;\n}\n\nexport function mergeContextDeletionTargets(\n\tbaseTargets: readonly ContextDeletionTarget[],\n\tadditionalTargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget[] {\n\tconst targets = [...baseTargets];\n\tfor (const target of additionalTargets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tdeleteEntryTarget(targets, target.entryId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!getDeletedEntryIds(targets).has(target.entryId)) {\n\t\t\taddTarget(targets, target);\n\t\t}\n\t}\n\treturn targets;\n}\n\nexport function canonicalizeEntryTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n): boolean {\n\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\tif (getDeletedEntryIds(targets).has(entry.entryId)) return false;\n\tconst deletedBlocks = getDeletedContentBlocks(targets).get(entry.entryId);\n\tif (!deletedBlocks || !entry.contentBlocks.every((block) => deletedBlocks.has(block.blockIndex))) return false;\n\t// Only repair/promote when dependency reconciliation reaches this entry. Non-tool entries that\n\t// request every block individually stay invalid so the assistant must choose explicit entry deletion.\n\treturn deleteEntryTarget(targets, entry.entryId);\n}\n\nexport function addToolCallDeletion(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): boolean {\n\tif (assistantEntryHasThinkingContentBlock(entry)) {\n\t\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\t\treturn deleteEntryTarget(targets, entry.entryId);\n\t}\n\n\tlet changed = false;\n\tfor (const blockIndex of toolCallBlockIndexes(entry, callId)) {\n\t\tconst target: ContextDeletionTarget = { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n\t\tif (!canDeleteTarget(transcript, target)) continue;\n\t\tif (!getDeletedEntryIds(targets).has(entry.entryId)) {\n\t\t\tchanged = addTarget(targets, target) || changed;\n\t\t}\n\t}\n\treturn canonicalizeEntryTargets(transcript, targets, entry) || changed;\n}\n\n/** Whether a task-bearing entry remains provider-visible after proposed block deletions. */\nexport function isTaskBearingEntry(\n\tentry: CompactableTranscriptEntry,\n\tdeletedContentBlocks: ReadonlySet<number> = new Set<number>(),\n): boolean {\n\tconst taskRole =\n\t\tentry.role === \"user\" ||\n\t\tentry.role === \"custom\" ||\n\t\tentry.role === \"branchSummary\" ||\n\t\tentry.entryType === \"branch_summary\";\n\treturn taskRole && transcriptEntryStartsNewTurn(entry, deletedContentBlocks);\n}\n\nexport function isRecentTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\treturn entry !== undefined && isRecentContextEntry(entry, transcript);\n}\n\nexport function isStaleUserImageOnlyEntry(transcript: CompactableTranscript, entry: CompactableTranscriptEntry): boolean {\n\tif (entry.role !== \"user\" || isRecentContextEntry(entry, transcript)) return false;\n\tconst visibleBlocks = entry.contentBlocks.filter((block) => compactableContentBlockIsLlmVisible(entry, block));\n\tif (visibleBlocks.length === 0 || !visibleBlocks.every((block) => block.type === \"image\")) return false;\n\treturn transcript.entries.some(\n\t\t(candidate) => candidate.entryId !== entry.entryId && isTaskBearingEntry(candidate),\n\t);\n}\n\nexport function canDeleteStaleUserImageContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): boolean {\n\tif (target.kind !== \"content_block\") return false;\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry || entry.role !== \"user\" || isRecentTarget(transcript, target)) return false;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block || block.type !== \"image\") return false;\n\treturn entry.contentBlocks.some(\n\t\t(candidate) =>\n\t\t\tcandidate.blockIndex !== target.blockIndex &&\n\t\t\tcandidate.type !== \"image\" &&\n\t\t\tcompactableContentBlockIsLlmVisible(entry, candidate),\n\t);\n}\n\nexport function canDeleteTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry) return false;\n\tif (isRecentTarget(transcript, target)) return false;\n\tif (target.kind === \"entry\") return isStaleUserImageOnlyEntry(transcript, entry) || !entry.protected;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block) return false;\n\tif (canDeleteStaleUserImageContentBlock(transcript, target)) return true;\n\tif (entry.protected) return false;\n\treturn !block.protected;\n}\n\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"context-deletion-tool-helpers.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tool-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,KAAK,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAC;AAiBnH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AACD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAkB5D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,GAAG,MAAM,CAUjG;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAK3D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtH;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAM9F;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,EAAE,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAKtH;AAED,wBAAgB,gBAAgB,CAC/B,UAAU,EAAE,qBAAqB,EAAE,EACnC,OAAO,EAAE,wBAAwB,EAAE,EACnC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,SAAS,EAAE,qBAAqB,EAChC,KAAK,EAAE,wBAAwB,GAC7B,IAAI,CAMN;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,0BAA0B,EAAE,EAAE,KAAK,EAAE,wBAAwB,GAAG,IAAI,CAQlH;AAED,wBAAgB,6BAA6B,CAC5C,UAAU,EAAE,SAAS,qBAAqB,EAAE,EAC5C,OAAO,EAAE,SAAS,wBAAwB,EAAE,EAC5C,cAAc,EAAE,SAAS,qBAAqB,EAAE,EAChD,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,0BAA0B,EAAE,GACnC;IAAE,UAAU,EAAE,qBAAqB,EAAE,CAAC;IAAC,OAAO,EAAE,wBAAwB,EAAE,CAAA;CAAE,CAkD9E","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { CompactableTranscript } from \"./context-compaction-types.ts\";\nimport type { ContextGrepDeletionMatch, ContextGrepDeletionSkipped } from \"./context-deletion-tool-definitions.ts\";\nimport {\n\tCONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS,\n\tCONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS,\n} from \"./context-deletion-tool-definitions.ts\";\nimport { formatErrorMessage } from \"./context-compaction-metrics.ts\";\nimport { validateContextDeletionRequest } from \"./context-deletion-application.ts\";\nimport {\n\tdeletionRequestFromTargets,\n\tfindLatestAssistantThinkingDeletionViolation,\n\tgetDeletedContentBlocks,\n\tgetDeletedEntryIds,\n\tisProtectedContextDeletionErrorMessage,\n\tmergeContextDeletionTargets,\n\ttargetKey,\n} from \"./context-deletion-targets.ts\";\n\nexport function escapeRegExpLiteral(text: string): string {\n\treturn text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\nexport function assertSafeRegexPattern(pattern: string): void {\n\tif (pattern.length > CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS) {\n\t\tthrow new Error(\n\t\t\t`Regex pattern is too long (${pattern.length} characters); maximum is ${CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS}`,\n\t\t);\n\t}\n\n\t// Heuristic ReDoS guard for common catastrophic-backtracking shapes. JavaScript's RegExp engine\n\t// does not expose a timeout, so reject nested quantified groups and backreferences instead of\n\t// relying only on transcript scan-size caps.\n\tconst hasNestedQuantifiedGroup = /\\((?:[^()\\\\]|\\\\.)*[+*](?:[^()\\\\]|\\\\.)*\\)\\s*(?:[+*]|\\{\\d)/u.test(pattern);\n\tconst hasQuantifiedAlternation = /\\((?:[^()\\\\]|\\\\.)*\\|(?:[^()\\\\]|\\\\.)*\\)\\s*(?:[+*]|\\{\\d)/u.test(pattern);\n\tconst hasBackreference = /\\\\[1-9]/u.test(pattern);\n\tif (hasNestedQuantifiedGroup || hasQuantifiedAlternation || hasBackreference) {\n\t\tthrow new Error(\n\t\t\t\"Regex pattern is not allowed because it may cause excessive backtracking; use a literal pattern or exact deletion targets instead.\",\n\t\t);\n\t}\n}\n\nexport function createGrepMatcher(pattern: string, regex: boolean, caseSensitive: boolean): RegExp {\n\tif (regex) {\n\t\tassertSafeRegexPattern(pattern);\n\t}\n\n\ttry {\n\t\treturn new RegExp(regex ? pattern : escapeRegExpLiteral(pattern), caseSensitive ? \"u\" : \"iu\");\n\t} catch (error) {\n\t\tthrow new Error(`Invalid grep ${regex ? \"regex\" : \"pattern\"}: ${formatErrorMessage(error)}`);\n\t}\n}\n\nexport function assertSafeRegexScan(scanChars: number): void {\n\tif (scanChars <= CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS) return;\n\tthrow new Error(\n\t\t`Regex grep would scan ${scanChars} characters; maximum is ${CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS}. Use a literal pattern or exact deletion targets instead.`,\n\t);\n}\n\nexport function clampInteger(value: number | undefined, defaultValue: number, minimum: number, maximum: number): number {\n\tif (value === undefined) return defaultValue;\n\treturn Math.max(minimum, Math.min(maximum, value));\n}\n\nexport function textSlice(text: string, offset: number, maxChars: number): string {\n\treturn text.slice(offset, Math.min(text.length, offset + maxChars));\n}\n\nexport function findMatchIndex(matcher: RegExp, text: string): number {\n\tconst match = matcher.exec(text);\n\tmatcher.lastIndex = 0;\n\treturn match?.index ?? -1;\n}\n\nexport function snippetForMatch(text: string, matchIndex: number, contextChars: number): string {\n\tconst start = Math.max(0, matchIndex - contextChars);\n\tconst end = Math.min(text.length, matchIndex + contextChars);\n\tconst prefix = start > 0 ? \"…\" : \"\";\n\tconst suffix = end < text.length ? \"…\" : \"\";\n\treturn `${prefix}${text.slice(start, end)}${suffix}`;\n}\n\nexport function currentTargetDeleted(targets: readonly ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tif (deletedEntryIds.has(target.entryId)) return true;\n\tif (target.kind === \"entry\") return false;\n\treturn getDeletedContentBlocks(targets).get(target.entryId)?.has(target.blockIndex) === true;\n}\n\nexport function addGrepCandidate(\n\tcandidates: ContextDeletionTarget[],\n\tmatches: ContextGrepDeletionMatch[],\n\tseenTargets: Set<string>,\n\tcandidate: ContextDeletionTarget,\n\tmatch: ContextGrepDeletionMatch,\n): void {\n\tconst key = targetKey(candidate);\n\tif (seenTargets.has(key)) return;\n\tseenTargets.add(key);\n\tcandidates.push(candidate);\n\tmatches.push(match);\n}\n\nexport function pushProtectedGrepSkip(skipped: ContextGrepDeletionSkipped[], match: ContextGrepDeletionMatch): void {\n\tskipped.push({\n\t\tentryId: match.entryId,\n\t\ttarget: match.target,\n\t\t...(match.blockIndex === undefined ? {} : { blockIndex: match.blockIndex }),\n\t\treason: match.target === \"content_block\" ? \"protected_block\" : \"protected_entry\",\n\t\ttext: match.text,\n\t});\n}\n\nexport function filterProtectedGrepCandidates(\n\tcandidates: readonly ContextDeletionTarget[],\n\tmatches: readonly ContextGrepDeletionMatch[],\n\tcurrentTargets: readonly ContextDeletionTarget[],\n\ttranscript: CompactableTranscript,\n\tskipped: ContextGrepDeletionSkipped[],\n): { candidates: ContextDeletionTarget[]; matches: ContextGrepDeletionMatch[] } {\n\tconst eligibleCandidates: ContextDeletionTarget[] = [];\n\tconst eligibleMatches: ContextGrepDeletionMatch[] = [];\n\tfor (let index = 0; index < candidates.length; index++) {\n\t\tconst candidate = candidates[index];\n\t\tconst match = matches[index];\n\t\tif (!candidate || !match) continue;\n\t\ttry {\n\t\t\tconst mergedTargets = mergeContextDeletionTargets(currentTargets, [candidate]);\n\t\t\tvalidateContextDeletionRequest(deletionRequestFromTargets(mergedTargets), transcript);\n\t\t\teligibleCandidates.push(candidate);\n\t\t\teligibleMatches.push(match);\n\t\t} catch (error) {\n\t\t\tconst message = formatErrorMessage(error);\n\t\t\tif (isProtectedContextDeletionErrorMessage(message)) {\n\t\t\t\tpushProtectedGrepSkip(skipped, match);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\teligibleCandidates.push(candidate);\n\t\t\teligibleMatches.push(match);\n\t\t}\n\t}\n\n\t// Some latest-assistant thinking violations only become visible after a grep batch also\n\t// deletes newer assistant entries. Classify the newly-unsafe grep candidates as\n\t// protected/skipped before maxMatches, expectedMatchCount, stats, or removals are computed.\n\tlet changed = true;\n\twhile (changed) {\n\t\tchanged = false;\n\t\tconst mergedTargets = mergeContextDeletionTargets(currentTargets, eligibleCandidates);\n\t\tconst violation = findLatestAssistantThinkingDeletionViolation(transcript, mergedTargets);\n\t\tif (!violation) continue;\n\t\tconst violationKey = targetKey(violation);\n\t\tlet violationIndex = eligibleCandidates.findIndex((candidate) => targetKey(candidate) === violationKey);\n\t\tif (violationIndex < 0) {\n\t\t\tviolationIndex = eligibleCandidates.findIndex((_candidate, candidateIndex) => {\n\t\t\t\tconst remainingCandidates = eligibleCandidates.filter((_candidateToKeep, index) => index !== candidateIndex);\n\t\t\t\tconst remainingTargets = mergeContextDeletionTargets(currentTargets, remainingCandidates);\n\t\t\t\tconst remainingViolation = findLatestAssistantThinkingDeletionViolation(transcript, remainingTargets);\n\t\t\t\treturn !remainingViolation || targetKey(remainingViolation) !== violationKey;\n\t\t\t});\n\t\t}\n\t\tif (violationIndex < 0) continue;\n\t\tconst [skippedMatch] = eligibleMatches.splice(violationIndex, 1);\n\t\teligibleCandidates.splice(violationIndex, 1);\n\t\tif (skippedMatch) pushProtectedGrepSkip(skipped, skippedMatch);\n\t\tchanged = true;\n\t}\n\n\treturn { candidates: eligibleCandidates, matches: eligibleMatches };\n}\n"]}
1
+ {"version":3,"file":"context-deletion-tool-helpers.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tool-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,KAAK,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAC;AAoBnH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AACD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAkB5D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,GAAG,MAAM,CAUjG;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAK3D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtH;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAM9F;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,EAAE,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAKtH;AAED,wBAAgB,gBAAgB,CAC/B,UAAU,EAAE,qBAAqB,EAAE,EACnC,OAAO,EAAE,wBAAwB,EAAE,EACnC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,SAAS,EAAE,qBAAqB,EAChC,KAAK,EAAE,wBAAwB,GAC7B,IAAI,CAMN;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,0BAA0B,EAAE,EAAE,KAAK,EAAE,wBAAwB,GAAG,IAAI,CAQlH;AAoCD,wBAAgB,6BAA6B,CAC5C,UAAU,EAAE,SAAS,qBAAqB,EAAE,EAC5C,OAAO,EAAE,SAAS,wBAAwB,EAAE,EAC5C,cAAc,EAAE,SAAS,qBAAqB,EAAE,EAChD,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,0BAA0B,EAAE,GACnC;IAAE,UAAU,EAAE,qBAAqB,EAAE,CAAC;IAAC,OAAO,EAAE,wBAAwB,EAAE,CAAA;CAAE,CAmG9E","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { CompactableTranscript } from \"./context-compaction-types.ts\";\nimport type { ContextGrepDeletionMatch, ContextGrepDeletionSkipped } from \"./context-deletion-tool-definitions.ts\";\nimport {\n\tCONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS,\n\tCONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS,\n} from \"./context-deletion-tool-definitions.ts\";\nimport { formatErrorMessage } from \"./context-compaction-metrics.ts\";\nimport { reconcileToolDependencies, validateContextDeletionRequest } from \"./context-deletion-application.ts\";\nimport {\n\tdeletionRequestFromTargets,\n\tgetDeletedContentBlocks,\n\tgetDeletedEntryIds,\n\tmergeContextDeletionTargets,\n\ttargetKey,\n} from \"./context-deletion-targets.ts\";\nimport {\n\tanalyzeCompactableAssistantTurns,\n\tisTranscriptEntryEffectivelyDeleted,\n\ttranscriptEntryStartsNewTurn,\n} from \"./context-assistant-turns.js\";\n\nexport function escapeRegExpLiteral(text: string): string {\n\treturn text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\nexport function assertSafeRegexPattern(pattern: string): void {\n\tif (pattern.length > CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS) {\n\t\tthrow new Error(\n\t\t\t`Regex pattern is too long (${pattern.length} characters); maximum is ${CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS}`,\n\t\t);\n\t}\n\n\t// Heuristic ReDoS guard for common catastrophic-backtracking shapes. JavaScript's RegExp engine\n\t// does not expose a timeout, so reject nested quantified groups and backreferences instead of\n\t// relying only on transcript scan-size caps.\n\tconst hasNestedQuantifiedGroup = /\\((?:[^()\\\\]|\\\\.)*[+*](?:[^()\\\\]|\\\\.)*\\)\\s*(?:[+*]|\\{\\d)/u.test(pattern);\n\tconst hasQuantifiedAlternation = /\\((?:[^()\\\\]|\\\\.)*\\|(?:[^()\\\\]|\\\\.)*\\)\\s*(?:[+*]|\\{\\d)/u.test(pattern);\n\tconst hasBackreference = /\\\\[1-9]/u.test(pattern);\n\tif (hasNestedQuantifiedGroup || hasQuantifiedAlternation || hasBackreference) {\n\t\tthrow new Error(\n\t\t\t\"Regex pattern is not allowed because it may cause excessive backtracking; use a literal pattern or exact deletion targets instead.\",\n\t\t);\n\t}\n}\n\nexport function createGrepMatcher(pattern: string, regex: boolean, caseSensitive: boolean): RegExp {\n\tif (regex) {\n\t\tassertSafeRegexPattern(pattern);\n\t}\n\n\ttry {\n\t\treturn new RegExp(regex ? pattern : escapeRegExpLiteral(pattern), caseSensitive ? \"u\" : \"iu\");\n\t} catch (error) {\n\t\tthrow new Error(`Invalid grep ${regex ? \"regex\" : \"pattern\"}: ${formatErrorMessage(error)}`);\n\t}\n}\n\nexport function assertSafeRegexScan(scanChars: number): void {\n\tif (scanChars <= CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS) return;\n\tthrow new Error(\n\t\t`Regex grep would scan ${scanChars} characters; maximum is ${CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS}. Use a literal pattern or exact deletion targets instead.`,\n\t);\n}\n\nexport function clampInteger(value: number | undefined, defaultValue: number, minimum: number, maximum: number): number {\n\tif (value === undefined) return defaultValue;\n\treturn Math.max(minimum, Math.min(maximum, value));\n}\n\nexport function textSlice(text: string, offset: number, maxChars: number): string {\n\treturn text.slice(offset, Math.min(text.length, offset + maxChars));\n}\n\nexport function findMatchIndex(matcher: RegExp, text: string): number {\n\tconst match = matcher.exec(text);\n\tmatcher.lastIndex = 0;\n\treturn match?.index ?? -1;\n}\n\nexport function snippetForMatch(text: string, matchIndex: number, contextChars: number): string {\n\tconst start = Math.max(0, matchIndex - contextChars);\n\tconst end = Math.min(text.length, matchIndex + contextChars);\n\tconst prefix = start > 0 ? \"…\" : \"\";\n\tconst suffix = end < text.length ? \"…\" : \"\";\n\treturn `${prefix}${text.slice(start, end)}${suffix}`;\n}\n\nexport function currentTargetDeleted(targets: readonly ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tif (deletedEntryIds.has(target.entryId)) return true;\n\tif (target.kind === \"entry\") return false;\n\treturn getDeletedContentBlocks(targets).get(target.entryId)?.has(target.blockIndex) === true;\n}\n\nexport function addGrepCandidate(\n\tcandidates: ContextDeletionTarget[],\n\tmatches: ContextGrepDeletionMatch[],\n\tseenTargets: Set<string>,\n\tcandidate: ContextDeletionTarget,\n\tmatch: ContextGrepDeletionMatch,\n): void {\n\tconst key = targetKey(candidate);\n\tif (seenTargets.has(key)) return;\n\tseenTargets.add(key);\n\tcandidates.push(candidate);\n\tmatches.push(match);\n}\n\nexport function pushProtectedGrepSkip(skipped: ContextGrepDeletionSkipped[], match: ContextGrepDeletionMatch): void {\n\tskipped.push({\n\t\tentryId: match.entryId,\n\t\ttarget: match.target,\n\t\t...(match.blockIndex === undefined ? {} : { blockIndex: match.blockIndex }),\n\t\treason: match.target === \"content_block\" ? \"protected_block\" : \"protected_entry\",\n\t\ttext: match.text,\n\t});\n}\n\nfunction assistantTurnsForTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n) {\n\tconst reconciled = reconcileToolDependencies(transcript, targets);\n\treturn { reconciled, ...analyzeCompactableAssistantTurns(transcript, reconciled) };\n}\n\nfunction candidateRemovesBoundary(\n\ttranscript: CompactableTranscript,\n\tcurrentTargets: readonly ContextDeletionTarget[],\n\tcandidate: ContextDeletionTarget,\n): boolean {\n\tconst entry = transcript.entries.find((item) => item.entryId === candidate.entryId);\n\tif (!entry) return false;\n\tconst beforeEntries = getDeletedEntryIds(currentTargets);\n\tconst beforeBlocks = getDeletedContentBlocks(currentTargets);\n\tconst before =\n\t\t!isTranscriptEntryEffectivelyDeleted(entry, beforeEntries, beforeBlocks) &&\n\t\ttranscriptEntryStartsNewTurn(entry, beforeBlocks.get(entry.entryId));\n\tif (!before) return false;\n\ttry {\n\t\tconst after = assistantTurnsForTargets(transcript, mergeContextDeletionTargets(currentTargets, [candidate]));\n\t\treturn isTranscriptEntryEffectivelyDeleted(entry, after.deletedEntryIds, after.deletedContentBlocks) ||\n\t\t\t!transcriptEntryStartsNewTurn(entry, after.deletedContentBlocks.get(entry.entryId));\n\t} catch {\n\t\treturn true;\n\t}\n}\n\ninterface SemanticCandidate {\n\tindex: number;\n\taffectedTurns: Set<number>;\n}\nexport function filterProtectedGrepCandidates(\n\tcandidates: readonly ContextDeletionTarget[],\n\tmatches: readonly ContextGrepDeletionMatch[],\n\tcurrentTargets: readonly ContextDeletionTarget[],\n\ttranscript: CompactableTranscript,\n\tskipped: ContextGrepDeletionSkipped[],\n): { candidates: ContextDeletionTarget[]; matches: ContextGrepDeletionMatch[] } {\n\tconst rejected = new Set<number>();\n\tconst accepted = new Set<number>();\n\tlet acceptedTargets = [...currentTargets];\n\tconst base = assistantTurnsForTargets(transcript, currentTargets);\n\tconst signedTurnByEntryId = new Map<string, number>();\n\tbase.turns.forEach((turn, turnIndex) => {\n\t\tfor (const entryId of turn.signedThinkingEntryIds) signedTurnByEntryId.set(entryId, turnIndex);\n\t});\n\tconst boundaries: number[] = [];\n\tconst ordinary: number[] = [];\n\tconst semantic: SemanticCandidate[] = [];\n\n\tfor (let index = 0; index < candidates.length; index++) {\n\t\tconst candidate = candidates[index]!;\n\t\tif (candidateRemovesBoundary(transcript, currentTargets, candidate)) {\n\t\t\tboundaries.push(index);\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\tconst single = assistantTurnsForTargets(\n\t\t\t\ttranscript,\n\t\t\t\tmergeContextDeletionTargets(currentTargets, [candidate]),\n\t\t\t);\n\t\t\tconst affectedTurns = new Set<number>();\n\t\t\tfor (const entryId of single.deletedEntryIds) {\n\t\t\t\tif (base.deletedEntryIds.has(entryId)) continue;\n\t\t\t\tconst turnIndex = signedTurnByEntryId.get(entryId);\n\t\t\t\tif (turnIndex !== undefined) affectedTurns.add(turnIndex);\n\t\t\t}\n\t\t\tif (affectedTurns.size === 0) ordinary.push(index);\n\t\t\telse semantic.push({ index, affectedTurns });\n\t\t} catch {\n\t\t\trejected.add(index);\n\t\t}\n\t}\n\n\tconst components: SemanticCandidate[][] = [];\n\tfor (const item of semantic) {\n\t\tconst overlapping = components.filter((component) =>\n\t\t\tcomponent.some((member) => [...member.affectedTurns].some((turn) => item.affectedTurns.has(turn))),\n\t\t);\n\t\tif (overlapping.length === 0) {\n\t\t\tcomponents.push([item]);\n\t\t\tcontinue;\n\t\t}\n\t\tconst merged = [item, ...overlapping.flat()];\n\t\tfor (const component of overlapping) components.splice(components.indexOf(component), 1);\n\t\tcomponents.push(merged.sort((left, right) => left.index - right.index));\n\t}\n\n\tfor (const component of components.sort((left, right) => left[0]!.index - right[0]!.index)) {\n\t\tconst indexes = component.map((item) => item.index);\n\t\tconst proposed = mergeContextDeletionTargets(acceptedTargets, indexes.map((index) => candidates[index]!));\n\t\tlet complete = true;\n\t\ttry {\n\t\t\tconst effect = assistantTurnsForTargets(transcript, proposed);\n\t\t\tconst affectedTurns = new Set(component.flatMap((item) => [...item.affectedTurns]));\n\t\t\tfor (const turnIndex of affectedTurns) {\n\t\t\t\tconst turn = base.turns[turnIndex]!;\n\t\t\t\tif (turn.active || !turn.signedThinkingEntryIds.every((entryId) => effect.deletedEntryIds.has(entryId))) {\n\t\t\t\t\tcomplete = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (complete) validateContextDeletionRequest(deletionRequestFromTargets(proposed), transcript);\n\t\t} catch {\n\t\t\tcomplete = false;\n\t\t}\n\t\tif (!complete) {\n\t\t\tfor (const index of indexes) rejected.add(index);\n\t\t\tcontinue;\n\t\t}\n\t\tacceptedTargets = proposed;\n\t\tfor (const index of indexes) accepted.add(index);\n\t}\n\n\tconst acceptIndividually = (indexes: readonly number[]): void => {\n\t\tfor (const index of indexes) {\n\t\t\tconst proposed = mergeContextDeletionTargets(acceptedTargets, [candidates[index]!]);\n\t\t\ttry {\n\t\t\t\tvalidateContextDeletionRequest(deletionRequestFromTargets(proposed), transcript);\n\t\t\t\tacceptedTargets = proposed;\n\t\t\t\taccepted.add(index);\n\t\t\t} catch {\n\t\t\t\trejected.add(index);\n\t\t\t}\n\t\t}\n\t};\n\tacceptIndividually(ordinary);\n\tacceptIndividually(boundaries);\n\n\tfor (let index = 0; index < matches.length; index++) {\n\t\tif (rejected.has(index)) pushProtectedGrepSkip(skipped, matches[index]!);\n\t}\n\treturn {\n\t\tcandidates: candidates.filter((_candidate, index) => accepted.has(index)),\n\t\tmatches: matches.filter((_match, index) => accepted.has(index)),\n\t};\n}\n"]}
@@ -1,7 +1,8 @@
1
1
  import { CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS, CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS, } from "./context-deletion-tool-definitions.js";
2
2
  import { formatErrorMessage } from "./context-compaction-metrics.js";
3
- import { validateContextDeletionRequest } from "./context-deletion-application.js";
4
- import { deletionRequestFromTargets, findLatestAssistantThinkingDeletionViolation, getDeletedContentBlocks, getDeletedEntryIds, isProtectedContextDeletionErrorMessage, mergeContextDeletionTargets, targetKey, } from "./context-deletion-targets.js";
3
+ import { reconcileToolDependencies, validateContextDeletionRequest } from "./context-deletion-application.js";
4
+ import { deletionRequestFromTargets, getDeletedContentBlocks, getDeletedEntryIds, mergeContextDeletionTargets, targetKey, } from "./context-deletion-targets.js";
5
+ import { analyzeCompactableAssistantTurns, isTranscriptEntryEffectivelyDeleted, transcriptEntryStartsNewTurn, } from "./context-assistant-turns.js";
5
6
  export function escapeRegExpLiteral(text) {
6
7
  return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7
8
  }
@@ -80,58 +81,130 @@ export function pushProtectedGrepSkip(skipped, match) {
80
81
  text: match.text,
81
82
  });
82
83
  }
84
+ function assistantTurnsForTargets(transcript, targets) {
85
+ const reconciled = reconcileToolDependencies(transcript, targets);
86
+ return { reconciled, ...analyzeCompactableAssistantTurns(transcript, reconciled) };
87
+ }
88
+ function candidateRemovesBoundary(transcript, currentTargets, candidate) {
89
+ const entry = transcript.entries.find((item) => item.entryId === candidate.entryId);
90
+ if (!entry)
91
+ return false;
92
+ const beforeEntries = getDeletedEntryIds(currentTargets);
93
+ const beforeBlocks = getDeletedContentBlocks(currentTargets);
94
+ const before = !isTranscriptEntryEffectivelyDeleted(entry, beforeEntries, beforeBlocks) &&
95
+ transcriptEntryStartsNewTurn(entry, beforeBlocks.get(entry.entryId));
96
+ if (!before)
97
+ return false;
98
+ try {
99
+ const after = assistantTurnsForTargets(transcript, mergeContextDeletionTargets(currentTargets, [candidate]));
100
+ return isTranscriptEntryEffectivelyDeleted(entry, after.deletedEntryIds, after.deletedContentBlocks) ||
101
+ !transcriptEntryStartsNewTurn(entry, after.deletedContentBlocks.get(entry.entryId));
102
+ }
103
+ catch {
104
+ return true;
105
+ }
106
+ }
83
107
  export function filterProtectedGrepCandidates(candidates, matches, currentTargets, transcript, skipped) {
84
- const eligibleCandidates = [];
85
- const eligibleMatches = [];
108
+ const rejected = new Set();
109
+ const accepted = new Set();
110
+ let acceptedTargets = [...currentTargets];
111
+ const base = assistantTurnsForTargets(transcript, currentTargets);
112
+ const signedTurnByEntryId = new Map();
113
+ base.turns.forEach((turn, turnIndex) => {
114
+ for (const entryId of turn.signedThinkingEntryIds)
115
+ signedTurnByEntryId.set(entryId, turnIndex);
116
+ });
117
+ const boundaries = [];
118
+ const ordinary = [];
119
+ const semantic = [];
86
120
  for (let index = 0; index < candidates.length; index++) {
87
121
  const candidate = candidates[index];
88
- const match = matches[index];
89
- if (!candidate || !match)
122
+ if (candidateRemovesBoundary(transcript, currentTargets, candidate)) {
123
+ boundaries.push(index);
90
124
  continue;
91
- try {
92
- const mergedTargets = mergeContextDeletionTargets(currentTargets, [candidate]);
93
- validateContextDeletionRequest(deletionRequestFromTargets(mergedTargets), transcript);
94
- eligibleCandidates.push(candidate);
95
- eligibleMatches.push(match);
96
125
  }
97
- catch (error) {
98
- const message = formatErrorMessage(error);
99
- if (isProtectedContextDeletionErrorMessage(message)) {
100
- pushProtectedGrepSkip(skipped, match);
101
- continue;
126
+ try {
127
+ const single = assistantTurnsForTargets(transcript, mergeContextDeletionTargets(currentTargets, [candidate]));
128
+ const affectedTurns = new Set();
129
+ for (const entryId of single.deletedEntryIds) {
130
+ if (base.deletedEntryIds.has(entryId))
131
+ continue;
132
+ const turnIndex = signedTurnByEntryId.get(entryId);
133
+ if (turnIndex !== undefined)
134
+ affectedTurns.add(turnIndex);
102
135
  }
103
- eligibleCandidates.push(candidate);
104
- eligibleMatches.push(match);
136
+ if (affectedTurns.size === 0)
137
+ ordinary.push(index);
138
+ else
139
+ semantic.push({ index, affectedTurns });
140
+ }
141
+ catch {
142
+ rejected.add(index);
105
143
  }
106
144
  }
107
- // Some latest-assistant thinking violations only become visible after a grep batch also
108
- // deletes newer assistant entries. Classify the newly-unsafe grep candidates as
109
- // protected/skipped before maxMatches, expectedMatchCount, stats, or removals are computed.
110
- let changed = true;
111
- while (changed) {
112
- changed = false;
113
- const mergedTargets = mergeContextDeletionTargets(currentTargets, eligibleCandidates);
114
- const violation = findLatestAssistantThinkingDeletionViolation(transcript, mergedTargets);
115
- if (!violation)
145
+ const components = [];
146
+ for (const item of semantic) {
147
+ const overlapping = components.filter((component) => component.some((member) => [...member.affectedTurns].some((turn) => item.affectedTurns.has(turn))));
148
+ if (overlapping.length === 0) {
149
+ components.push([item]);
116
150
  continue;
117
- const violationKey = targetKey(violation);
118
- let violationIndex = eligibleCandidates.findIndex((candidate) => targetKey(candidate) === violationKey);
119
- if (violationIndex < 0) {
120
- violationIndex = eligibleCandidates.findIndex((_candidate, candidateIndex) => {
121
- const remainingCandidates = eligibleCandidates.filter((_candidateToKeep, index) => index !== candidateIndex);
122
- const remainingTargets = mergeContextDeletionTargets(currentTargets, remainingCandidates);
123
- const remainingViolation = findLatestAssistantThinkingDeletionViolation(transcript, remainingTargets);
124
- return !remainingViolation || targetKey(remainingViolation) !== violationKey;
125
- });
126
151
  }
127
- if (violationIndex < 0)
152
+ const merged = [item, ...overlapping.flat()];
153
+ for (const component of overlapping)
154
+ components.splice(components.indexOf(component), 1);
155
+ components.push(merged.sort((left, right) => left.index - right.index));
156
+ }
157
+ for (const component of components.sort((left, right) => left[0].index - right[0].index)) {
158
+ const indexes = component.map((item) => item.index);
159
+ const proposed = mergeContextDeletionTargets(acceptedTargets, indexes.map((index) => candidates[index]));
160
+ let complete = true;
161
+ try {
162
+ const effect = assistantTurnsForTargets(transcript, proposed);
163
+ const affectedTurns = new Set(component.flatMap((item) => [...item.affectedTurns]));
164
+ for (const turnIndex of affectedTurns) {
165
+ const turn = base.turns[turnIndex];
166
+ if (turn.active || !turn.signedThinkingEntryIds.every((entryId) => effect.deletedEntryIds.has(entryId))) {
167
+ complete = false;
168
+ break;
169
+ }
170
+ }
171
+ if (complete)
172
+ validateContextDeletionRequest(deletionRequestFromTargets(proposed), transcript);
173
+ }
174
+ catch {
175
+ complete = false;
176
+ }
177
+ if (!complete) {
178
+ for (const index of indexes)
179
+ rejected.add(index);
128
180
  continue;
129
- const [skippedMatch] = eligibleMatches.splice(violationIndex, 1);
130
- eligibleCandidates.splice(violationIndex, 1);
131
- if (skippedMatch)
132
- pushProtectedGrepSkip(skipped, skippedMatch);
133
- changed = true;
181
+ }
182
+ acceptedTargets = proposed;
183
+ for (const index of indexes)
184
+ accepted.add(index);
185
+ }
186
+ const acceptIndividually = (indexes) => {
187
+ for (const index of indexes) {
188
+ const proposed = mergeContextDeletionTargets(acceptedTargets, [candidates[index]]);
189
+ try {
190
+ validateContextDeletionRequest(deletionRequestFromTargets(proposed), transcript);
191
+ acceptedTargets = proposed;
192
+ accepted.add(index);
193
+ }
194
+ catch {
195
+ rejected.add(index);
196
+ }
197
+ }
198
+ };
199
+ acceptIndividually(ordinary);
200
+ acceptIndividually(boundaries);
201
+ for (let index = 0; index < matches.length; index++) {
202
+ if (rejected.has(index))
203
+ pushProtectedGrepSkip(skipped, matches[index]);
134
204
  }
135
- return { candidates: eligibleCandidates, matches: eligibleMatches };
205
+ return {
206
+ candidates: candidates.filter((_candidate, index) => accepted.has(index)),
207
+ matches: matches.filter((_match, index) => accepted.has(index)),
208
+ };
136
209
  }
137
210
  //# sourceMappingURL=context-deletion-tool-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-deletion-tool-helpers.js","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tool-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { CompactableTranscript } from \"./context-compaction-types.ts\";\nimport type { ContextGrepDeletionMatch, ContextGrepDeletionSkipped } from \"./context-deletion-tool-definitions.ts\";\nimport {\n\tCONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS,\n\tCONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS,\n} from \"./context-deletion-tool-definitions.ts\";\nimport { formatErrorMessage } from \"./context-compaction-metrics.ts\";\nimport { validateContextDeletionRequest } from \"./context-deletion-application.ts\";\nimport {\n\tdeletionRequestFromTargets,\n\tfindLatestAssistantThinkingDeletionViolation,\n\tgetDeletedContentBlocks,\n\tgetDeletedEntryIds,\n\tisProtectedContextDeletionErrorMessage,\n\tmergeContextDeletionTargets,\n\ttargetKey,\n} from \"./context-deletion-targets.ts\";\n\nexport function escapeRegExpLiteral(text: string): string {\n\treturn text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\nexport function assertSafeRegexPattern(pattern: string): void {\n\tif (pattern.length > CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS) {\n\t\tthrow new Error(\n\t\t\t`Regex pattern is too long (${pattern.length} characters); maximum is ${CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS}`,\n\t\t);\n\t}\n\n\t// Heuristic ReDoS guard for common catastrophic-backtracking shapes. JavaScript's RegExp engine\n\t// does not expose a timeout, so reject nested quantified groups and backreferences instead of\n\t// relying only on transcript scan-size caps.\n\tconst hasNestedQuantifiedGroup = /\\((?:[^()\\\\]|\\\\.)*[+*](?:[^()\\\\]|\\\\.)*\\)\\s*(?:[+*]|\\{\\d)/u.test(pattern);\n\tconst hasQuantifiedAlternation = /\\((?:[^()\\\\]|\\\\.)*\\|(?:[^()\\\\]|\\\\.)*\\)\\s*(?:[+*]|\\{\\d)/u.test(pattern);\n\tconst hasBackreference = /\\\\[1-9]/u.test(pattern);\n\tif (hasNestedQuantifiedGroup || hasQuantifiedAlternation || hasBackreference) {\n\t\tthrow new Error(\n\t\t\t\"Regex pattern is not allowed because it may cause excessive backtracking; use a literal pattern or exact deletion targets instead.\",\n\t\t);\n\t}\n}\n\nexport function createGrepMatcher(pattern: string, regex: boolean, caseSensitive: boolean): RegExp {\n\tif (regex) {\n\t\tassertSafeRegexPattern(pattern);\n\t}\n\n\ttry {\n\t\treturn new RegExp(regex ? pattern : escapeRegExpLiteral(pattern), caseSensitive ? \"u\" : \"iu\");\n\t} catch (error) {\n\t\tthrow new Error(`Invalid grep ${regex ? \"regex\" : \"pattern\"}: ${formatErrorMessage(error)}`);\n\t}\n}\n\nexport function assertSafeRegexScan(scanChars: number): void {\n\tif (scanChars <= CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS) return;\n\tthrow new Error(\n\t\t`Regex grep would scan ${scanChars} characters; maximum is ${CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS}. Use a literal pattern or exact deletion targets instead.`,\n\t);\n}\n\nexport function clampInteger(value: number | undefined, defaultValue: number, minimum: number, maximum: number): number {\n\tif (value === undefined) return defaultValue;\n\treturn Math.max(minimum, Math.min(maximum, value));\n}\n\nexport function textSlice(text: string, offset: number, maxChars: number): string {\n\treturn text.slice(offset, Math.min(text.length, offset + maxChars));\n}\n\nexport function findMatchIndex(matcher: RegExp, text: string): number {\n\tconst match = matcher.exec(text);\n\tmatcher.lastIndex = 0;\n\treturn match?.index ?? -1;\n}\n\nexport function snippetForMatch(text: string, matchIndex: number, contextChars: number): string {\n\tconst start = Math.max(0, matchIndex - contextChars);\n\tconst end = Math.min(text.length, matchIndex + contextChars);\n\tconst prefix = start > 0 ? \"…\" : \"\";\n\tconst suffix = end < text.length ? \"…\" : \"\";\n\treturn `${prefix}${text.slice(start, end)}${suffix}`;\n}\n\nexport function currentTargetDeleted(targets: readonly ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tif (deletedEntryIds.has(target.entryId)) return true;\n\tif (target.kind === \"entry\") return false;\n\treturn getDeletedContentBlocks(targets).get(target.entryId)?.has(target.blockIndex) === true;\n}\n\nexport function addGrepCandidate(\n\tcandidates: ContextDeletionTarget[],\n\tmatches: ContextGrepDeletionMatch[],\n\tseenTargets: Set<string>,\n\tcandidate: ContextDeletionTarget,\n\tmatch: ContextGrepDeletionMatch,\n): void {\n\tconst key = targetKey(candidate);\n\tif (seenTargets.has(key)) return;\n\tseenTargets.add(key);\n\tcandidates.push(candidate);\n\tmatches.push(match);\n}\n\nexport function pushProtectedGrepSkip(skipped: ContextGrepDeletionSkipped[], match: ContextGrepDeletionMatch): void {\n\tskipped.push({\n\t\tentryId: match.entryId,\n\t\ttarget: match.target,\n\t\t...(match.blockIndex === undefined ? {} : { blockIndex: match.blockIndex }),\n\t\treason: match.target === \"content_block\" ? \"protected_block\" : \"protected_entry\",\n\t\ttext: match.text,\n\t});\n}\n\nexport function filterProtectedGrepCandidates(\n\tcandidates: readonly ContextDeletionTarget[],\n\tmatches: readonly ContextGrepDeletionMatch[],\n\tcurrentTargets: readonly ContextDeletionTarget[],\n\ttranscript: CompactableTranscript,\n\tskipped: ContextGrepDeletionSkipped[],\n): { candidates: ContextDeletionTarget[]; matches: ContextGrepDeletionMatch[] } {\n\tconst eligibleCandidates: ContextDeletionTarget[] = [];\n\tconst eligibleMatches: ContextGrepDeletionMatch[] = [];\n\tfor (let index = 0; index < candidates.length; index++) {\n\t\tconst candidate = candidates[index];\n\t\tconst match = matches[index];\n\t\tif (!candidate || !match) continue;\n\t\ttry {\n\t\t\tconst mergedTargets = mergeContextDeletionTargets(currentTargets, [candidate]);\n\t\t\tvalidateContextDeletionRequest(deletionRequestFromTargets(mergedTargets), transcript);\n\t\t\teligibleCandidates.push(candidate);\n\t\t\teligibleMatches.push(match);\n\t\t} catch (error) {\n\t\t\tconst message = formatErrorMessage(error);\n\t\t\tif (isProtectedContextDeletionErrorMessage(message)) {\n\t\t\t\tpushProtectedGrepSkip(skipped, match);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\teligibleCandidates.push(candidate);\n\t\t\teligibleMatches.push(match);\n\t\t}\n\t}\n\n\t// Some latest-assistant thinking violations only become visible after a grep batch also\n\t// deletes newer assistant entries. Classify the newly-unsafe grep candidates as\n\t// protected/skipped before maxMatches, expectedMatchCount, stats, or removals are computed.\n\tlet changed = true;\n\twhile (changed) {\n\t\tchanged = false;\n\t\tconst mergedTargets = mergeContextDeletionTargets(currentTargets, eligibleCandidates);\n\t\tconst violation = findLatestAssistantThinkingDeletionViolation(transcript, mergedTargets);\n\t\tif (!violation) continue;\n\t\tconst violationKey = targetKey(violation);\n\t\tlet violationIndex = eligibleCandidates.findIndex((candidate) => targetKey(candidate) === violationKey);\n\t\tif (violationIndex < 0) {\n\t\t\tviolationIndex = eligibleCandidates.findIndex((_candidate, candidateIndex) => {\n\t\t\t\tconst remainingCandidates = eligibleCandidates.filter((_candidateToKeep, index) => index !== candidateIndex);\n\t\t\t\tconst remainingTargets = mergeContextDeletionTargets(currentTargets, remainingCandidates);\n\t\t\t\tconst remainingViolation = findLatestAssistantThinkingDeletionViolation(transcript, remainingTargets);\n\t\t\t\treturn !remainingViolation || targetKey(remainingViolation) !== violationKey;\n\t\t\t});\n\t\t}\n\t\tif (violationIndex < 0) continue;\n\t\tconst [skippedMatch] = eligibleMatches.splice(violationIndex, 1);\n\t\teligibleCandidates.splice(violationIndex, 1);\n\t\tif (skippedMatch) pushProtectedGrepSkip(skipped, skippedMatch);\n\t\tchanged = true;\n\t}\n\n\treturn { candidates: eligibleCandidates, matches: eligibleMatches };\n}\n"]}
1
+ {"version":3,"file":"context-deletion-tool-helpers.js","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tool-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { CompactableTranscript } from \"./context-compaction-types.ts\";\nimport type { ContextGrepDeletionMatch, ContextGrepDeletionSkipped } from \"./context-deletion-tool-definitions.ts\";\nimport {\n\tCONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS,\n\tCONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS,\n} from \"./context-deletion-tool-definitions.ts\";\nimport { formatErrorMessage } from \"./context-compaction-metrics.ts\";\nimport { reconcileToolDependencies, validateContextDeletionRequest } from \"./context-deletion-application.ts\";\nimport {\n\tdeletionRequestFromTargets,\n\tgetDeletedContentBlocks,\n\tgetDeletedEntryIds,\n\tmergeContextDeletionTargets,\n\ttargetKey,\n} from \"./context-deletion-targets.ts\";\nimport {\n\tanalyzeCompactableAssistantTurns,\n\tisTranscriptEntryEffectivelyDeleted,\n\ttranscriptEntryStartsNewTurn,\n} from \"./context-assistant-turns.js\";\n\nexport function escapeRegExpLiteral(text: string): string {\n\treturn text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\nexport function assertSafeRegexPattern(pattern: string): void {\n\tif (pattern.length > CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS) {\n\t\tthrow new Error(\n\t\t\t`Regex pattern is too long (${pattern.length} characters); maximum is ${CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS}`,\n\t\t);\n\t}\n\n\t// Heuristic ReDoS guard for common catastrophic-backtracking shapes. JavaScript's RegExp engine\n\t// does not expose a timeout, so reject nested quantified groups and backreferences instead of\n\t// relying only on transcript scan-size caps.\n\tconst hasNestedQuantifiedGroup = /\\((?:[^()\\\\]|\\\\.)*[+*](?:[^()\\\\]|\\\\.)*\\)\\s*(?:[+*]|\\{\\d)/u.test(pattern);\n\tconst hasQuantifiedAlternation = /\\((?:[^()\\\\]|\\\\.)*\\|(?:[^()\\\\]|\\\\.)*\\)\\s*(?:[+*]|\\{\\d)/u.test(pattern);\n\tconst hasBackreference = /\\\\[1-9]/u.test(pattern);\n\tif (hasNestedQuantifiedGroup || hasQuantifiedAlternation || hasBackreference) {\n\t\tthrow new Error(\n\t\t\t\"Regex pattern is not allowed because it may cause excessive backtracking; use a literal pattern or exact deletion targets instead.\",\n\t\t);\n\t}\n}\n\nexport function createGrepMatcher(pattern: string, regex: boolean, caseSensitive: boolean): RegExp {\n\tif (regex) {\n\t\tassertSafeRegexPattern(pattern);\n\t}\n\n\ttry {\n\t\treturn new RegExp(regex ? pattern : escapeRegExpLiteral(pattern), caseSensitive ? \"u\" : \"iu\");\n\t} catch (error) {\n\t\tthrow new Error(`Invalid grep ${regex ? \"regex\" : \"pattern\"}: ${formatErrorMessage(error)}`);\n\t}\n}\n\nexport function assertSafeRegexScan(scanChars: number): void {\n\tif (scanChars <= CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS) return;\n\tthrow new Error(\n\t\t`Regex grep would scan ${scanChars} characters; maximum is ${CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS}. Use a literal pattern or exact deletion targets instead.`,\n\t);\n}\n\nexport function clampInteger(value: number | undefined, defaultValue: number, minimum: number, maximum: number): number {\n\tif (value === undefined) return defaultValue;\n\treturn Math.max(minimum, Math.min(maximum, value));\n}\n\nexport function textSlice(text: string, offset: number, maxChars: number): string {\n\treturn text.slice(offset, Math.min(text.length, offset + maxChars));\n}\n\nexport function findMatchIndex(matcher: RegExp, text: string): number {\n\tconst match = matcher.exec(text);\n\tmatcher.lastIndex = 0;\n\treturn match?.index ?? -1;\n}\n\nexport function snippetForMatch(text: string, matchIndex: number, contextChars: number): string {\n\tconst start = Math.max(0, matchIndex - contextChars);\n\tconst end = Math.min(text.length, matchIndex + contextChars);\n\tconst prefix = start > 0 ? \"…\" : \"\";\n\tconst suffix = end < text.length ? \"…\" : \"\";\n\treturn `${prefix}${text.slice(start, end)}${suffix}`;\n}\n\nexport function currentTargetDeleted(targets: readonly ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tif (deletedEntryIds.has(target.entryId)) return true;\n\tif (target.kind === \"entry\") return false;\n\treturn getDeletedContentBlocks(targets).get(target.entryId)?.has(target.blockIndex) === true;\n}\n\nexport function addGrepCandidate(\n\tcandidates: ContextDeletionTarget[],\n\tmatches: ContextGrepDeletionMatch[],\n\tseenTargets: Set<string>,\n\tcandidate: ContextDeletionTarget,\n\tmatch: ContextGrepDeletionMatch,\n): void {\n\tconst key = targetKey(candidate);\n\tif (seenTargets.has(key)) return;\n\tseenTargets.add(key);\n\tcandidates.push(candidate);\n\tmatches.push(match);\n}\n\nexport function pushProtectedGrepSkip(skipped: ContextGrepDeletionSkipped[], match: ContextGrepDeletionMatch): void {\n\tskipped.push({\n\t\tentryId: match.entryId,\n\t\ttarget: match.target,\n\t\t...(match.blockIndex === undefined ? {} : { blockIndex: match.blockIndex }),\n\t\treason: match.target === \"content_block\" ? \"protected_block\" : \"protected_entry\",\n\t\ttext: match.text,\n\t});\n}\n\nfunction assistantTurnsForTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n) {\n\tconst reconciled = reconcileToolDependencies(transcript, targets);\n\treturn { reconciled, ...analyzeCompactableAssistantTurns(transcript, reconciled) };\n}\n\nfunction candidateRemovesBoundary(\n\ttranscript: CompactableTranscript,\n\tcurrentTargets: readonly ContextDeletionTarget[],\n\tcandidate: ContextDeletionTarget,\n): boolean {\n\tconst entry = transcript.entries.find((item) => item.entryId === candidate.entryId);\n\tif (!entry) return false;\n\tconst beforeEntries = getDeletedEntryIds(currentTargets);\n\tconst beforeBlocks = getDeletedContentBlocks(currentTargets);\n\tconst before =\n\t\t!isTranscriptEntryEffectivelyDeleted(entry, beforeEntries, beforeBlocks) &&\n\t\ttranscriptEntryStartsNewTurn(entry, beforeBlocks.get(entry.entryId));\n\tif (!before) return false;\n\ttry {\n\t\tconst after = assistantTurnsForTargets(transcript, mergeContextDeletionTargets(currentTargets, [candidate]));\n\t\treturn isTranscriptEntryEffectivelyDeleted(entry, after.deletedEntryIds, after.deletedContentBlocks) ||\n\t\t\t!transcriptEntryStartsNewTurn(entry, after.deletedContentBlocks.get(entry.entryId));\n\t} catch {\n\t\treturn true;\n\t}\n}\n\ninterface SemanticCandidate {\n\tindex: number;\n\taffectedTurns: Set<number>;\n}\nexport function filterProtectedGrepCandidates(\n\tcandidates: readonly ContextDeletionTarget[],\n\tmatches: readonly ContextGrepDeletionMatch[],\n\tcurrentTargets: readonly ContextDeletionTarget[],\n\ttranscript: CompactableTranscript,\n\tskipped: ContextGrepDeletionSkipped[],\n): { candidates: ContextDeletionTarget[]; matches: ContextGrepDeletionMatch[] } {\n\tconst rejected = new Set<number>();\n\tconst accepted = new Set<number>();\n\tlet acceptedTargets = [...currentTargets];\n\tconst base = assistantTurnsForTargets(transcript, currentTargets);\n\tconst signedTurnByEntryId = new Map<string, number>();\n\tbase.turns.forEach((turn, turnIndex) => {\n\t\tfor (const entryId of turn.signedThinkingEntryIds) signedTurnByEntryId.set(entryId, turnIndex);\n\t});\n\tconst boundaries: number[] = [];\n\tconst ordinary: number[] = [];\n\tconst semantic: SemanticCandidate[] = [];\n\n\tfor (let index = 0; index < candidates.length; index++) {\n\t\tconst candidate = candidates[index]!;\n\t\tif (candidateRemovesBoundary(transcript, currentTargets, candidate)) {\n\t\t\tboundaries.push(index);\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\tconst single = assistantTurnsForTargets(\n\t\t\t\ttranscript,\n\t\t\t\tmergeContextDeletionTargets(currentTargets, [candidate]),\n\t\t\t);\n\t\t\tconst affectedTurns = new Set<number>();\n\t\t\tfor (const entryId of single.deletedEntryIds) {\n\t\t\t\tif (base.deletedEntryIds.has(entryId)) continue;\n\t\t\t\tconst turnIndex = signedTurnByEntryId.get(entryId);\n\t\t\t\tif (turnIndex !== undefined) affectedTurns.add(turnIndex);\n\t\t\t}\n\t\t\tif (affectedTurns.size === 0) ordinary.push(index);\n\t\t\telse semantic.push({ index, affectedTurns });\n\t\t} catch {\n\t\t\trejected.add(index);\n\t\t}\n\t}\n\n\tconst components: SemanticCandidate[][] = [];\n\tfor (const item of semantic) {\n\t\tconst overlapping = components.filter((component) =>\n\t\t\tcomponent.some((member) => [...member.affectedTurns].some((turn) => item.affectedTurns.has(turn))),\n\t\t);\n\t\tif (overlapping.length === 0) {\n\t\t\tcomponents.push([item]);\n\t\t\tcontinue;\n\t\t}\n\t\tconst merged = [item, ...overlapping.flat()];\n\t\tfor (const component of overlapping) components.splice(components.indexOf(component), 1);\n\t\tcomponents.push(merged.sort((left, right) => left.index - right.index));\n\t}\n\n\tfor (const component of components.sort((left, right) => left[0]!.index - right[0]!.index)) {\n\t\tconst indexes = component.map((item) => item.index);\n\t\tconst proposed = mergeContextDeletionTargets(acceptedTargets, indexes.map((index) => candidates[index]!));\n\t\tlet complete = true;\n\t\ttry {\n\t\t\tconst effect = assistantTurnsForTargets(transcript, proposed);\n\t\t\tconst affectedTurns = new Set(component.flatMap((item) => [...item.affectedTurns]));\n\t\t\tfor (const turnIndex of affectedTurns) {\n\t\t\t\tconst turn = base.turns[turnIndex]!;\n\t\t\t\tif (turn.active || !turn.signedThinkingEntryIds.every((entryId) => effect.deletedEntryIds.has(entryId))) {\n\t\t\t\t\tcomplete = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (complete) validateContextDeletionRequest(deletionRequestFromTargets(proposed), transcript);\n\t\t} catch {\n\t\t\tcomplete = false;\n\t\t}\n\t\tif (!complete) {\n\t\t\tfor (const index of indexes) rejected.add(index);\n\t\t\tcontinue;\n\t\t}\n\t\tacceptedTargets = proposed;\n\t\tfor (const index of indexes) accepted.add(index);\n\t}\n\n\tconst acceptIndividually = (indexes: readonly number[]): void => {\n\t\tfor (const index of indexes) {\n\t\t\tconst proposed = mergeContextDeletionTargets(acceptedTargets, [candidates[index]!]);\n\t\t\ttry {\n\t\t\t\tvalidateContextDeletionRequest(deletionRequestFromTargets(proposed), transcript);\n\t\t\t\tacceptedTargets = proposed;\n\t\t\t\taccepted.add(index);\n\t\t\t} catch {\n\t\t\t\trejected.add(index);\n\t\t\t}\n\t\t}\n\t};\n\tacceptIndividually(ordinary);\n\tacceptIndividually(boundaries);\n\n\tfor (let index = 0; index < matches.length; index++) {\n\t\tif (rejected.has(index)) pushProtectedGrepSkip(skipped, matches[index]!);\n\t}\n\treturn {\n\t\tcandidates: candidates.filter((_candidate, index) => accepted.has(index)),\n\t\tmatches: matches.filter((_match, index) => accepted.has(index)),\n\t};\n}\n"]}
@@ -1,9 +1,8 @@
1
1
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
2
  import { type SessionEntry } from "../session-manager.ts";
3
3
  import type { CompactionSettings } from "./compaction.ts";
4
- import { type CompactableTranscriptEntry, type ContextCompactionPreparation, type ContextCompactionRunOptions } from "./context-compaction-types.ts";
4
+ import { type ContextCompactionPreparation, type ContextCompactionRunOptions } from "./context-compaction-types.ts";
5
5
  export declare function isExcludedFromLlmContext(message: AgentMessage): boolean;
6
- export declare function assistantEntryHasThinkingContentBlock(entry: CompactableTranscriptEntry): boolean;
7
6
  export declare function hasAssistantError(message: AgentMessage): boolean;
8
7
  export declare function hasToolResultError(message: AgentMessage): boolean;
9
8
  export declare function hasFailedBashExecution(message: AgentMessage): boolean;