@bastani/atomic 0.9.9 → 0.9.10

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 (864) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/README.md +2 -0
  3. package/dist/builtin/cursor/CHANGELOG.md +12 -0
  4. package/dist/builtin/cursor/package.json +3 -3
  5. package/dist/builtin/intercom/CHANGELOG.md +30 -0
  6. package/dist/builtin/intercom/README.md +12 -4
  7. package/dist/builtin/intercom/broker/broker.ts +96 -14
  8. package/dist/builtin/intercom/broker/client-message-validation.ts +39 -0
  9. package/dist/builtin/intercom/broker/client.ts +101 -92
  10. package/dist/builtin/intercom/broker/group-isolation.ts +28 -0
  11. package/dist/builtin/intercom/broker/send-handler.ts +62 -10
  12. package/dist/builtin/intercom/broker/send-signature.ts +3 -0
  13. package/dist/builtin/intercom/broker/supervisor-channel.ts +126 -0
  14. package/dist/builtin/intercom/closed-workflow-stage-message.ts +66 -0
  15. package/dist/builtin/intercom/config.ts +10 -0
  16. package/dist/builtin/intercom/contact-supervisor-tool.ts +14 -10
  17. package/dist/builtin/intercom/foreground-detach-handoff.ts +12 -2
  18. package/dist/builtin/intercom/group.ts +46 -0
  19. package/dist/builtin/intercom/inbound-message-admission.ts +79 -0
  20. package/dist/builtin/intercom/incoming-message-delivery.ts +49 -0
  21. package/dist/builtin/intercom/index-heavy.ts +148 -94
  22. package/dist/builtin/intercom/index.ts +66 -4
  23. package/dist/builtin/intercom/intercom-test-seams.ts +6 -0
  24. package/dist/builtin/intercom/intercom-tool.ts +71 -20
  25. package/dist/builtin/intercom/intercom-utils.ts +15 -2
  26. package/dist/builtin/intercom/late-stage-message-router.ts +148 -0
  27. package/dist/builtin/intercom/lifecycle.ts +10 -4
  28. package/dist/builtin/intercom/package.json +2 -2
  29. package/dist/builtin/intercom/reconnect-backoff.ts +6 -0
  30. package/dist/builtin/intercom/reply-tracker.ts +8 -0
  31. package/dist/builtin/intercom/skills/intercom/SKILL.md +2 -0
  32. package/dist/builtin/intercom/stable-delivery-retry.ts +32 -0
  33. package/dist/builtin/intercom/subagent-relay.ts +67 -14
  34. package/dist/builtin/intercom/supervisor-authorization-registry.ts +22 -0
  35. package/dist/builtin/intercom/terminal-ordering-barrier.ts +144 -25
  36. package/dist/builtin/intercom/types.ts +18 -5
  37. package/dist/builtin/intercom/workflow-reply-tracker.ts +19 -0
  38. package/dist/builtin/intercom/workflow-stage-admission.ts +43 -0
  39. package/dist/builtin/intercom/workflow-stage-delivery-failure.ts +77 -0
  40. package/dist/builtin/mcp/CHANGELOG.md +22 -0
  41. package/dist/builtin/mcp/README.md +6 -2
  42. package/dist/builtin/mcp/config.ts +8 -8
  43. package/dist/builtin/mcp/direct-tool-executor.ts +7 -6
  44. package/dist/builtin/mcp/package.json +3 -3
  45. package/dist/builtin/mcp/proxy-call.ts +5 -4
  46. package/dist/builtin/mcp/sampling-handler.ts +7 -2
  47. package/dist/builtin/mcp/tool-call-timeout.ts +101 -0
  48. package/dist/builtin/mcp/tool-result-renderer.ts +3 -2
  49. package/dist/builtin/mcp/types.ts +5 -0
  50. package/dist/builtin/mcp/ui-server.ts +3 -2
  51. package/dist/builtin/subagents/CHANGELOG.md +42 -0
  52. package/dist/builtin/subagents/README.md +6 -3
  53. package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
  54. package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
  55. package/dist/builtin/subagents/agents/codebase-locator.md +1 -1
  56. package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
  57. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +1 -1
  58. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
  59. package/dist/builtin/subagents/agents/codebase-research-locator.md +1 -1
  60. package/dist/builtin/subagents/agents/debugger.md +1 -1
  61. package/dist/builtin/subagents/agents/worker.md +1 -1
  62. package/dist/builtin/subagents/package.json +4 -4
  63. package/dist/builtin/subagents/skills/subagent/SKILL.md +1 -1
  64. package/dist/builtin/subagents/src/extension/index.ts +37 -61
  65. package/dist/builtin/subagents/src/extension/notification-content.ts +80 -0
  66. package/dist/builtin/subagents/src/extension/schemas.ts +9 -0
  67. package/dist/builtin/subagents/src/extension/tool-description.ts +1 -0
  68. package/dist/builtin/subagents/src/intercom/supervisor-authorization.ts +23 -0
  69. package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +4 -0
  70. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +2 -0
  71. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +4 -0
  72. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +75 -13
  73. package/dist/builtin/subagents/src/runs/background/async-status.ts +19 -0
  74. package/dist/builtin/subagents/src/runs/background/completion-notification.ts +4 -3
  75. package/dist/builtin/subagents/src/runs/background/notify.ts +76 -15
  76. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +1 -1
  77. package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +13 -0
  78. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +1 -0
  79. package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +1 -0
  80. package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +2 -1
  81. package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +4 -0
  82. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +13 -0
  83. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +19 -2
  84. package/dist/builtin/subagents/src/runs/foreground/detached-cleanup-barrier.ts +26 -0
  85. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +19 -30
  86. package/dist/builtin/subagents/src/runs/foreground/execution-intercom-detach.ts +47 -0
  87. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +60 -2
  88. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +21 -0
  89. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +21 -2
  90. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +6 -1
  91. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +2 -0
  92. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +2 -0
  93. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +1 -1
  94. package/dist/builtin/subagents/src/runs/shared/intercom-group.ts +50 -0
  95. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +16 -0
  96. package/dist/builtin/subagents/src/runs/shared/worktree-post-create.ts +75 -0
  97. package/dist/builtin/subagents/src/runs/shared/worktree-root.ts +51 -0
  98. package/dist/builtin/subagents/src/runs/shared/worktree.ts +69 -77
  99. package/dist/builtin/subagents/src/shared/types-config.ts +6 -0
  100. package/dist/builtin/subagents/src/slash/slash-commands.ts +3 -2
  101. package/dist/builtin/subagents/src/tui/render-result-compact.ts +5 -3
  102. package/dist/builtin/subagents/src/tui/render-result.ts +5 -3
  103. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +7 -4
  104. package/dist/builtin/web-access/CHANGELOG.md +22 -0
  105. package/dist/builtin/web-access/extract-frames.ts +14 -13
  106. package/dist/builtin/web-access/extract.ts +2 -2
  107. package/dist/builtin/web-access/gemini-api.ts +0 -3
  108. package/dist/builtin/web-access/gemini-web-config.ts +1 -3
  109. package/dist/builtin/web-access/gemini-web.ts +1 -0
  110. package/dist/builtin/web-access/package.json +2 -2
  111. package/dist/builtin/web-access/perplexity.ts +0 -3
  112. package/dist/builtin/web-access/result-renderers.ts +7 -5
  113. package/dist/builtin/web-access/subprocess.ts +100 -0
  114. package/dist/builtin/web-access/summary-review.ts +14 -3
  115. package/dist/builtin/web-access/video-extract.ts +12 -17
  116. package/dist/builtin/web-access/web-search-browser.ts +18 -10
  117. package/dist/builtin/web-access/web-search-summary.ts +9 -2
  118. package/dist/builtin/web-access/youtube-extract.ts +22 -25
  119. package/dist/builtin/workflows/CHANGELOG.md +153 -0
  120. package/dist/builtin/workflows/README.md +76 -38
  121. package/dist/builtin/workflows/ambient.d.ts +30 -0
  122. package/dist/builtin/workflows/builtin/adversarial-verification-prompts.ts +15 -0
  123. package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +93 -0
  124. package/dist/builtin/workflows/builtin/adversarial-verification.d.ts +11 -0
  125. package/dist/builtin/workflows/builtin/adversarial-verification.ts +24 -0
  126. package/dist/builtin/workflows/builtin/classify-and-act-prompts.ts +11 -0
  127. package/dist/builtin/workflows/builtin/classify-and-act-runner.ts +110 -0
  128. package/dist/builtin/workflows/builtin/classify-and-act.d.ts +24 -0
  129. package/dist/builtin/workflows/builtin/classify-and-act.ts +35 -0
  130. package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +8 -2
  131. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-prompts.ts +11 -0
  132. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts +96 -0
  133. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.d.ts +23 -0
  134. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.ts +32 -0
  135. package/dist/builtin/workflows/builtin/generate-and-filter-prompts.ts +15 -0
  136. package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +75 -0
  137. package/dist/builtin/workflows/builtin/generate-and-filter.d.ts +11 -0
  138. package/dist/builtin/workflows/builtin/generate-and-filter.ts +26 -0
  139. package/dist/builtin/workflows/builtin/goal-models.ts +72 -0
  140. package/dist/builtin/workflows/builtin/goal-runner.ts +2 -64
  141. package/dist/builtin/workflows/builtin/index.d.ts +44 -0
  142. package/dist/builtin/workflows/builtin/index.ts +6 -0
  143. package/dist/builtin/workflows/builtin/loop-until-done-prompts.ts +79 -0
  144. package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +189 -0
  145. package/dist/builtin/workflows/builtin/loop-until-done.d.ts +34 -0
  146. package/dist/builtin/workflows/builtin/loop-until-done.ts +31 -0
  147. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +6 -1
  148. package/dist/builtin/workflows/builtin/pattern-artifact-root.ts +28 -0
  149. package/dist/builtin/workflows/builtin/ralph-models.ts +26 -5
  150. package/dist/builtin/workflows/builtin/ralph-runner.ts +1 -0
  151. package/dist/builtin/workflows/builtin/tournament-prompts.ts +79 -0
  152. package/dist/builtin/workflows/builtin/tournament-runner.ts +188 -0
  153. package/dist/builtin/workflows/builtin/tournament.d.ts +33 -0
  154. package/dist/builtin/workflows/builtin/tournament.ts +34 -0
  155. package/dist/builtin/workflows/package.json +2 -2
  156. package/dist/builtin/workflows/src/authoring.d.ts +2 -6
  157. package/dist/builtin/workflows/src/durable/backend.ts +163 -120
  158. package/dist/builtin/workflows/src/durable/completed-catalog.ts +37 -64
  159. package/dist/builtin/workflows/src/durable/completed-inspection.ts +4 -72
  160. package/dist/builtin/workflows/src/durable/dbos-backend.ts +242 -195
  161. package/dist/builtin/workflows/src/durable/dbos-embedded-postgres.ts +207 -0
  162. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +42 -42
  163. package/dist/builtin/workflows/src/durable/dbos-lifecycle.ts +155 -0
  164. package/dist/builtin/workflows/src/durable/dbos-local-postgres.ts +126 -0
  165. package/dist/builtin/workflows/src/durable/dbos-metadata.ts +105 -58
  166. package/dist/builtin/workflows/src/durable/dbos-prompt-reservations.ts +320 -0
  167. package/dist/builtin/workflows/src/durable/dbos-sdk-handle.ts +161 -0
  168. package/dist/builtin/workflows/src/durable/dbos-status-transition.ts +62 -0
  169. package/dist/builtin/workflows/src/durable/dbos-tombstone.ts +2 -2
  170. package/dist/builtin/workflows/src/durable/durable-hash.ts +20 -0
  171. package/dist/builtin/workflows/src/durable/factory.ts +23 -83
  172. package/dist/builtin/workflows/src/durable/format-version.ts +4 -10
  173. package/dist/builtin/workflows/src/durable/index.ts +16 -20
  174. package/dist/builtin/workflows/src/durable/local-command.ts +63 -0
  175. package/dist/builtin/workflows/src/durable/prompt-reservation-state.ts +177 -0
  176. package/dist/builtin/workflows/src/durable/prompt-reservations.ts +36 -0
  177. package/dist/builtin/workflows/src/durable/resume-catalog.ts +2 -200
  178. package/dist/builtin/workflows/src/durable/resume-eligibility.ts +42 -2
  179. package/dist/builtin/workflows/src/durable/resume-runtime.ts +121 -118
  180. package/dist/builtin/workflows/src/durable/retention-policy.ts +42 -0
  181. package/dist/builtin/workflows/src/durable/run-timing.ts +98 -0
  182. package/dist/builtin/workflows/src/durable/scoped-backend.ts +62 -14
  183. package/dist/builtin/workflows/src/durable/stage-primitive.ts +15 -2
  184. package/dist/builtin/workflows/src/durable/tool-primitive.ts +11 -7
  185. package/dist/builtin/workflows/src/durable/types.ts +25 -18
  186. package/dist/builtin/workflows/src/durable/ui-primitive.ts +117 -29
  187. package/dist/builtin/workflows/src/durable/workflow-status-transition.ts +30 -0
  188. package/dist/builtin/workflows/src/engine/primitives/parallel.ts +20 -5
  189. package/dist/builtin/workflows/src/engine/primitives/task.ts +3 -2
  190. package/dist/builtin/workflows/src/engine/primitives/ui.ts +6 -3
  191. package/dist/builtin/workflows/src/engine/run-durable-finalize.ts +14 -22
  192. package/dist/builtin/workflows/src/engine/run-durable-stage-session.ts +14 -14
  193. package/dist/builtin/workflows/src/engine/run.ts +35 -37
  194. package/dist/builtin/workflows/src/engine/runtime.ts +3 -0
  195. package/dist/builtin/workflows/src/engine/workflow-activity.ts +9 -0
  196. package/dist/builtin/workflows/src/extension/completed-stage-intercom-ask.ts +155 -0
  197. package/dist/builtin/workflows/src/extension/config-file-loader.ts +13 -0
  198. package/dist/builtin/workflows/src/extension/config-loader.ts +20 -0
  199. package/dist/builtin/workflows/src/extension/dispatcher.ts +56 -17
  200. package/dist/builtin/workflows/src/extension/extension-factory.ts +13 -10
  201. package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +37 -59
  202. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +16 -18
  203. package/dist/builtin/workflows/src/extension/lifecycle-notification-delivery.ts +83 -0
  204. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +80 -41
  205. package/dist/builtin/workflows/src/extension/postmortem-deps.ts +73 -0
  206. package/dist/builtin/workflows/src/extension/public-types.ts +11 -51
  207. package/dist/builtin/workflows/src/extension/render-call.ts +3 -9
  208. package/dist/builtin/workflows/src/extension/render-result.ts +22 -7
  209. package/dist/builtin/workflows/src/extension/runtime-active-block-claim.ts +78 -0
  210. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +50 -29
  211. package/dist/builtin/workflows/src/extension/runtime.ts +70 -219
  212. package/dist/builtin/workflows/src/extension/ui-surface.ts +107 -3
  213. package/dist/builtin/workflows/src/extension/wiring.ts +76 -7
  214. package/dist/builtin/workflows/src/extension/workflow-command-completions.ts +10 -5
  215. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +27 -5
  216. package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +49 -19
  217. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +8 -8
  218. package/dist/builtin/workflows/src/extension/workflow-resume-picker-rows.ts +81 -0
  219. package/dist/builtin/workflows/src/extension/workflow-resume-shadow.ts +55 -0
  220. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +193 -145
  221. package/dist/builtin/workflows/src/extension/workflow-schema.ts +9 -133
  222. package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +189 -0
  223. package/dist/builtin/workflows/src/extension/workflow-targets.ts +1 -1
  224. package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +78 -3
  225. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +185 -89
  226. package/dist/builtin/workflows/src/extension/workflow-tool-send.ts +92 -11
  227. package/dist/builtin/workflows/src/extension/workflow-tool.ts +18 -24
  228. package/dist/builtin/workflows/src/runs/background/durable-resume-transition.ts +63 -0
  229. package/dist/builtin/workflows/src/runs/background/quit.ts +139 -29
  230. package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +97 -0
  231. package/dist/builtin/workflows/src/runs/background/run-inspect.ts +111 -0
  232. package/dist/builtin/workflows/src/runs/background/runner.ts +46 -17
  233. package/dist/builtin/workflows/src/runs/background/startup-admission.ts +77 -0
  234. package/dist/builtin/workflows/src/runs/background/status.ts +133 -224
  235. package/dist/builtin/workflows/src/runs/background/workflow-lifecycle-aggregate.ts +44 -0
  236. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +57 -256
  237. package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +7 -4
  238. package/dist/builtin/workflows/src/runs/foreground/executor-lifecycle.ts +12 -1
  239. package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +39 -0
  240. package/dist/builtin/workflows/src/runs/foreground/executor-queued-user-message.ts +75 -0
  241. package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +44 -12
  242. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +63 -12
  243. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +30 -4
  244. package/dist/builtin/workflows/src/runs/foreground/executor-stage-replay.ts +3 -0
  245. package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +4 -1
  246. package/dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts +0 -67
  247. package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +6 -0
  248. package/dist/builtin/workflows/src/runs/foreground/executor.ts +0 -1
  249. package/dist/builtin/workflows/src/runs/foreground/postmortem-stage-chat.ts +169 -0
  250. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +38 -1
  251. package/dist/builtin/workflows/src/runs/foreground/stage-runner-candidate.ts +21 -0
  252. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +21 -3
  253. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +85 -84
  254. package/dist/builtin/workflows/src/runs/foreground/stage-runner-message-admission.ts +195 -0
  255. package/dist/builtin/workflows/src/runs/foreground/stage-runner-options.ts +12 -5
  256. package/dist/builtin/workflows/src/runs/foreground/stage-runner-replacement.ts +42 -0
  257. package/dist/builtin/workflows/src/runs/foreground/stage-runner-send-user-message.ts +100 -8
  258. package/dist/builtin/workflows/src/runs/foreground/stage-runner-session-options.ts +51 -0
  259. package/dist/builtin/workflows/src/runs/foreground/stage-runner-session.ts +19 -0
  260. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +28 -2
  261. package/dist/builtin/workflows/src/runs/shared/prompt-callsite.ts +4 -6
  262. package/dist/builtin/workflows/src/runs/shared/worktree-git-runner.ts +89 -0
  263. package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +29 -133
  264. package/dist/builtin/workflows/src/runs/shared/worktree-post-create.ts +130 -0
  265. package/dist/builtin/workflows/src/runs/shared/worktree-root.ts +84 -0
  266. package/dist/builtin/workflows/src/runs/shared/worktree-setup.ts +77 -63
  267. package/dist/builtin/workflows/src/runs/shared/worktree-types.ts +4 -0
  268. package/dist/builtin/workflows/src/sdk-surface.ts +1 -1
  269. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +29 -22
  270. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +26 -24
  271. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -0
  272. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
  273. package/dist/builtin/workflows/src/shared/intercom-group.ts +51 -0
  274. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +6 -0
  275. package/dist/builtin/workflows/src/shared/persistence-restore.ts +4 -0
  276. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +3 -0
  277. package/dist/builtin/workflows/src/shared/prompt-callsite-context.ts +13 -0
  278. package/dist/builtin/workflows/src/shared/returned-run-status.ts +2 -1
  279. package/dist/builtin/workflows/src/shared/session-transcript.ts +74 -0
  280. package/dist/builtin/workflows/src/shared/store-stage-methods.ts +1 -0
  281. package/dist/builtin/workflows/src/shared/store-types.ts +8 -0
  282. package/dist/builtin/workflows/src/shared/timing.ts +4 -1
  283. package/dist/builtin/workflows/src/shared/types.ts +2 -6
  284. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +2 -42
  285. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +2 -2
  286. package/dist/builtin/workflows/src/tui/graph-view-constants.ts +7 -3
  287. package/dist/builtin/workflows/src/tui/graph-view-input.ts +29 -67
  288. package/dist/builtin/workflows/src/tui/graph-view-render-helpers.ts +15 -10
  289. package/dist/builtin/workflows/src/tui/graph-view-state.ts +0 -2
  290. package/dist/builtin/workflows/src/tui/graph-view-types.ts +3 -9
  291. package/dist/builtin/workflows/src/tui/host-input-form.ts +62 -0
  292. package/dist/builtin/workflows/src/tui/mouse-input.ts +63 -0
  293. package/dist/builtin/workflows/src/tui/node-card.ts +1 -0
  294. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +67 -42
  295. package/dist/builtin/workflows/src/tui/overlay-terminal-modes.ts +49 -0
  296. package/dist/builtin/workflows/src/tui/session-overlays.ts +3 -104
  297. package/dist/builtin/workflows/src/tui/session-picker.ts +3 -12
  298. package/dist/builtin/workflows/src/tui/stage-chat-composer-drafts.ts +19 -0
  299. package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +30 -10
  300. package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +19 -9
  301. package/dist/builtin/workflows/src/tui/stage-chat-view-input.ts +25 -38
  302. package/dist/builtin/workflows/src/tui/stage-chat-view-render-helpers.ts +1 -1
  303. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +7 -6
  304. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +7 -1
  305. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +3 -1
  306. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +19 -20
  307. package/dist/builtin/workflows/src/tui/switcher.ts +4 -4
  308. package/dist/builtin/workflows/src/tui/widget.ts +46 -33
  309. package/dist/builtin/workflows/src/tui/workflow-attach-pane-handle.ts +26 -0
  310. package/dist/builtin/workflows/src/tui/workflow-attach-pane-types.ts +14 -2
  311. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +26 -27
  312. package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +208 -69
  313. package/dist/bun/cli.js +3 -0
  314. package/dist/bun/cli.js.map +1 -1
  315. package/dist/cli/session-picker.d.ts.map +1 -1
  316. package/dist/cli/session-picker.js +3 -0
  317. package/dist/cli/session-picker.js.map +1 -1
  318. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  319. package/dist/core/agent-session-auto-compaction.js +19 -2
  320. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  321. package/dist/core/agent-session-compaction.js +2 -2
  322. package/dist/core/agent-session-compaction.js.map +1 -1
  323. package/dist/core/agent-session-events.d.ts.map +1 -1
  324. package/dist/core/agent-session-events.js +5 -3
  325. package/dist/core/agent-session-events.js.map +1 -1
  326. package/dist/core/agent-session-export.js +1 -1
  327. package/dist/core/agent-session-export.js.map +1 -1
  328. package/dist/core/agent-session-extension-bindings.d.ts +2 -4
  329. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  330. package/dist/core/agent-session-extension-bindings.js +9 -2
  331. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  332. package/dist/core/agent-session-message-queue.d.ts +6 -0
  333. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  334. package/dist/core/agent-session-message-queue.js +107 -36
  335. package/dist/core/agent-session-message-queue.js.map +1 -1
  336. package/dist/core/agent-session-methods.d.ts +18 -7
  337. package/dist/core/agent-session-methods.d.ts.map +1 -1
  338. package/dist/core/agent-session-methods.js.map +1 -1
  339. package/dist/core/agent-session-models.d.ts +3 -1
  340. package/dist/core/agent-session-models.d.ts.map +1 -1
  341. package/dist/core/agent-session-models.js +1 -1
  342. package/dist/core/agent-session-models.js.map +1 -1
  343. package/dist/core/agent-session-post-tool-compaction.d.ts +16 -0
  344. package/dist/core/agent-session-post-tool-compaction.d.ts.map +1 -0
  345. package/dist/core/agent-session-post-tool-compaction.js +113 -0
  346. package/dist/core/agent-session-post-tool-compaction.js.map +1 -0
  347. package/dist/core/agent-session-prompt.d.ts +12 -1
  348. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  349. package/dist/core/agent-session-prompt.js +22 -5
  350. package/dist/core/agent-session-prompt.js.map +1 -1
  351. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  352. package/dist/core/agent-session-runtime.js +3 -0
  353. package/dist/core/agent-session-runtime.js.map +1 -1
  354. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  355. package/dist/core/agent-session-tool-hooks.js +21 -0
  356. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  357. package/dist/core/agent-session-tree.d.ts.map +1 -1
  358. package/dist/core/agent-session-tree.js +2 -1
  359. package/dist/core/agent-session-tree.js.map +1 -1
  360. package/dist/core/agent-session-types.d.ts +7 -0
  361. package/dist/core/agent-session-types.d.ts.map +1 -1
  362. package/dist/core/agent-session-types.js.map +1 -1
  363. package/dist/core/agent-session.d.ts +6 -0
  364. package/dist/core/agent-session.d.ts.map +1 -1
  365. package/dist/core/agent-session.js +18 -1
  366. package/dist/core/agent-session.js.map +1 -1
  367. package/dist/core/async/job-manager.d.ts +1 -0
  368. package/dist/core/async/job-manager.d.ts.map +1 -1
  369. package/dist/core/async/job-manager.js +29 -5
  370. package/dist/core/async/job-manager.js.map +1 -1
  371. package/dist/core/async/session-manager.d.ts +2 -4
  372. package/dist/core/async/session-manager.d.ts.map +1 -1
  373. package/dist/core/async/session-manager.js +5 -32
  374. package/dist/core/async/session-manager.js.map +1 -1
  375. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  376. package/dist/core/atomic-guide-command.js +2 -0
  377. package/dist/core/atomic-guide-command.js.map +1 -1
  378. package/dist/core/auth-storage.d.ts +20 -10
  379. package/dist/core/auth-storage.d.ts.map +1 -1
  380. package/dist/core/auth-storage.js +151 -92
  381. package/dist/core/auth-storage.js.map +1 -1
  382. package/dist/core/callback-activity.d.ts +27 -0
  383. package/dist/core/callback-activity.d.ts.map +1 -0
  384. package/dist/core/callback-activity.js +44 -0
  385. package/dist/core/callback-activity.js.map +1 -0
  386. package/dist/core/compaction/branch-summarization.d.ts +4 -1
  387. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  388. package/dist/core/compaction/branch-summarization.js +4 -3
  389. package/dist/core/compaction/branch-summarization.js.map +1 -1
  390. package/dist/core/compaction/compaction-boundary.d.ts +1 -1
  391. package/dist/core/compaction/compaction-boundary.d.ts.map +1 -1
  392. package/dist/core/compaction/compaction-boundary.js +10 -23
  393. package/dist/core/compaction/compaction-boundary.js.map +1 -1
  394. package/dist/core/compaction/compaction-runner.d.ts +4 -1
  395. package/dist/core/compaction/compaction-runner.d.ts.map +1 -1
  396. package/dist/core/compaction/compaction-runner.js +1 -1
  397. package/dist/core/compaction/compaction-runner.js.map +1 -1
  398. package/dist/core/compaction/compaction-types.d.ts +3 -2
  399. package/dist/core/compaction/compaction-types.d.ts.map +1 -1
  400. package/dist/core/compaction/compaction-types.js.map +1 -1
  401. package/dist/core/compaction/compaction.d.ts +6 -6
  402. package/dist/core/compaction/compaction.d.ts.map +1 -1
  403. package/dist/core/compaction/compaction.js +12 -9
  404. package/dist/core/compaction/compaction.js.map +1 -1
  405. package/dist/core/compaction/index.d.ts +1 -0
  406. package/dist/core/compaction/index.d.ts.map +1 -1
  407. package/dist/core/compaction/index.js +1 -0
  408. package/dist/core/compaction/index.js.map +1 -1
  409. package/dist/core/compaction/range-planner-diagnostics.d.ts +101 -0
  410. package/dist/core/compaction/range-planner-diagnostics.d.ts.map +1 -0
  411. package/dist/core/compaction/range-planner-diagnostics.js +116 -0
  412. package/dist/core/compaction/range-planner-diagnostics.js.map +1 -0
  413. package/dist/core/compaction/range-planner.d.ts +13 -3
  414. package/dist/core/compaction/range-planner.d.ts.map +1 -1
  415. package/dist/core/compaction/range-planner.js +117 -68
  416. package/dist/core/compaction/range-planner.js.map +1 -1
  417. package/dist/core/compaction/truncated-range-recovery.d.ts +47 -0
  418. package/dist/core/compaction/truncated-range-recovery.d.ts.map +1 -0
  419. package/dist/core/compaction/truncated-range-recovery.js +112 -0
  420. package/dist/core/compaction/truncated-range-recovery.js.map +1 -0
  421. package/dist/core/extensions/api-types.d.ts +2 -2
  422. package/dist/core/extensions/api-types.d.ts.map +1 -1
  423. package/dist/core/extensions/api-types.js.map +1 -1
  424. package/dist/core/extensions/context-types.d.ts +23 -1
  425. package/dist/core/extensions/context-types.d.ts.map +1 -1
  426. package/dist/core/extensions/context-types.js.map +1 -1
  427. package/dist/core/extensions/index.d.ts +1 -1
  428. package/dist/core/extensions/index.d.ts.map +1 -1
  429. package/dist/core/extensions/index.js.map +1 -1
  430. package/dist/core/extensions/loader-api.js +2 -2
  431. package/dist/core/extensions/loader-api.js.map +1 -1
  432. package/dist/core/extensions/loader-core.d.ts.map +1 -1
  433. package/dist/core/extensions/loader-core.js +8 -1
  434. package/dist/core/extensions/loader-core.js.map +1 -1
  435. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  436. package/dist/core/extensions/loader-virtual-modules.js +9 -6
  437. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  438. package/dist/core/extensions/message-types.d.ts +17 -0
  439. package/dist/core/extensions/message-types.d.ts.map +1 -1
  440. package/dist/core/extensions/message-types.js.map +1 -1
  441. package/dist/core/extensions/provider-types.d.ts +3 -0
  442. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  443. package/dist/core/extensions/provider-types.js.map +1 -1
  444. package/dist/core/extensions/runner-events.d.ts.map +1 -1
  445. package/dist/core/extensions/runner-events.js +11 -10
  446. package/dist/core/extensions/runner-events.js.map +1 -1
  447. package/dist/core/extensions/runtime-types.d.ts +2 -2
  448. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  449. package/dist/core/extensions/runtime-types.js.map +1 -1
  450. package/dist/core/extensions/ui-types.d.ts +78 -0
  451. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  452. package/dist/core/extensions/ui-types.js.map +1 -1
  453. package/dist/core/model-registry-auth.d.ts +2 -1
  454. package/dist/core/model-registry-auth.d.ts.map +1 -1
  455. package/dist/core/model-registry-auth.js +25 -6
  456. package/dist/core/model-registry-auth.js.map +1 -1
  457. package/dist/core/model-registry-builtins.d.ts +3 -2
  458. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  459. package/dist/core/model-registry-builtins.js +12 -6
  460. package/dist/core/model-registry-builtins.js.map +1 -1
  461. package/dist/core/model-registry-dynamic.d.ts +1 -0
  462. package/dist/core/model-registry-dynamic.d.ts.map +1 -1
  463. package/dist/core/model-registry-dynamic.js +53 -13
  464. package/dist/core/model-registry-dynamic.js.map +1 -1
  465. package/dist/core/model-registry-loader.d.ts +2 -1
  466. package/dist/core/model-registry-loader.d.ts.map +1 -1
  467. package/dist/core/model-registry-loader.js +2 -2
  468. package/dist/core/model-registry-loader.js.map +1 -1
  469. package/dist/core/model-registry-types.d.ts +10 -3
  470. package/dist/core/model-registry-types.d.ts.map +1 -1
  471. package/dist/core/model-registry-types.js.map +1 -1
  472. package/dist/core/model-registry.d.ts +15 -1
  473. package/dist/core/model-registry.d.ts.map +1 -1
  474. package/dist/core/model-registry.js +214 -30
  475. package/dist/core/model-registry.js.map +1 -1
  476. package/dist/core/models-store.d.ts +25 -0
  477. package/dist/core/models-store.d.ts.map +1 -0
  478. package/dist/core/models-store.js +73 -0
  479. package/dist/core/models-store.js.map +1 -0
  480. package/dist/core/oauth-compat.d.ts +17 -0
  481. package/dist/core/oauth-compat.d.ts.map +1 -0
  482. package/dist/core/oauth-compat.js +2 -0
  483. package/dist/core/oauth-compat.js.map +1 -0
  484. package/dist/core/oauth-provider-bridge.d.ts +40 -0
  485. package/dist/core/oauth-provider-bridge.d.ts.map +1 -0
  486. package/dist/core/oauth-provider-bridge.js +169 -0
  487. package/dist/core/oauth-provider-bridge.js.map +1 -0
  488. package/dist/core/output-guard.d.ts +2 -0
  489. package/dist/core/output-guard.d.ts.map +1 -1
  490. package/dist/core/output-guard.js +14 -0
  491. package/dist/core/output-guard.js.map +1 -1
  492. package/dist/core/remote-catalog-provider.d.ts +5 -0
  493. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  494. package/dist/core/remote-catalog-provider.js +138 -0
  495. package/dist/core/remote-catalog-provider.js.map +1 -0
  496. package/dist/core/sdk.d.ts.map +1 -1
  497. package/dist/core/sdk.js +8 -3
  498. package/dist/core/sdk.js.map +1 -1
  499. package/dist/core/session-manager-core.d.ts +1 -1
  500. package/dist/core/session-manager-core.d.ts.map +1 -1
  501. package/dist/core/session-manager-core.js +1 -1
  502. package/dist/core/session-manager-core.js.map +1 -1
  503. package/dist/core/session-manager-entries.d.ts +1 -1
  504. package/dist/core/session-manager-entries.d.ts.map +1 -1
  505. package/dist/core/session-manager-entries.js.map +1 -1
  506. package/dist/core/session-manager-history.d.ts +2 -2
  507. package/dist/core/session-manager-history.js +2 -2
  508. package/dist/core/session-manager-history.js.map +1 -1
  509. package/dist/core/session-manager-list.d.ts.map +1 -1
  510. package/dist/core/session-manager-list.js +65 -23
  511. package/dist/core/session-manager-list.js.map +1 -1
  512. package/dist/core/session-manager-types.d.ts +3 -2
  513. package/dist/core/session-manager-types.d.ts.map +1 -1
  514. package/dist/core/session-manager-types.js.map +1 -1
  515. package/dist/core/slash-commands.d.ts.map +1 -1
  516. package/dist/core/slash-commands.js +9 -5
  517. package/dist/core/slash-commands.js.map +1 -1
  518. package/dist/core/tools/bash.d.ts.map +1 -1
  519. package/dist/core/tools/bash.js +2 -3
  520. package/dist/core/tools/bash.js.map +1 -1
  521. package/dist/core/tools/find.js +2 -2
  522. package/dist/core/tools/find.js.map +1 -1
  523. package/dist/core/tools/grep.js +2 -2
  524. package/dist/core/tools/grep.js.map +1 -1
  525. package/dist/core/tools/ls.js +2 -2
  526. package/dist/core/tools/ls.js.map +1 -1
  527. package/dist/core/tools/read.d.ts.map +1 -1
  528. package/dist/core/tools/read.js +4 -3
  529. package/dist/core/tools/read.js.map +1 -1
  530. package/dist/core/tools/todos-render.d.ts.map +1 -1
  531. package/dist/core/tools/todos-render.js +3 -2
  532. package/dist/core/tools/todos-render.js.map +1 -1
  533. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  534. package/dist/core/tools/tool-definition-wrapper.js +3 -2
  535. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  536. package/dist/core/tools/write.js +2 -2
  537. package/dist/core/tools/write.js.map +1 -1
  538. package/dist/core/workflow-stage-admission.d.ts +29 -0
  539. package/dist/core/workflow-stage-admission.d.ts.map +1 -0
  540. package/dist/core/workflow-stage-admission.js +81 -0
  541. package/dist/core/workflow-stage-admission.js.map +1 -0
  542. package/dist/index-extensions.d.ts +1 -1
  543. package/dist/index-extensions.d.ts.map +1 -1
  544. package/dist/index-extensions.js.map +1 -1
  545. package/dist/index.d.ts +4 -1
  546. package/dist/index.d.ts.map +1 -1
  547. package/dist/index.js +4 -1
  548. package/dist/index.js.map +1 -1
  549. package/dist/main-types.d.ts +13 -0
  550. package/dist/main-types.d.ts.map +1 -0
  551. package/dist/main-types.js +2 -0
  552. package/dist/main-types.js.map +1 -0
  553. package/dist/main.d.ts +2 -5
  554. package/dist/main.d.ts.map +1 -1
  555. package/dist/main.js +25 -17
  556. package/dist/main.js.map +1 -1
  557. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  558. package/dist/modes/interactive/components/assistant-message.js +17 -12
  559. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  560. package/dist/modes/interactive/components/atomic-banner.d.ts +7 -0
  561. package/dist/modes/interactive/components/atomic-banner.d.ts.map +1 -1
  562. package/dist/modes/interactive/components/atomic-banner.js +20 -0
  563. package/dist/modes/interactive/components/atomic-banner.js.map +1 -1
  564. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  565. package/dist/modes/interactive/components/bash-execution.js +5 -3
  566. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  567. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  568. package/dist/modes/interactive/components/branch-summary-message.js +3 -4
  569. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  570. package/dist/modes/interactive/components/chat-message-renderer.d.ts +4 -0
  571. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  572. package/dist/modes/interactive/components/chat-message-renderer.js +4 -0
  573. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  574. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  575. package/dist/modes/interactive/components/chat-session-host-events.js +79 -8
  576. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  577. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
  578. package/dist/modes/interactive/components/chat-session-host-rendering.js +4 -2
  579. package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
  580. package/dist/modes/interactive/components/chat-session-host.d.ts +1 -0
  581. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  582. package/dist/modes/interactive/components/chat-session-host.js +4 -1
  583. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  584. package/dist/modes/interactive/components/compaction-boundary-message.d.ts.map +1 -1
  585. package/dist/modes/interactive/components/compaction-boundary-message.js +3 -4
  586. package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -1
  587. package/dist/modes/interactive/components/host-input-form-mount.d.ts +14 -0
  588. package/dist/modes/interactive/components/host-input-form-mount.d.ts.map +1 -0
  589. package/dist/modes/interactive/components/host-input-form-mount.js +79 -0
  590. package/dist/modes/interactive/components/host-input-form-mount.js.map +1 -0
  591. package/dist/modes/interactive/components/host-input-form.d.ts +52 -0
  592. package/dist/modes/interactive/components/host-input-form.d.ts.map +1 -0
  593. package/dist/modes/interactive/components/host-input-form.js +278 -0
  594. package/dist/modes/interactive/components/host-input-form.js.map +1 -0
  595. package/dist/modes/interactive/components/host-session-picker.d.ts +46 -0
  596. package/dist/modes/interactive/components/host-session-picker.d.ts.map +1 -0
  597. package/dist/modes/interactive/components/host-session-picker.js +183 -0
  598. package/dist/modes/interactive/components/host-session-picker.js.map +1 -0
  599. package/dist/modes/interactive/components/index.d.ts +1 -1
  600. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  601. package/dist/modes/interactive/components/index.js +1 -1
  602. package/dist/modes/interactive/components/index.js.map +1 -1
  603. package/dist/modes/interactive/components/keybinding-hints.d.ts +2 -0
  604. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  605. package/dist/modes/interactive/components/keybinding-hints.js +12 -0
  606. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  607. package/dist/modes/interactive/components/login-dialog.d.ts +3 -1
  608. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  609. package/dist/modes/interactive/components/login-dialog.js +8 -2
  610. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  611. package/dist/modes/interactive/components/model-selector.d.ts +7 -1
  612. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  613. package/dist/modes/interactive/components/model-selector.js +57 -10
  614. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  615. package/dist/modes/interactive/components/session-selector.d.ts +15 -0
  616. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  617. package/dist/modes/interactive/components/session-selector.js +35 -3
  618. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  619. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  620. package/dist/modes/interactive/components/skill-invocation-message.js +3 -2
  621. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  622. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  623. package/dist/modes/interactive/components/tool-execution.js +9 -0
  624. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  625. package/dist/modes/interactive/interactive-agent-events.js +24 -10
  626. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  627. package/dist/modes/interactive/interactive-auth-login.js +7 -1
  628. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  629. package/dist/modes/interactive/interactive-auth-routing.js +3 -3
  630. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  631. package/dist/modes/interactive/interactive-autocomplete.js +49 -0
  632. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  633. package/dist/modes/interactive/interactive-bash-compact.js +2 -0
  634. package/dist/modes/interactive/interactive-bash-compact.js.map +1 -1
  635. package/dist/modes/interactive/interactive-extension-context.js +14 -0
  636. package/dist/modes/interactive/interactive-extension-context.js.map +1 -1
  637. package/dist/modes/interactive/interactive-extension-runtime.js +1 -1
  638. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  639. package/dist/modes/interactive/interactive-global-clear.d.ts +13 -0
  640. package/dist/modes/interactive/interactive-global-clear.d.ts.map +1 -0
  641. package/dist/modes/interactive/interactive-global-clear.js +11 -0
  642. package/dist/modes/interactive/interactive-global-clear.js.map +1 -0
  643. package/dist/modes/interactive/interactive-input-handling.js +17 -10
  644. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  645. package/dist/modes/interactive/interactive-mode-base.d.ts +6 -1
  646. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  647. package/dist/modes/interactive/interactive-mode-base.js +25 -2
  648. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  649. package/dist/modes/interactive/interactive-mode-deps.d.ts +4 -3
  650. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  651. package/dist/modes/interactive/interactive-mode-deps.js +2 -2
  652. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  653. package/dist/modes/interactive/interactive-mode-helpers.d.ts +4 -1
  654. package/dist/modes/interactive/interactive-mode-helpers.d.ts.map +1 -1
  655. package/dist/modes/interactive/interactive-mode-helpers.js +14 -1
  656. package/dist/modes/interactive/interactive-mode-helpers.js.map +1 -1
  657. package/dist/modes/interactive/interactive-mode-surface.d.ts +3 -2
  658. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  659. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  660. package/dist/modes/interactive/interactive-mode-types.d.ts +3 -0
  661. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  662. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  663. package/dist/modes/interactive/interactive-model-routing.js +7 -4
  664. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  665. package/dist/modes/interactive/interactive-queueing.js +2 -2
  666. package/dist/modes/interactive/interactive-queueing.js.map +1 -1
  667. package/dist/modes/interactive/interactive-render-chat.js +25 -4
  668. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  669. package/dist/modes/interactive/interactive-session-routing.js +3 -0
  670. package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
  671. package/dist/modes/interactive/interactive-slash-commands.js +5 -2
  672. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  673. package/dist/modes/interactive/interactive-startup.d.ts +1 -1
  674. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  675. package/dist/modes/interactive/interactive-startup.js +22 -9
  676. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  677. package/dist/modes/interactive/interactive-terminal-title.d.ts +6 -0
  678. package/dist/modes/interactive/interactive-terminal-title.d.ts.map +1 -0
  679. package/dist/modes/interactive/interactive-terminal-title.js +7 -0
  680. package/dist/modes/interactive/interactive-terminal-title.js.map +1 -0
  681. package/dist/modes/interactive-engine/activity-watchdog.d.ts +45 -0
  682. package/dist/modes/interactive-engine/activity-watchdog.d.ts.map +1 -0
  683. package/dist/modes/interactive-engine/activity-watchdog.js +74 -0
  684. package/dist/modes/interactive-engine/activity-watchdog.js.map +1 -0
  685. package/dist/modes/interactive-engine/create-isolated-runtime.d.ts +14 -0
  686. package/dist/modes/interactive-engine/create-isolated-runtime.d.ts.map +1 -0
  687. package/dist/modes/interactive-engine/create-isolated-runtime.js +56 -0
  688. package/dist/modes/interactive-engine/create-isolated-runtime.js.map +1 -0
  689. package/dist/modes/interactive-engine/engine-args.d.ts +10 -0
  690. package/dist/modes/interactive-engine/engine-args.d.ts.map +1 -0
  691. package/dist/modes/interactive-engine/engine-args.js +55 -0
  692. package/dist/modes/interactive-engine/engine-args.js.map +1 -0
  693. package/dist/modes/interactive-engine/engine-child-liveness.d.ts +7 -0
  694. package/dist/modes/interactive-engine/engine-child-liveness.d.ts.map +1 -0
  695. package/dist/modes/interactive-engine/engine-child-liveness.js +50 -0
  696. package/dist/modes/interactive-engine/engine-child-liveness.js.map +1 -0
  697. package/dist/modes/interactive-engine/engine-custom-ui.d.ts +47 -0
  698. package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -0
  699. package/dist/modes/interactive-engine/engine-custom-ui.js +276 -0
  700. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -0
  701. package/dist/modes/interactive-engine/engine-input-form.d.ts +13 -0
  702. package/dist/modes/interactive-engine/engine-input-form.d.ts.map +1 -0
  703. package/dist/modes/interactive-engine/engine-input-form.js +49 -0
  704. package/dist/modes/interactive-engine/engine-input-form.js.map +1 -0
  705. package/dist/modes/interactive-engine/engine-monitor.d.ts +18 -0
  706. package/dist/modes/interactive-engine/engine-monitor.d.ts.map +1 -0
  707. package/dist/modes/interactive-engine/engine-monitor.js +63 -0
  708. package/dist/modes/interactive-engine/engine-monitor.js.map +1 -0
  709. package/dist/modes/interactive-engine/engine-render-service.d.ts +17 -0
  710. package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -0
  711. package/dist/modes/interactive-engine/engine-render-service.js +150 -0
  712. package/dist/modes/interactive-engine/engine-render-service.js.map +1 -0
  713. package/dist/modes/interactive-engine/engine-session-picker.d.ts +22 -0
  714. package/dist/modes/interactive-engine/engine-session-picker.d.ts.map +1 -0
  715. package/dist/modes/interactive-engine/engine-session-picker.js +106 -0
  716. package/dist/modes/interactive-engine/engine-session-picker.js.map +1 -0
  717. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts +23 -0
  718. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -0
  719. package/dist/modes/interactive-engine/extension-ui-bridge.js +126 -0
  720. package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -0
  721. package/dist/modes/interactive-engine/input-form-host.d.ts +15 -0
  722. package/dist/modes/interactive-engine/input-form-host.d.ts.map +1 -0
  723. package/dist/modes/interactive-engine/input-form-host.js +44 -0
  724. package/dist/modes/interactive-engine/input-form-host.js.map +1 -0
  725. package/dist/modes/interactive-engine/isolated-runtime.d.ts +75 -0
  726. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -0
  727. package/dist/modes/interactive-engine/isolated-runtime.js +448 -0
  728. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -0
  729. package/dist/modes/interactive-engine/protocol.d.ts +184 -0
  730. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -0
  731. package/dist/modes/interactive-engine/protocol.js +254 -0
  732. package/dist/modes/interactive-engine/protocol.js.map +1 -0
  733. package/dist/modes/interactive-engine/remote-command-catalog.d.ts +33 -0
  734. package/dist/modes/interactive-engine/remote-command-catalog.d.ts.map +1 -0
  735. package/dist/modes/interactive-engine/remote-command-catalog.js +51 -0
  736. package/dist/modes/interactive-engine/remote-command-catalog.js.map +1 -0
  737. package/dist/modes/interactive-engine/remote-component.d.ts +16 -0
  738. package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -0
  739. package/dist/modes/interactive-engine/remote-component.js +209 -0
  740. package/dist/modes/interactive-engine/remote-component.js.map +1 -0
  741. package/dist/modes/interactive-engine/remote-frame-clamp.d.ts +25 -0
  742. package/dist/modes/interactive-engine/remote-frame-clamp.d.ts.map +1 -0
  743. package/dist/modes/interactive-engine/remote-frame-clamp.js +43 -0
  744. package/dist/modes/interactive-engine/remote-frame-clamp.js.map +1 -0
  745. package/dist/modes/interactive-engine/remote-renderer.d.ts +59 -0
  746. package/dist/modes/interactive-engine/remote-renderer.d.ts.map +1 -0
  747. package/dist/modes/interactive-engine/remote-renderer.js +123 -0
  748. package/dist/modes/interactive-engine/remote-renderer.js.map +1 -0
  749. package/dist/modes/interactive-engine/session-picker-host.d.ts +25 -0
  750. package/dist/modes/interactive-engine/session-picker-host.d.ts.map +1 -0
  751. package/dist/modes/interactive-engine/session-picker-host.js +75 -0
  752. package/dist/modes/interactive-engine/session-picker-host.js.map +1 -0
  753. package/dist/modes/interactive-engine/terminal-mode-controller.d.ts +43 -0
  754. package/dist/modes/interactive-engine/terminal-mode-controller.d.ts.map +1 -0
  755. package/dist/modes/interactive-engine/terminal-mode-controller.js +109 -0
  756. package/dist/modes/interactive-engine/terminal-mode-controller.js.map +1 -0
  757. package/dist/modes/rpc/bounded-writer.d.ts +27 -0
  758. package/dist/modes/rpc/bounded-writer.d.ts.map +1 -0
  759. package/dist/modes/rpc/bounded-writer.js +103 -0
  760. package/dist/modes/rpc/bounded-writer.js.map +1 -0
  761. package/dist/modes/rpc/jsonl.d.ts +15 -12
  762. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  763. package/dist/modes/rpc/jsonl.js +102 -28
  764. package/dist/modes/rpc/jsonl.js.map +1 -1
  765. package/dist/modes/rpc/rpc-client-api.d.ts +83 -0
  766. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -0
  767. package/dist/modes/rpc/rpc-client-api.js +64 -0
  768. package/dist/modes/rpc/rpc-client-api.js.map +1 -0
  769. package/dist/modes/rpc/rpc-client-process.d.ts +19 -0
  770. package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -0
  771. package/dist/modes/rpc/rpc-client-process.js +79 -0
  772. package/dist/modes/rpc/rpc-client-process.js.map +1 -0
  773. package/dist/modes/rpc/rpc-client-waits.d.ts +8 -0
  774. package/dist/modes/rpc/rpc-client-waits.d.ts.map +1 -0
  775. package/dist/modes/rpc/rpc-client-waits.js +33 -0
  776. package/dist/modes/rpc/rpc-client-waits.js.map +1 -0
  777. package/dist/modes/rpc/rpc-client.d.ts +48 -124
  778. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  779. package/dist/modes/rpc/rpc-client.js +295 -249
  780. package/dist/modes/rpc/rpc-client.js.map +1 -1
  781. package/dist/modes/rpc/rpc-command-handler.d.ts +5 -1
  782. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  783. package/dist/modes/rpc/rpc-command-handler.js +79 -3
  784. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  785. package/dist/modes/rpc/rpc-event-buffer.d.ts +11 -0
  786. package/dist/modes/rpc/rpc-event-buffer.d.ts.map +1 -0
  787. package/dist/modes/rpc/rpc-event-buffer.js +30 -0
  788. package/dist/modes/rpc/rpc-event-buffer.js.map +1 -0
  789. package/dist/modes/rpc/rpc-extension-ui.d.ts +7 -1
  790. package/dist/modes/rpc/rpc-extension-ui.d.ts.map +1 -1
  791. package/dist/modes/rpc/rpc-extension-ui.js +54 -32
  792. package/dist/modes/rpc/rpc-extension-ui.js.map +1 -1
  793. package/dist/modes/rpc/rpc-input-scheduler.d.ts +16 -0
  794. package/dist/modes/rpc/rpc-input-scheduler.d.ts.map +1 -0
  795. package/dist/modes/rpc/rpc-input-scheduler.js +69 -0
  796. package/dist/modes/rpc/rpc-input-scheduler.js.map +1 -0
  797. package/dist/modes/rpc/rpc-input.d.ts +2 -1
  798. package/dist/modes/rpc/rpc-input.d.ts.map +1 -1
  799. package/dist/modes/rpc/rpc-input.js +4 -9
  800. package/dist/modes/rpc/rpc-input.js.map +1 -1
  801. package/dist/modes/rpc/rpc-keybindings-reload.d.ts +27 -0
  802. package/dist/modes/rpc/rpc-keybindings-reload.d.ts.map +1 -0
  803. package/dist/modes/rpc/rpc-keybindings-reload.js +69 -0
  804. package/dist/modes/rpc/rpc-keybindings-reload.js.map +1 -0
  805. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  806. package/dist/modes/rpc/rpc-mode.js +63 -8
  807. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  808. package/dist/modes/rpc/rpc-output-buffer.d.ts +10 -0
  809. package/dist/modes/rpc/rpc-output-buffer.d.ts.map +1 -0
  810. package/dist/modes/rpc/rpc-output-buffer.js +70 -0
  811. package/dist/modes/rpc/rpc-output-buffer.js.map +1 -0
  812. package/dist/modes/rpc/rpc-session-binding.d.ts +16 -1
  813. package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
  814. package/dist/modes/rpc/rpc-session-binding.js +16 -3
  815. package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
  816. package/dist/modes/rpc/rpc-types.d.ts +109 -0
  817. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  818. package/dist/modes/rpc/rpc-types.js.map +1 -1
  819. package/dist/package-manager-cli-parser.d.ts +2 -0
  820. package/dist/package-manager-cli-parser.d.ts.map +1 -1
  821. package/dist/package-manager-cli-parser.js +24 -5
  822. package/dist/package-manager-cli-parser.js.map +1 -1
  823. package/dist/package-manager-cli.d.ts +7 -0
  824. package/dist/package-manager-cli.d.ts.map +1 -1
  825. package/dist/package-manager-cli.js +65 -1
  826. package/dist/package-manager-cli.js.map +1 -1
  827. package/dist/utils/shell.d.ts +1 -0
  828. package/dist/utils/shell.d.ts.map +1 -1
  829. package/dist/utils/shell.js +46 -0
  830. package/dist/utils/shell.js.map +1 -1
  831. package/docs/changelog.mdx +11 -0
  832. package/docs/compaction.md +53 -17
  833. package/docs/custom-provider.md +24 -5
  834. package/docs/development.md +9 -7
  835. package/docs/docs.json +1 -0
  836. package/docs/extensions.md +30 -16
  837. package/docs/intercom.md +489 -0
  838. package/docs/json.md +1 -1
  839. package/docs/keybindings.md +1 -1
  840. package/docs/packages.md +1 -0
  841. package/docs/quickstart.md +11 -5
  842. package/docs/rpc.md +9 -7
  843. package/docs/sdk.md +6 -0
  844. package/docs/session-format.md +7 -6
  845. package/docs/sessions.md +4 -2
  846. package/docs/settings.md +2 -2
  847. package/docs/subagents.md +7 -2
  848. package/docs/tui.md +61 -2
  849. package/docs/usage.md +6 -5
  850. package/docs/workflows.md +2572 -1379
  851. package/examples/extensions/handoff.ts +1 -1
  852. package/examples/extensions/qna.ts +1 -1
  853. package/examples/extensions/summarize.ts +1 -1
  854. package/npm-shrinkwrap.json +225 -76
  855. package/package.json +7 -6
  856. package/dist/builtin/workflows/src/durable/file-backend.ts +0 -439
  857. package/dist/builtin/workflows/src/durable/file-lock.ts +0 -153
  858. package/dist/builtin/workflows/src/durable/file-state.ts +0 -104
  859. package/dist/builtin/workflows/src/extension/runtime-direct.ts +0 -96
  860. package/dist/builtin/workflows/src/extension/workflow-tool-helpers.ts +0 -66
  861. package/dist/builtin/workflows/src/runs/foreground/executor-direct-output.ts +0 -91
  862. package/dist/builtin/workflows/src/runs/foreground/executor-direct.ts +0 -282
  863. package/dist/builtin/workflows/src/shared/resumable-workflow-notices.ts +0 -43
  864. package/dist/builtin/workflows/src/tui/session-confirm.ts +0 -299
@@ -1 +1 @@
1
- {"version":3,"file":"branch-summarization.js","sourceRoot":"","sources":["../../../src/core/compaction/branch-summarization.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Branch summarization for tree navigation.\n *\n * When navigating to a different point in the session tree, this generates\n * a summary of the branch being left so context isn't lost.\n */\n\nimport type { AgentMessage, StreamFn } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Model, SimpleStreamOptions } from \"@earendil-works/pi-ai/compat\";\nimport { completeSimple } from \"@earendil-works/pi-ai/compat\";\nimport { formatCopilotProviderError } from \"../copilot-errors.ts\";\nimport { convertToLlm, createBranchSummaryMessage, createCustomMessage } from \"../messages.ts\";\nimport type { ReadonlySessionManager, SessionEntry } from \"../session-manager.ts\";\nimport { estimateTokens } from \"./compaction.ts\";\nimport {\n\tcomputeFileLists,\n\tcreateFileOps,\n\textractFileOpsFromMessage,\n\ttype FileOperations,\n\tformatFileOperations,\n\tSUMMARIZATION_SYSTEM_PROMPT,\n\tserializeConversation,\n} from \"./utils.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface BranchSummaryResult {\n\tsummary?: string;\n\treadFiles?: string[];\n\tmodifiedFiles?: string[];\n\taborted?: boolean;\n\terror?: string;\n}\n\n/** Details stored in BranchSummaryEntry.details for file tracking */\nexport interface BranchSummaryDetails {\n\treadFiles: string[];\n\tmodifiedFiles: string[];\n}\n\nexport type { FileOperations } from \"./utils.ts\";\n\nexport interface BranchPreparation {\n\t/** Messages extracted for summarization, in chronological order */\n\tmessages: AgentMessage[];\n\t/** File operations extracted from tool calls */\n\tfileOps: FileOperations;\n\t/** Total estimated tokens in messages */\n\ttotalTokens: number;\n}\n\nexport interface CollectEntriesResult {\n\t/** Entries to summarize, in chronological order */\n\tentries: SessionEntry[];\n\t/** Common ancestor between old and new position, if any */\n\tcommonAncestorId: string | null;\n}\n\nexport interface GenerateBranchSummaryOptions {\n\t/** Model to use for summarization */\n\tmodel: Model<Api>;\n\t/** API key for the model */\n\tapiKey: string;\n\t/** Request headers for the model */\n\theaders?: Record<string, string>;\n\t/** Abort signal for cancellation */\n\tsignal: AbortSignal;\n\t/** Optional custom instructions for summarization */\n\tcustomInstructions?: string;\n\t/** If true, customInstructions replaces the default prompt instead of being appended */\n\treplaceInstructions?: boolean;\n\t/** Tokens reserved for prompt + LLM response (default 16384) */\n\treserveTokens?: number;\n\t/** Optional session stream function. Used to preserve SDK request behavior without mutating agent state. */\n\tstreamFn?: StreamFn;\n}\n\n// ============================================================================\n// Entry Collection\n// ============================================================================\n\n/**\n * Collect entries that should be summarized when navigating from one position to another.\n *\n * Walks from oldLeafId back to the common ancestor with targetId, collecting entries\n * along the way. Does NOT stop at legacy compaction entries, but those entries are\n * inert and are not fed into branch summarization prompts.\n *\n * @param session - Session manager (read-only access)\n * @param oldLeafId - Current position (where we're navigating from)\n * @param targetId - Target position (where we're navigating to)\n * @returns Entries to summarize and the common ancestor\n */\nexport function collectEntriesForBranchSummary(\n\tsession: ReadonlySessionManager,\n\toldLeafId: string | null,\n\ttargetId: string,\n): CollectEntriesResult {\n\t// If no old position, nothing to summarize\n\tif (!oldLeafId) {\n\t\treturn { entries: [], commonAncestorId: null };\n\t}\n\n\t// Find common ancestor (deepest node that's on both paths)\n\tconst oldPath = new Set(session.getBranch(oldLeafId).map((e) => e.id));\n\tconst targetPath = session.getBranch(targetId);\n\n\t// targetPath is root-first, so iterate backwards to find deepest common ancestor\n\tlet commonAncestorId: string | null = null;\n\tfor (let i = targetPath.length - 1; i >= 0; i--) {\n\t\tif (oldPath.has(targetPath[i].id)) {\n\t\t\tcommonAncestorId = targetPath[i].id;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Collect entries from old leaf back to common ancestor\n\tconst entries: SessionEntry[] = [];\n\tlet current: string | null = oldLeafId;\n\n\twhile (current && current !== commonAncestorId) {\n\t\tconst entry = session.getEntry(current);\n\t\tif (!entry) break;\n\t\tentries.push(entry);\n\t\tcurrent = entry.parentId;\n\t}\n\n\t// Reverse to get chronological order\n\tentries.reverse();\n\n\treturn { entries, commonAncestorId };\n}\n\n// ============================================================================\n// Entry to Message Conversion\n// ============================================================================\n\n/**\n * Extract AgentMessage from a session entry.\n * Similar to getMessageFromEntry in compaction.ts, with legacy compaction entries kept inert.\n */\nfunction getMessageFromEntry(entry: SessionEntry): AgentMessage | undefined {\n\tswitch (entry.type) {\n\t\tcase \"message\":\n\t\t\t// Skip tool results - context is in assistant's tool call\n\t\t\tif (entry.message.role === \"toolResult\") return undefined;\n\t\t\treturn entry.message;\n\n\t\tcase \"custom_message\":\n\t\t\treturn createCustomMessage(\n\t\t\t\tentry.customType,\n\t\t\t\tentry.content,\n\t\t\t\tentry.display,\n\t\t\t\tentry.details,\n\t\t\t\tentry.timestamp,\n\t\t\t\tentry.excludeFromContext,\n\t\t\t);\n\n\t\tcase \"branch_summary\":\n\t\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\n\t\tcase \"compaction\":\n\t\t\treturn undefined;\n\n\t\t// These don't contribute to conversation content\n\t\tcase \"thinking_level_change\":\n\t\tcase \"context_window_change\":\n\t\tcase \"model_change\":\n\t\tcase \"custom\":\n\t\tcase \"label\":\n\t\tcase \"session_info\":\n\t\tcase \"context_compaction\":\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Prepare entries for summarization with token budget.\n *\n * Walks entries from NEWEST to OLDEST, adding messages until we hit the token budget.\n * This ensures we keep the most recent context when the branch is too long.\n *\n * Also collects file operations from:\n * - Tool calls in assistant messages\n * - Existing branch_summary entries' details (for cumulative tracking)\n *\n * @param entries - Entries in chronological order\n * @param tokenBudget - Maximum tokens to include (0 = no limit)\n */\nexport function prepareBranchEntries(entries: SessionEntry[], tokenBudget: number = 0): BranchPreparation {\n\tconst messages: AgentMessage[] = [];\n\tconst fileOps = createFileOps();\n\tconst filteredEntries = entries;\n\tlet totalTokens = 0;\n\n\t// First pass: collect file ops from ALL entries (even if they don't fit in token budget)\n\t// This ensures we capture cumulative file tracking from nested branch summaries\n\t// Only extract from pi-generated summaries (fromHook !== true), not extension-generated ones\n\tfor (const entry of filteredEntries) {\n\t\tif (entry.type === \"branch_summary\" && !entry.fromHook && entry.details) {\n\t\t\tconst details = entry.details as BranchSummaryDetails;\n\t\t\tif (Array.isArray(details.readFiles)) {\n\t\t\t\tfor (const f of details.readFiles) fileOps.read.add(f);\n\t\t\t}\n\t\t\tif (Array.isArray(details.modifiedFiles)) {\n\t\t\t\t// Modified files go into both edited and written for proper deduplication\n\t\t\t\tfor (const f of details.modifiedFiles) {\n\t\t\t\t\tfileOps.edited.add(f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Second pass: walk from newest to oldest, adding messages until token budget\n\tfor (let i = filteredEntries.length - 1; i >= 0; i--) {\n\t\tconst entry = filteredEntries[i];\n\t\tconst message = getMessageFromEntry(entry);\n\t\tif (!message) continue;\n\n\t\t// Extract file ops from assistant messages (tool calls)\n\t\textractFileOpsFromMessage(message, fileOps);\n\n\t\tconst tokens = estimateTokens(message);\n\n\t\t// Check budget before adding\n\t\tif (tokenBudget > 0 && totalTokens + tokens > tokenBudget) {\n\t\t\t// If this is a branch summary entry, try to fit it anyway as it's important context\n\t\t\tif (entry.type === \"branch_summary\") {\n\t\t\t\tif (totalTokens < tokenBudget * 0.9) {\n\t\t\t\t\tmessages.unshift(message);\n\t\t\t\t\ttotalTokens += tokens;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Stop - we've hit the budget\n\t\t\tbreak;\n\t\t}\n\n\t\tmessages.unshift(message);\n\t\ttotalTokens += tokens;\n\t}\n\n\treturn { messages, fileOps, totalTokens };\n}\n\n// ============================================================================\n// Summary Generation\n// ============================================================================\n\nconst BRANCH_SUMMARY_PREAMBLE = `The user explored a different conversation branch before returning here.\nSummary of that exploration:\n\n`;\n\nconst BRANCH_SUMMARY_PROMPT = `Create a structured summary of this conversation branch for context when returning later.\n\nUse this EXACT format:\n\n## Goal\n[What was the user trying to accomplish in this branch?]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Work that was started but not finished]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Next Steps\n1. [What should happen next to continue this work]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\n/**\n * Generate a summary of abandoned branch entries.\n *\n * @param entries - Session entries to summarize (chronological order)\n * @param options - Generation options\n */\nexport async function generateBranchSummary(\n\tentries: SessionEntry[],\n\toptions: GenerateBranchSummaryOptions,\n): Promise<BranchSummaryResult> {\n\tconst {\n\t\tmodel,\n\t\tapiKey,\n\t\theaders,\n\t\tsignal,\n\t\tcustomInstructions,\n\t\treplaceInstructions,\n\t\treserveTokens = 16384,\n\t\tstreamFn,\n\t} = options;\n\n\t// Token budget = context window minus reserved space for prompt + response\n\tconst contextWindow = model.contextWindow || 128000;\n\tconst tokenBudget = contextWindow - reserveTokens;\n\n\tconst { messages, fileOps } = prepareBranchEntries(entries, tokenBudget);\n\n\tif (messages.length === 0) {\n\t\treturn { summary: \"No content to summarize\" };\n\t}\n\n\t// Transform to LLM-compatible messages, then serialize to text\n\t// Serialization prevents the model from treating it as a conversation to continue\n\tconst llmMessages = convertToLlm(messages);\n\tconst conversationText = serializeConversation(llmMessages);\n\n\t// Build prompt\n\tlet instructions: string;\n\tif (replaceInstructions && customInstructions) {\n\t\tinstructions = customInstructions;\n\t} else if (customInstructions) {\n\t\tinstructions = `${BRANCH_SUMMARY_PROMPT}\\n\\nAdditional focus: ${customInstructions}`;\n\t} else {\n\t\tinstructions = BRANCH_SUMMARY_PROMPT;\n\t}\n\tconst promptText = `<conversation>\\n${conversationText}\\n</conversation>\\n\\n${instructions}`;\n\n\tconst summarizationMessages = [\n\t\t{\n\t\t\trole: \"user\" as const,\n\t\t\tcontent: [{ type: \"text\" as const, text: promptText }],\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t];\n\n\t// Call LLM for summarization. Prefer the session stream function so SDK\n\t// request behavior (timeouts, retries, attribution headers) stays consistent\n\t// without running through agent state/events.\n\tconst context = { systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages };\n\tconst requestOptions: SimpleStreamOptions = { apiKey, headers, signal, maxTokens: 2048 };\n\tconst response = await (async () => {\n\t\ttry {\n\t\t\treturn streamFn\n\t\t\t\t? await (await streamFn(model, context, requestOptions)).result()\n\t\t\t\t: await completeSimple(model, context, requestOptions);\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstopReason: \"error\" as const,\n\t\t\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t})();\n\n\t// Check if aborted or errored\n\tif (!response || response.stopReason === \"aborted\") {\n\t\treturn { aborted: true };\n\t}\n\tif (response.stopReason === \"error\") {\n\t\treturn { error: formatCopilotProviderError(model.provider, response.errorMessage || \"Summarization failed\") };\n\t}\n\n\tlet summary = response.content\n\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t.map((c) => c.text)\n\t\t.join(\"\\n\");\n\n\t// Prepend preamble to provide context about the branch summary\n\tsummary = BRANCH_SUMMARY_PREAMBLE + summary;\n\n\t// Compute file lists and append to summary\n\tconst { readFiles, modifiedFiles } = computeFileLists(fileOps);\n\tsummary += formatFileOperations(readFiles, modifiedFiles);\n\n\treturn {\n\t\tsummary: summary || \"No summary generated\",\n\t\treadFiles,\n\t\tmodifiedFiles,\n\t};\n}\n"]}
1
+ {"version":3,"file":"branch-summarization.js","sourceRoot":"","sources":["../../../src/core/compaction/branch-summarization.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Branch summarization for tree navigation.\n *\n * When navigating to a different point in the session tree, this generates\n * a summary of the branch being left so context isn't lost.\n */\n\nimport type { AgentMessage, StreamFn } from \"@earendil-works/pi-agent-core\";\nimport type { ProviderHeaders } from \"@earendil-works/pi-ai\";\nimport type { Api, Model, SimpleStreamOptions } from \"@earendil-works/pi-ai/compat\";\nimport { completeSimple } from \"@earendil-works/pi-ai/compat\";\nimport { formatCopilotProviderError } from \"../copilot-errors.ts\";\nimport { convertToLlm, createBranchSummaryMessage, createCustomMessage } from \"../messages.ts\";\nimport type { ReadonlySessionManager, SessionEntry } from \"../session-manager.ts\";\nimport { estimateTokens } from \"./compaction.ts\";\nimport {\n\tcomputeFileLists,\n\tcreateFileOps,\n\textractFileOpsFromMessage,\n\ttype FileOperations,\n\tformatFileOperations,\n\tSUMMARIZATION_SYSTEM_PROMPT,\n\tserializeConversation,\n} from \"./utils.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface BranchSummaryResult {\n\tsummary?: string;\n\treadFiles?: string[];\n\tmodifiedFiles?: string[];\n\taborted?: boolean;\n\terror?: string;\n}\n\n/** Details stored in BranchSummaryEntry.details for file tracking */\nexport interface BranchSummaryDetails {\n\treadFiles: string[];\n\tmodifiedFiles: string[];\n}\n\nexport type { FileOperations } from \"./utils.ts\";\n\nexport interface BranchPreparation {\n\t/** Messages extracted for summarization, in chronological order */\n\tmessages: AgentMessage[];\n\t/** File operations extracted from tool calls */\n\tfileOps: FileOperations;\n\t/** Total estimated tokens in messages */\n\ttotalTokens: number;\n}\n\nexport interface CollectEntriesResult {\n\t/** Entries to summarize, in chronological order */\n\tentries: SessionEntry[];\n\t/** Common ancestor between old and new position, if any */\n\tcommonAncestorId: string | null;\n}\n\nexport interface GenerateBranchSummaryOptions {\n\t/** Model to use for summarization */\n\tmodel: Model<Api>;\n\t/** API key for the model */\n\tapiKey: string;\n\t/** Request headers for the model */\n\theaders?: ProviderHeaders;\n\t/** Credential-specific request endpoint for the model */\n\tbaseUrl?: string;\n\t/** Abort signal for cancellation */\n\tsignal: AbortSignal;\n\t/** Optional custom instructions for summarization */\n\tcustomInstructions?: string;\n\t/** If true, customInstructions replaces the default prompt instead of being appended */\n\treplaceInstructions?: boolean;\n\t/** Tokens reserved for prompt + LLM response (default 16384) */\n\treserveTokens?: number;\n\t/** Optional session stream function. Used to preserve SDK request behavior without mutating agent state. */\n\tstreamFn?: StreamFn;\n}\n\n// ============================================================================\n// Entry Collection\n// ============================================================================\n\n/**\n * Collect entries that should be summarized when navigating from one position to another.\n *\n * Walks from oldLeafId back to the common ancestor with targetId, collecting entries\n * along the way. Does NOT stop at legacy compaction entries, but those entries are\n * inert and are not fed into branch summarization prompts.\n *\n * @param session - Session manager (read-only access)\n * @param oldLeafId - Current position (where we're navigating from)\n * @param targetId - Target position (where we're navigating to)\n * @returns Entries to summarize and the common ancestor\n */\nexport function collectEntriesForBranchSummary(\n\tsession: ReadonlySessionManager,\n\toldLeafId: string | null,\n\ttargetId: string,\n): CollectEntriesResult {\n\t// If no old position, nothing to summarize\n\tif (!oldLeafId) {\n\t\treturn { entries: [], commonAncestorId: null };\n\t}\n\n\t// Find common ancestor (deepest node that's on both paths)\n\tconst oldPath = new Set(session.getBranch(oldLeafId).map((e) => e.id));\n\tconst targetPath = session.getBranch(targetId);\n\n\t// targetPath is root-first, so iterate backwards to find deepest common ancestor\n\tlet commonAncestorId: string | null = null;\n\tfor (let i = targetPath.length - 1; i >= 0; i--) {\n\t\tif (oldPath.has(targetPath[i].id)) {\n\t\t\tcommonAncestorId = targetPath[i].id;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Collect entries from old leaf back to common ancestor\n\tconst entries: SessionEntry[] = [];\n\tlet current: string | null = oldLeafId;\n\n\twhile (current && current !== commonAncestorId) {\n\t\tconst entry = session.getEntry(current);\n\t\tif (!entry) break;\n\t\tentries.push(entry);\n\t\tcurrent = entry.parentId;\n\t}\n\n\t// Reverse to get chronological order\n\tentries.reverse();\n\n\treturn { entries, commonAncestorId };\n}\n\n// ============================================================================\n// Entry to Message Conversion\n// ============================================================================\n\n/**\n * Extract AgentMessage from a session entry.\n * Similar to getMessageFromEntry in compaction.ts, with legacy compaction entries kept inert.\n */\nfunction getMessageFromEntry(entry: SessionEntry): AgentMessage | undefined {\n\tswitch (entry.type) {\n\t\tcase \"message\":\n\t\t\t// Skip tool results - context is in assistant's tool call\n\t\t\tif (entry.message.role === \"toolResult\") return undefined;\n\t\t\treturn entry.message;\n\n\t\tcase \"custom_message\":\n\t\t\treturn createCustomMessage(\n\t\t\t\tentry.customType,\n\t\t\t\tentry.content,\n\t\t\t\tentry.display,\n\t\t\t\tentry.details,\n\t\t\t\tentry.timestamp,\n\t\t\t\tentry.excludeFromContext,\n\t\t\t);\n\n\t\tcase \"branch_summary\":\n\t\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\n\t\tcase \"compaction\":\n\t\t\treturn undefined;\n\n\t\t// These don't contribute to conversation content\n\t\tcase \"thinking_level_change\":\n\t\tcase \"context_window_change\":\n\t\tcase \"model_change\":\n\t\tcase \"custom\":\n\t\tcase \"label\":\n\t\tcase \"session_info\":\n\t\tcase \"context_compaction\":\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Prepare entries for summarization with token budget.\n *\n * Walks entries from NEWEST to OLDEST, adding messages until we hit the token budget.\n * This ensures we keep the most recent context when the branch is too long.\n *\n * Also collects file operations from:\n * - Tool calls in assistant messages\n * - Existing branch_summary entries' details (for cumulative tracking)\n *\n * @param entries - Entries in chronological order\n * @param tokenBudget - Maximum tokens to include (0 = no limit)\n */\nexport function prepareBranchEntries(entries: SessionEntry[], tokenBudget: number = 0): BranchPreparation {\n\tconst messages: AgentMessage[] = [];\n\tconst fileOps = createFileOps();\n\tconst filteredEntries = entries;\n\tlet totalTokens = 0;\n\n\t// First pass: collect file ops from ALL entries (even if they don't fit in token budget)\n\t// This ensures we capture cumulative file tracking from nested branch summaries\n\t// Only extract from pi-generated summaries (fromHook !== true), not extension-generated ones\n\tfor (const entry of filteredEntries) {\n\t\tif (entry.type === \"branch_summary\" && !entry.fromHook && entry.details) {\n\t\t\tconst details = entry.details as BranchSummaryDetails;\n\t\t\tif (Array.isArray(details.readFiles)) {\n\t\t\t\tfor (const f of details.readFiles) fileOps.read.add(f);\n\t\t\t}\n\t\t\tif (Array.isArray(details.modifiedFiles)) {\n\t\t\t\t// Modified files go into both edited and written for proper deduplication\n\t\t\t\tfor (const f of details.modifiedFiles) {\n\t\t\t\t\tfileOps.edited.add(f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Second pass: walk from newest to oldest, adding messages until token budget\n\tfor (let i = filteredEntries.length - 1; i >= 0; i--) {\n\t\tconst entry = filteredEntries[i];\n\t\tconst message = getMessageFromEntry(entry);\n\t\tif (!message) continue;\n\n\t\t// Extract file ops from assistant messages (tool calls)\n\t\textractFileOpsFromMessage(message, fileOps);\n\n\t\tconst tokens = estimateTokens(message);\n\n\t\t// Check budget before adding\n\t\tif (tokenBudget > 0 && totalTokens + tokens > tokenBudget) {\n\t\t\t// If this is a branch summary entry, try to fit it anyway as it's important context\n\t\t\tif (entry.type === \"branch_summary\") {\n\t\t\t\tif (totalTokens < tokenBudget * 0.9) {\n\t\t\t\t\tmessages.unshift(message);\n\t\t\t\t\ttotalTokens += tokens;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Stop - we've hit the budget\n\t\t\tbreak;\n\t\t}\n\n\t\tmessages.unshift(message);\n\t\ttotalTokens += tokens;\n\t}\n\n\treturn { messages, fileOps, totalTokens };\n}\n\n// ============================================================================\n// Summary Generation\n// ============================================================================\n\nconst BRANCH_SUMMARY_PREAMBLE = `The user explored a different conversation branch before returning here.\nSummary of that exploration:\n\n`;\n\nconst BRANCH_SUMMARY_PROMPT = `Create a structured summary of this conversation branch for context when returning later.\n\nUse this EXACT format:\n\n## Goal\n[What was the user trying to accomplish in this branch?]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Work that was started but not finished]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Next Steps\n1. [What should happen next to continue this work]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\n/**\n * Generate a summary of abandoned branch entries.\n *\n * @param entries - Session entries to summarize (chronological order)\n * @param options - Generation options\n */\nexport async function generateBranchSummary(\n\tentries: SessionEntry[],\n\toptions: GenerateBranchSummaryOptions,\n): Promise<BranchSummaryResult> {\n\tconst {\n\t\tmodel,\n\t\tapiKey,\n\t\theaders,\n\t\tbaseUrl,\n\t\tsignal,\n\t\tcustomInstructions,\n\t\treplaceInstructions,\n\t\treserveTokens = 16384,\n\t\tstreamFn,\n\t} = options;\n\n\t// Token budget = context window minus reserved space for prompt + response\n\tconst contextWindow = model.contextWindow || 128000;\n\tconst tokenBudget = contextWindow - reserveTokens;\n\n\tconst { messages, fileOps } = prepareBranchEntries(entries, tokenBudget);\n\n\tif (messages.length === 0) {\n\t\treturn { summary: \"No content to summarize\" };\n\t}\n\n\t// Transform to LLM-compatible messages, then serialize to text\n\t// Serialization prevents the model from treating it as a conversation to continue\n\tconst llmMessages = convertToLlm(messages);\n\tconst conversationText = serializeConversation(llmMessages);\n\n\t// Build prompt\n\tlet instructions: string;\n\tif (replaceInstructions && customInstructions) {\n\t\tinstructions = customInstructions;\n\t} else if (customInstructions) {\n\t\tinstructions = `${BRANCH_SUMMARY_PROMPT}\\n\\nAdditional focus: ${customInstructions}`;\n\t} else {\n\t\tinstructions = BRANCH_SUMMARY_PROMPT;\n\t}\n\tconst promptText = `<conversation>\\n${conversationText}\\n</conversation>\\n\\n${instructions}`;\n\n\tconst summarizationMessages = [\n\t\t{\n\t\t\trole: \"user\" as const,\n\t\t\tcontent: [{ type: \"text\" as const, text: promptText }],\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t];\n\n\t// Call LLM for summarization. Prefer the session stream function so SDK\n\t// request behavior (timeouts, retries, attribution headers) stays consistent\n\t// without running through agent state/events.\n\tconst context = { systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages };\n\tconst requestOptions: SimpleStreamOptions = { apiKey, headers, signal, maxTokens: 2048 };\n\tconst requestModel = baseUrl === undefined || baseUrl === model.baseUrl ? model : { ...model, baseUrl };\n\tconst response = await (async () => {\n\t\ttry {\n\t\t\treturn streamFn\n\t\t\t\t? await (await streamFn(requestModel, context, requestOptions)).result()\n\t\t\t\t: await completeSimple(requestModel, context, requestOptions);\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstopReason: \"error\" as const,\n\t\t\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t})();\n\n\t// Check if aborted or errored\n\tif (!response || response.stopReason === \"aborted\") {\n\t\treturn { aborted: true };\n\t}\n\tif (response.stopReason === \"error\") {\n\t\treturn { error: formatCopilotProviderError(model.provider, response.errorMessage || \"Summarization failed\") };\n\t}\n\n\tlet summary = response.content\n\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t.map((c) => c.text)\n\t\t.join(\"\\n\");\n\n\t// Prepend preamble to provide context about the branch summary\n\tsummary = BRANCH_SUMMARY_PREAMBLE + summary;\n\n\t// Compute file lists and append to summary\n\tconst { readFiles, modifiedFiles } = computeFileLists(fileOps);\n\tsummary += formatFileOperations(readFiles, modifiedFiles);\n\n\treturn {\n\t\tsummary: summary || \"No summary generated\",\n\t\treadFiles,\n\t\tmodifiedFiles,\n\t};\n}\n"]}
@@ -4,6 +4,6 @@ import { type VerbatimCompactionParameters, type VerbatimCompactionPreparation }
4
4
  /** Return the independently estimated cost of the protected tail. */
5
5
  export declare function getKeptTailTokenEstimate(preparation: VerbatimCompactionPreparation): number;
6
6
  export declare function autoDetectCompactionQuery(entries: readonly SessionEntry[]): string;
7
- /** Prepare a compactable region and a structurally valid, user-turn-aligned tail. */
7
+ /** Prepare the complete compactable transcript and its exact context-visible message tail. */
8
8
  export declare function prepareCompactionBoundary(pathEntries: SessionEntry[], settings: CompactionSettings, options?: Partial<VerbatimCompactionParameters>): VerbatimCompactionPreparation | undefined;
9
9
  //# sourceMappingURL=compaction-boundary.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compaction-boundary.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction-boundary.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAyC,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEjG,OAAO,EAIN,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,MAAM,uBAAuB,CAAC;AAW/B,qEAAqE;AACrE,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,6BAA6B,GAAG,MAAM,CAG3F;AAqCD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CASlF;AAoBD,qFAAqF;AACrF,wBAAgB,yBAAyB,CACxC,WAAW,EAAE,YAAY,EAAE,EAC3B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACjD,6BAA6B,GAAG,SAAS,CAiC3C"}
1
+ {"version":3,"file":"compaction-boundary.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction-boundary.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAyC,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEjG,OAAO,EAIN,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,MAAM,uBAAuB,CAAC;AAW/B,qEAAqE;AACrE,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,6BAA6B,GAAG,MAAM,CAG3F;AAqCD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CASlF;AAUD,8FAA8F;AAC9F,wBAAgB,yBAAyB,CACxC,WAAW,EAAE,YAAY,EAAE,EAC3B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACjD,6BAA6B,GAAG,SAAS,CAiC3C"}
@@ -66,42 +66,29 @@ function latestActiveBoundary(entries) {
66
66
  }
67
67
  return undefined;
68
68
  }
69
- function selectCut(visible, preserveRecent) {
70
- if (visible.length === 0)
71
- return undefined;
72
- const candidate = preserveRecent >= visible.length ? 0 : Math.max(0, visible.length - preserveRecent);
73
- const searchStart = preserveRecent === 0 ? visible.length - 1 : candidate;
74
- for (let index = searchStart; index >= 0; index--) {
75
- if (messageStartsLlmUserTurn(visible[index].message))
76
- return visible[index];
77
- }
78
- return undefined;
79
- }
80
- /** Prepare a compactable region and a structurally valid, user-turn-aligned tail. */
69
+ /** Prepare the complete compactable transcript and its exact context-visible message tail. */
81
70
  export function prepareCompactionBoundary(pathEntries, settings, options = {}) {
82
71
  const entries = normalizeDerivedSessionEntries(pathEntries);
83
72
  const previous = latestActiveBoundary(entries);
84
73
  let regionStart = 0;
85
74
  if (previous) {
86
- const keptIndex = entries.findIndex((entry) => entry.id === previous.entry.firstKeptEntryId);
75
+ const keptIndex = previous.entry.firstKeptEntryId === null
76
+ ? -1
77
+ : entries.findIndex((entry) => entry.id === previous.entry.firstKeptEntryId);
87
78
  regionStart = keptIndex >= 0 ? keptIndex : previous.index + 1;
88
79
  }
89
80
  const visible = visibleEntries(entries, regionStart);
90
81
  const parameters = normalizeCompactionParameters({ ...settings, ...options }, autoDetectCompactionQuery(entries));
91
- const cut = selectCut(visible, parameters.preserve_recent);
92
- if (!cut)
93
- return undefined;
94
- const regionMessages = visible.filter((item) => item.index < cut.index);
95
- if (regionMessages.length < 2)
96
- return undefined;
82
+ const tailStart = Math.max(0, visible.length - parameters.preserve_recent);
83
+ const regionMessages = visible.slice(0, tailStart);
84
+ const tailMessages = visible.slice(tailStart);
97
85
  const serialized = serializeConversationForCompaction(convertToLlm(regionMessages.map((item) => item.message)));
98
- const regionText = previous?.entry.summary ? `${previous.entry.summary}\n${serialized}` : serialized;
86
+ const regionText = [previous?.entry.summary, serialized].filter((text) => typeof text === "string" && text.length > 0).join("\n");
99
87
  const region = createNumberedRegion(regionText);
100
88
  if (region.lines.length < MIN_COMPACTABLE_REGION_LINES)
101
89
  return undefined;
102
- const tailMessages = visible.filter((item) => item.index >= cut.index).map((item) => item.message);
103
90
  const preparation = {
104
- firstKeptEntryId: cut.entry.id,
91
+ firstKeptEntryId: tailMessages[0]?.entry.id ?? null,
105
92
  region,
106
93
  regionEntryIds: regionMessages.map((item) => item.entry.id),
107
94
  keptTailMessageCount: tailMessages.length,
@@ -109,7 +96,7 @@ export function prepareCompactionBoundary(pathEntries, settings, options = {}) {
109
96
  parameters,
110
97
  settings,
111
98
  };
112
- keptTailTokensByPreparation.set(preparation, tailMessages.reduce((sum, message) => sum + estimateTokens(message), 0));
99
+ keptTailTokensByPreparation.set(preparation, tailMessages.reduce((sum, item) => sum + estimateTokens(item.message), 0));
113
100
  return preparation;
114
101
  }
115
102
  //# sourceMappingURL=compaction-boundary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compaction-boundary.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction-boundary.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { convertToLlm, createBranchSummaryMessage, createCustomMessage, messageIsLlmVisible, messageStartsLlmUserTurn } from \"../messages.js\";\nimport { normalizeDerivedSessionEntries } from \"../session-entry-normalization.js\";\nimport { buildSessionContext } from \"../session-manager-history.js\";\nimport type { CompactionEntry, SessionEntry } from \"../session-manager-types.js\";\nimport { estimateContextTokens, estimateTokens, type CompactionSettings } from \"./compaction.js\";\nimport { normalizeCompactionParameters, normalizeCompactionQuery, COMPACTION_AUTO_QUERY } from \"./compaction-parameters.js\";\nimport {\n\tMIN_COMPACTABLE_REGION_LINES,\n\tVERBATIM_COMPACTION_STRATEGY,\n\ttype VerbatimCompactionDetails,\n\ttype VerbatimCompactionParameters,\n\ttype VerbatimCompactionPreparation,\n} from \"./compaction-types.js\";\nimport { createNumberedRegion, serializeConversationForCompaction } from \"./transcript-serialization.js\";\n\ninterface VisibleEntry {\n\tentry: SessionEntry;\n\tindex: number;\n\tmessage: AgentMessage;\n}\n\nconst keptTailTokensByPreparation = new WeakMap<VerbatimCompactionPreparation, number>();\n\n/** Return the independently estimated cost of the protected tail. */\nexport function getKeptTailTokenEstimate(preparation: VerbatimCompactionPreparation): number {\n\treturn keptTailTokensByPreparation.get(preparation)\n\t\t?? Math.max(0, preparation.tokensBefore - preparation.region.tokenEstimate);\n}\n\nfunction messageFromEntry(entry: SessionEntry): AgentMessage | undefined {\n\tif (entry.type === \"message\") return entry.message;\n\tif (entry.type === \"custom_message\") {\n\t\treturn createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp, entry.excludeFromContext);\n\t}\n\tif (entry.type === \"branch_summary\" && typeof entry.summary === \"string\") {\n\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\t}\n\treturn undefined;\n}\n\nfunction activeBoundary(entry: SessionEntry): entry is CompactionEntry<VerbatimCompactionDetails> {\n\tif (entry.type !== \"compaction\") return false;\n\tconst details = (entry as CompactionEntry<{ strategy?: string }>).details;\n\treturn details?.strategy === VERBATIM_COMPACTION_STRATEGY;\n}\n\nfunction visibleEntries(entries: SessionEntry[], start = 0): VisibleEntry[] {\n\tconst visible: VisibleEntry[] = [];\n\tfor (let index = start; index < entries.length; index++) {\n\t\tconst entry = entries[index];\n\t\tconst message = messageFromEntry(entry);\n\t\tif (message && messageIsLlmVisible(message)) visible.push({ entry, index, message });\n\t}\n\treturn visible;\n}\n\nfunction messageText(message: AgentMessage): string {\n\tconst converted = convertToLlm([message]);\n\tif (converted.length === 0) return \"\";\n\treturn converted\n\t\t.flatMap((item) => typeof item.content === \"string\" ? [item.content] : item.content.filter((block) => block.type === \"text\").map((block) => block.text))\n\t\t.join(\"\\n\");\n}\n\nexport function autoDetectCompactionQuery(entries: readonly SessionEntry[]): string {\n\tconst normalized = normalizeDerivedSessionEntries(entries);\n\tfor (let index = normalized.length - 1; index >= 0; index--) {\n\t\tconst message = messageFromEntry(normalized[index]);\n\t\tif (!message || !messageStartsLlmUserTurn(message)) continue;\n\t\tconst text = messageText(message).trim();\n\t\tif (text) return normalizeCompactionQuery(text, COMPACTION_AUTO_QUERY);\n\t}\n\treturn COMPACTION_AUTO_QUERY;\n}\n\nfunction latestActiveBoundary(entries: SessionEntry[]): { entry: CompactionEntry<VerbatimCompactionDetails>; index: number } | undefined {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (activeBoundary(entry)) return { entry, index };\n\t}\n\treturn undefined;\n}\n\nfunction selectCut(visible: VisibleEntry[], preserveRecent: number): VisibleEntry | undefined {\n\tif (visible.length === 0) return undefined;\n\tconst candidate = preserveRecent >= visible.length ? 0 : Math.max(0, visible.length - preserveRecent);\n\tconst searchStart = preserveRecent === 0 ? visible.length - 1 : candidate;\n\tfor (let index = searchStart; index >= 0; index--) {\n\t\tif (messageStartsLlmUserTurn(visible[index].message)) return visible[index];\n\t}\n\treturn undefined;\n}\n\n/** Prepare a compactable region and a structurally valid, user-turn-aligned tail. */\nexport function prepareCompactionBoundary(\n\tpathEntries: SessionEntry[],\n\tsettings: CompactionSettings,\n\toptions: Partial<VerbatimCompactionParameters> = {},\n): VerbatimCompactionPreparation | undefined {\n\tconst entries = normalizeDerivedSessionEntries(pathEntries);\n\tconst previous = latestActiveBoundary(entries);\n\tlet regionStart = 0;\n\tif (previous) {\n\t\tconst keptIndex = entries.findIndex((entry) => entry.id === previous.entry.firstKeptEntryId);\n\t\tregionStart = keptIndex >= 0 ? keptIndex : previous.index + 1;\n\t}\n\n\tconst visible = visibleEntries(entries, regionStart);\n\tconst parameters = normalizeCompactionParameters({ ...settings, ...options }, autoDetectCompactionQuery(entries));\n\tconst cut = selectCut(visible, parameters.preserve_recent);\n\tif (!cut) return undefined;\n\tconst regionMessages = visible.filter((item) => item.index < cut.index);\n\tif (regionMessages.length < 2) return undefined;\n\n\tconst serialized = serializeConversationForCompaction(convertToLlm(regionMessages.map((item) => item.message)));\n\tconst regionText = previous?.entry.summary ? `${previous.entry.summary}\\n${serialized}` : serialized;\n\tconst region = createNumberedRegion(regionText);\n\tif (region.lines.length < MIN_COMPACTABLE_REGION_LINES) return undefined;\n\n\tconst tailMessages = visible.filter((item) => item.index >= cut.index).map((item) => item.message);\n\tconst preparation: VerbatimCompactionPreparation = {\n\t\tfirstKeptEntryId: cut.entry.id,\n\t\tregion,\n\t\tregionEntryIds: regionMessages.map((item) => item.entry.id),\n\t\tkeptTailMessageCount: tailMessages.length,\n\t\ttokensBefore: estimateContextTokens(buildSessionContext(entries).messages).tokens,\n\t\tparameters,\n\t\tsettings,\n\t};\n\tkeptTailTokensByPreparation.set(preparation, tailMessages.reduce((sum, message) => sum + estimateTokens(message), 0));\n\treturn preparation;\n}\n"]}
1
+ {"version":3,"file":"compaction-boundary.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction-boundary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC9I,OAAO,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAA2B,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAAE,6BAA6B,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAC5H,OAAO,EACN,4BAA4B,EAC5B,4BAA4B,GAI5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,kCAAkC,EAAE,MAAM,+BAA+B,CAAC;AAQzG,MAAM,2BAA2B,GAAG,IAAI,OAAO,EAAyC,CAAC;AAEzF,qEAAqE;AACrE,MAAM,UAAU,wBAAwB,CAAC,WAA0C;IAClF,OAAO,2BAA2B,CAAC,GAAG,CAAC,WAAW,CAAC;WAC/C,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAmB;IAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACnD,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QACrC,OAAO,mBAAmB,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtI,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC1E,OAAO,0BAA0B,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,KAAmB;IAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,OAAO,GAAI,KAAgD,CAAC,OAAO,CAAC;IAC1E,OAAO,OAAO,EAAE,QAAQ,KAAK,4BAA4B,CAAC;AAC3D,CAAC;AAED,SAAS,cAAc,CAAC,OAAuB,EAAE,KAAK,GAAG,CAAC;IACzD,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,OAAO,IAAI,mBAAmB,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,OAAqB;IACzC,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,OAAO,SAAS;SACd,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SACvJ,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAgC;IACzE,MAAM,UAAU,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAC;IAC3D,KAAK,IAAI,KAAK,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7D,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC;YAAE,SAAS;QAC7D,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACzC,IAAI,IAAI;YAAE,OAAO,wBAAwB,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,qBAAqB,CAAC;AAC9B,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAuB;IACpD,KAAK,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,cAAc,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,yBAAyB,CACxC,WAA2B,EAC3B,QAA4B,EAC5B,OAAO,GAA0C,EAAE;IAEnD,MAAM,OAAO,GAAG,8BAA8B,CAAC,WAAW,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,QAAQ,EAAE,CAAC;QACd,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,gBAAgB,KAAK,IAAI;YACzD,CAAC,CAAC,CAAC,CAAC;YACJ,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC9E,WAAW,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,6BAA6B,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC;IAClH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IAC3E,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAE9C,MAAM,UAAU,GAAG,kCAAkC,CAAC,YAAY,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAChH,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClJ,MAAM,MAAM,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAChD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,4BAA4B;QAAE,OAAO,SAAS,CAAC;IAEzE,MAAM,WAAW,GAAkC;QAClD,gBAAgB,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI;QACnD,MAAM;QACN,cAAc,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,oBAAoB,EAAE,YAAY,CAAC,MAAM;QACzC,YAAY,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM;QACjF,UAAU;QACV,QAAQ;KACR,CAAC;IACF,2BAA2B,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxH,OAAO,WAAW,CAAC;AACpB,CAAC","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { convertToLlm, createBranchSummaryMessage, createCustomMessage, messageIsLlmVisible, messageStartsLlmUserTurn } from \"../messages.js\";\nimport { normalizeDerivedSessionEntries } from \"../session-entry-normalization.js\";\nimport { buildSessionContext } from \"../session-manager-history.js\";\nimport type { CompactionEntry, SessionEntry } from \"../session-manager-types.js\";\nimport { estimateContextTokens, estimateTokens, type CompactionSettings } from \"./compaction.js\";\nimport { normalizeCompactionParameters, normalizeCompactionQuery, COMPACTION_AUTO_QUERY } from \"./compaction-parameters.js\";\nimport {\n\tMIN_COMPACTABLE_REGION_LINES,\n\tVERBATIM_COMPACTION_STRATEGY,\n\ttype VerbatimCompactionDetails,\n\ttype VerbatimCompactionParameters,\n\ttype VerbatimCompactionPreparation,\n} from \"./compaction-types.js\";\nimport { createNumberedRegion, serializeConversationForCompaction } from \"./transcript-serialization.js\";\n\ninterface VisibleEntry {\n\tentry: SessionEntry;\n\tindex: number;\n\tmessage: AgentMessage;\n}\n\nconst keptTailTokensByPreparation = new WeakMap<VerbatimCompactionPreparation, number>();\n\n/** Return the independently estimated cost of the protected tail. */\nexport function getKeptTailTokenEstimate(preparation: VerbatimCompactionPreparation): number {\n\treturn keptTailTokensByPreparation.get(preparation)\n\t\t?? Math.max(0, preparation.tokensBefore - preparation.region.tokenEstimate);\n}\n\nfunction messageFromEntry(entry: SessionEntry): AgentMessage | undefined {\n\tif (entry.type === \"message\") return entry.message;\n\tif (entry.type === \"custom_message\") {\n\t\treturn createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp, entry.excludeFromContext);\n\t}\n\tif (entry.type === \"branch_summary\" && typeof entry.summary === \"string\") {\n\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\t}\n\treturn undefined;\n}\n\nfunction activeBoundary(entry: SessionEntry): entry is CompactionEntry<VerbatimCompactionDetails> {\n\tif (entry.type !== \"compaction\") return false;\n\tconst details = (entry as CompactionEntry<{ strategy?: string }>).details;\n\treturn details?.strategy === VERBATIM_COMPACTION_STRATEGY;\n}\n\nfunction visibleEntries(entries: SessionEntry[], start = 0): VisibleEntry[] {\n\tconst visible: VisibleEntry[] = [];\n\tfor (let index = start; index < entries.length; index++) {\n\t\tconst entry = entries[index];\n\t\tconst message = messageFromEntry(entry);\n\t\tif (message && messageIsLlmVisible(message)) visible.push({ entry, index, message });\n\t}\n\treturn visible;\n}\n\nfunction messageText(message: AgentMessage): string {\n\tconst converted = convertToLlm([message]);\n\tif (converted.length === 0) return \"\";\n\treturn converted\n\t\t.flatMap((item) => typeof item.content === \"string\" ? [item.content] : item.content.filter((block) => block.type === \"text\").map((block) => block.text))\n\t\t.join(\"\\n\");\n}\n\nexport function autoDetectCompactionQuery(entries: readonly SessionEntry[]): string {\n\tconst normalized = normalizeDerivedSessionEntries(entries);\n\tfor (let index = normalized.length - 1; index >= 0; index--) {\n\t\tconst message = messageFromEntry(normalized[index]);\n\t\tif (!message || !messageStartsLlmUserTurn(message)) continue;\n\t\tconst text = messageText(message).trim();\n\t\tif (text) return normalizeCompactionQuery(text, COMPACTION_AUTO_QUERY);\n\t}\n\treturn COMPACTION_AUTO_QUERY;\n}\n\nfunction latestActiveBoundary(entries: SessionEntry[]): { entry: CompactionEntry<VerbatimCompactionDetails>; index: number } | undefined {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (activeBoundary(entry)) return { entry, index };\n\t}\n\treturn undefined;\n}\n\n/** Prepare the complete compactable transcript and its exact context-visible message tail. */\nexport function prepareCompactionBoundary(\n\tpathEntries: SessionEntry[],\n\tsettings: CompactionSettings,\n\toptions: Partial<VerbatimCompactionParameters> = {},\n): VerbatimCompactionPreparation | undefined {\n\tconst entries = normalizeDerivedSessionEntries(pathEntries);\n\tconst previous = latestActiveBoundary(entries);\n\tlet regionStart = 0;\n\tif (previous) {\n\t\tconst keptIndex = previous.entry.firstKeptEntryId === null\n\t\t\t? -1\n\t\t\t: entries.findIndex((entry) => entry.id === previous.entry.firstKeptEntryId);\n\t\tregionStart = keptIndex >= 0 ? keptIndex : previous.index + 1;\n\t}\n\n\tconst visible = visibleEntries(entries, regionStart);\n\tconst parameters = normalizeCompactionParameters({ ...settings, ...options }, autoDetectCompactionQuery(entries));\n\tconst tailStart = Math.max(0, visible.length - parameters.preserve_recent);\n\tconst regionMessages = visible.slice(0, tailStart);\n\tconst tailMessages = visible.slice(tailStart);\n\n\tconst serialized = serializeConversationForCompaction(convertToLlm(regionMessages.map((item) => item.message)));\n\tconst regionText = [previous?.entry.summary, serialized].filter((text): text is string => typeof text === \"string\" && text.length > 0).join(\"\\n\");\n\tconst region = createNumberedRegion(regionText);\n\tif (region.lines.length < MIN_COMPACTABLE_REGION_LINES) return undefined;\n\n\tconst preparation: VerbatimCompactionPreparation = {\n\t\tfirstKeptEntryId: tailMessages[0]?.entry.id ?? null,\n\t\tregion,\n\t\tregionEntryIds: regionMessages.map((item) => item.entry.id),\n\t\tkeptTailMessageCount: tailMessages.length,\n\t\ttokensBefore: estimateContextTokens(buildSessionContext(entries).messages).tokens,\n\t\tparameters,\n\t\tsettings,\n\t};\n\tkeptTailTokensByPreparation.set(preparation, tailMessages.reduce((sum, item) => sum + estimateTokens(item.message), 0));\n\treturn preparation;\n}\n"]}
@@ -1,8 +1,11 @@
1
1
  import type { StreamFn, ThinkingLevel } from "@earendil-works/pi-agent-core";
2
+ import type { ProviderHeaders } from "@earendil-works/pi-ai";
2
3
  import type { Api, Model } from "@earendil-works/pi-ai/compat";
3
4
  import type { CompactedTranscript, VerbatimCompactionPreparation } from "./compaction-types.js";
4
5
  export interface CompactionPlanOptions {
5
6
  streamFn: StreamFn;
7
+ /** Absolute path of the persisted session file. Undefined for in-memory sessions. */
8
+ sessionFilePath?: string;
6
9
  }
7
10
  export type CompactionRungResult = CompactedTranscript & {
8
11
  rung: "planned";
@@ -10,5 +13,5 @@ export type CompactionRungResult = CompactedTranscript & {
10
13
  /** Calculate the single global line threshold directly from the prepared setting. */
11
14
  export declare function targetKeepLines(preparation: VerbatimCompactionPreparation): number;
12
15
  /** Execute one whole-region model plan and mechanically accept its safe deletions. */
13
- export declare function runVerbatimCompaction(preparation: VerbatimCompactionPreparation, model: Model<Api>, apiKey: string, headers: Record<string, string> | undefined, signal: AbortSignal | undefined, thinkingLevel: ThinkingLevel | undefined, options: CompactionPlanOptions): Promise<CompactionRungResult>;
16
+ export declare function runVerbatimCompaction(preparation: VerbatimCompactionPreparation, model: Model<Api>, apiKey: string, headers: ProviderHeaders | undefined, signal: AbortSignal | undefined, thinkingLevel: ThinkingLevel | undefined, options: CompactionPlanOptions): Promise<CompactionRungResult>;
14
17
  //# sourceMappingURL=compaction-runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compaction-runner.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAI/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAEhG,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAE7E,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,WAAW,EAAE,6BAA6B,GAAG,MAAM,CAMlF;AAiBD,sFAAsF;AACtF,wBAAsB,qBAAqB,CAC1C,WAAW,EAAE,6BAA6B,EAC1C,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC3C,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CAkB/B"}
1
+ {"version":3,"file":"compaction-runner.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAI/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAEhG,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,QAAQ,CAAC;IACnB,qFAAqF;IACrF,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAE7E,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,WAAW,EAAE,6BAA6B,GAAG,MAAM,CAMlF;AAiBD,sFAAsF;AACtF,wBAAsB,qBAAqB,CAC1C,WAAW,EAAE,6BAA6B,EAC1C,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CAkB/B"}
@@ -21,7 +21,7 @@ function withWholeContextStats(result, preparation) {
21
21
  export async function runVerbatimCompaction(preparation, model, apiKey, headers, signal, thinkingLevel, options) {
22
22
  if (signal?.aborted)
23
23
  throw new Error("Compaction cancelled");
24
- const raw = await planDeletedLineRanges(preparation.region, preparation.parameters, model, { apiKey, headers }, signal, thinkingLevel, preparation.settings.reserveTokens, targetKeepLines(preparation), { streamFn: options.streamFn });
24
+ const raw = await planDeletedLineRanges(preparation.region, preparation.parameters, model, { apiKey, headers }, signal, thinkingLevel, preparation.settings.reserveTokens, targetKeepLines(preparation), { streamFn: options.streamFn, sessionFilePath: options.sessionFilePath });
25
25
  if (signal?.aborted)
26
26
  throw new Error("Compaction cancelled");
27
27
  return withWholeContextStats(reconstructCompactedTranscript(preparation.region, validateDeletedRanges(raw, preparation.region)), preparation);
@@ -1 +1 @@
1
- {"version":3,"file":"compaction-runner.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction-runner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAS3D,qFAAqF;AACrF,MAAM,UAAU,eAAe,CAAC,WAA0C;IACzE,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC,oBAAoB,EAAE,IAAI,IAAI,CAAC,CAAC;IAC1E,OAAO,IAAI,CAAC,GAAG,CACd,cAAc,EACd,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,UAAU,CAAC,iBAAiB,CAAC,CACtF,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC7B,MAA2B,EAC3B,WAA0C;IAE1C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,wBAAwB,CAAC,WAAW,CAAC,CAAC;IACrF,MAAM,gBAAgB,GAAG,WAAW,CAAC,YAAY,KAAK,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACxE,OAAO;QACN,GAAG,MAAM;QACT,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,CAAC,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE;KACjG,CAAC;AACH,CAAC;AAED,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAC1C,WAA0C,EAC1C,KAAiB,EACjB,MAAc,EACd,OAA2C,EAC3C,MAA+B,EAC/B,aAAwC,EACxC,OAA8B;IAE9B,IAAI,MAAM,EAAE,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,MAAM,qBAAqB,CACtC,WAAW,CAAC,MAAM,EAClB,WAAW,CAAC,UAAU,EACtB,KAAK,EACL,EAAE,MAAM,EAAE,OAAO,EAAE,EACnB,MAAM,EACN,aAAa,EACb,WAAW,CAAC,QAAQ,CAAC,aAAa,EAClC,eAAe,CAAC,WAAW,CAAC,EAC5B,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAC9B,CAAC;IACF,IAAI,MAAM,EAAE,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC7D,OAAO,qBAAqB,CAC3B,8BAA8B,CAAC,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,EAClG,WAAW,CACX,CAAC;AACH,CAAC","sourcesContent":["import type { StreamFn, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Model } from \"@earendil-works/pi-ai/compat\";\nimport { getKeptTailTokenEstimate } from \"./compaction-boundary.js\";\nimport { reconstructCompactedTranscript, validateDeletedRanges } from \"./deleted-ranges.js\";\nimport { planDeletedLineRanges } from \"./range-planner.js\";\nimport type { CompactedTranscript, VerbatimCompactionPreparation } from \"./compaction-types.js\";\n\nexport interface CompactionPlanOptions {\n\tstreamFn: StreamFn;\n}\n\nexport type CompactionRungResult = CompactedTranscript & { rung: \"planned\" };\n\n/** Calculate the single global line threshold directly from the prepared setting. */\nexport function targetKeepLines(preparation: VerbatimCompactionPreparation): number {\n\tconst protectedLines = preparation.region.protectedLineNumbers?.size ?? 0;\n\treturn Math.max(\n\t\tprotectedLines,\n\t\tMath.round(preparation.region.lines.length * preparation.parameters.compression_ratio),\n\t);\n}\n\nfunction withWholeContextStats(\n\tresult: CompactedTranscript,\n\tpreparation: VerbatimCompactionPreparation,\n): CompactionRungResult {\n\tconst tokensAfter = result.stats.tokensAfter + getKeptTailTokenEstimate(preparation);\n\tconst percentReduction = preparation.tokensBefore === 0\n\t\t? 0\n\t\t: Math.round((1 - tokensAfter / preparation.tokensBefore) * 1000) / 10;\n\treturn {\n\t\t...result,\n\t\trung: \"planned\",\n\t\tstats: { ...result.stats, tokensBefore: preparation.tokensBefore, tokensAfter, percentReduction },\n\t};\n}\n\n/** Execute one whole-region model plan and mechanically accept its safe deletions. */\nexport async function runVerbatimCompaction(\n\tpreparation: VerbatimCompactionPreparation,\n\tmodel: Model<Api>,\n\tapiKey: string,\n\theaders: Record<string, string> | undefined,\n\tsignal: AbortSignal | undefined,\n\tthinkingLevel: ThinkingLevel | undefined,\n\toptions: CompactionPlanOptions,\n): Promise<CompactionRungResult> {\n\tif (signal?.aborted) throw new Error(\"Compaction cancelled\");\n\tconst raw = await planDeletedLineRanges(\n\t\tpreparation.region,\n\t\tpreparation.parameters,\n\t\tmodel,\n\t\t{ apiKey, headers },\n\t\tsignal,\n\t\tthinkingLevel,\n\t\tpreparation.settings.reserveTokens,\n\t\ttargetKeepLines(preparation),\n\t\t{ streamFn: options.streamFn },\n\t);\n\tif (signal?.aborted) throw new Error(\"Compaction cancelled\");\n\treturn withWholeContextStats(\n\t\treconstructCompactedTranscript(preparation.region, validateDeletedRanges(raw, preparation.region)),\n\t\tpreparation,\n\t);\n}\n"]}
1
+ {"version":3,"file":"compaction-runner.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAW3D,qFAAqF;AACrF,MAAM,UAAU,eAAe,CAAC,WAA0C;IACzE,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC,oBAAoB,EAAE,IAAI,IAAI,CAAC,CAAC;IAC1E,OAAO,IAAI,CAAC,GAAG,CACd,cAAc,EACd,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,UAAU,CAAC,iBAAiB,CAAC,CACtF,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC7B,MAA2B,EAC3B,WAA0C;IAE1C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,wBAAwB,CAAC,WAAW,CAAC,CAAC;IACrF,MAAM,gBAAgB,GAAG,WAAW,CAAC,YAAY,KAAK,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACxE,OAAO;QACN,GAAG,MAAM;QACT,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,CAAC,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE;KACjG,CAAC;AACH,CAAC;AAED,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAC1C,WAA0C,EAC1C,KAAiB,EACjB,MAAc,EACd,OAAoC,EACpC,MAA+B,EAC/B,aAAwC,EACxC,OAA8B;IAE9B,IAAI,MAAM,EAAE,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,MAAM,qBAAqB,CACtC,WAAW,CAAC,MAAM,EAClB,WAAW,CAAC,UAAU,EACtB,KAAK,EACL,EAAE,MAAM,EAAE,OAAO,EAAE,EACnB,MAAM,EACN,aAAa,EACb,WAAW,CAAC,QAAQ,CAAC,aAAa,EAClC,eAAe,CAAC,WAAW,CAAC,EAC5B,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CACxE,CAAC;IACF,IAAI,MAAM,EAAE,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC7D,OAAO,qBAAqB,CAC3B,8BAA8B,CAAC,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,EAClG,WAAW,CACX,CAAC;AACH,CAAC","sourcesContent":["import type { StreamFn, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { ProviderHeaders } from \"@earendil-works/pi-ai\";\nimport type { Api, Model } from \"@earendil-works/pi-ai/compat\";\nimport { getKeptTailTokenEstimate } from \"./compaction-boundary.js\";\nimport { reconstructCompactedTranscript, validateDeletedRanges } from \"./deleted-ranges.js\";\nimport { planDeletedLineRanges } from \"./range-planner.js\";\nimport type { CompactedTranscript, VerbatimCompactionPreparation } from \"./compaction-types.js\";\n\nexport interface CompactionPlanOptions {\n\tstreamFn: StreamFn;\n\t/** Absolute path of the persisted session file. Undefined for in-memory sessions. */\n\tsessionFilePath?: string;\n}\n\nexport type CompactionRungResult = CompactedTranscript & { rung: \"planned\" };\n\n/** Calculate the single global line threshold directly from the prepared setting. */\nexport function targetKeepLines(preparation: VerbatimCompactionPreparation): number {\n\tconst protectedLines = preparation.region.protectedLineNumbers?.size ?? 0;\n\treturn Math.max(\n\t\tprotectedLines,\n\t\tMath.round(preparation.region.lines.length * preparation.parameters.compression_ratio),\n\t);\n}\n\nfunction withWholeContextStats(\n\tresult: CompactedTranscript,\n\tpreparation: VerbatimCompactionPreparation,\n): CompactionRungResult {\n\tconst tokensAfter = result.stats.tokensAfter + getKeptTailTokenEstimate(preparation);\n\tconst percentReduction = preparation.tokensBefore === 0\n\t\t? 0\n\t\t: Math.round((1 - tokensAfter / preparation.tokensBefore) * 1000) / 10;\n\treturn {\n\t\t...result,\n\t\trung: \"planned\",\n\t\tstats: { ...result.stats, tokensBefore: preparation.tokensBefore, tokensAfter, percentReduction },\n\t};\n}\n\n/** Execute one whole-region model plan and mechanically accept its safe deletions. */\nexport async function runVerbatimCompaction(\n\tpreparation: VerbatimCompactionPreparation,\n\tmodel: Model<Api>,\n\tapiKey: string,\n\theaders: ProviderHeaders | undefined,\n\tsignal: AbortSignal | undefined,\n\tthinkingLevel: ThinkingLevel | undefined,\n\toptions: CompactionPlanOptions,\n): Promise<CompactionRungResult> {\n\tif (signal?.aborted) throw new Error(\"Compaction cancelled\");\n\tconst raw = await planDeletedLineRanges(\n\t\tpreparation.region,\n\t\tpreparation.parameters,\n\t\tmodel,\n\t\t{ apiKey, headers },\n\t\tsignal,\n\t\tthinkingLevel,\n\t\tpreparation.settings.reserveTokens,\n\t\ttargetKeepLines(preparation),\n\t\t{ streamFn: options.streamFn, sessionFilePath: options.sessionFilePath },\n\t);\n\tif (signal?.aborted) throw new Error(\"Compaction cancelled\");\n\treturn withWholeContextStats(\n\t\treconstructCompactedTranscript(preparation.region, validateDeletedRanges(raw, preparation.region)),\n\t\tpreparation,\n\t);\n}\n"]}
@@ -58,7 +58,8 @@ export interface VerbatimCompactionDetails {
58
58
  backupPath?: string;
59
59
  }
60
60
  export interface VerbatimCompactionPreparation {
61
- firstKeptEntryId: string;
61
+ /** First context-visible tail entry, or null when no pre-boundary message is retained. */
62
+ firstKeptEntryId: string | null;
62
63
  region: NumberedRegion;
63
64
  regionEntryIds: string[];
64
65
  keptTailMessageCount: number;
@@ -68,7 +69,7 @@ export interface VerbatimCompactionPreparation {
68
69
  }
69
70
  export interface VerbatimCompactionResult {
70
71
  compactedText: string;
71
- firstKeptEntryId: string;
72
+ firstKeptEntryId: string | null;
72
73
  tokensBefore: number;
73
74
  stats: VerbatimCompactionStats;
74
75
  parameters: VerbatimCompactionParameters;
@@ -1 +1 @@
1
- {"version":3,"file":"compaction-types.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,eAAO,MAAM,kCAAkC,EAAG,CAAU,CAAC;AAC7D,eAAO,MAAM,4BAA4B,EAAG,gBAAyB,CAAC;AAEtE,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAE/C,MAAM,WAAW,4BAA4B;IAC5C,oDAAoD;IACpD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,eAAe,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACzB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC5B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,GAAG,CAAC,EAAE,eAAe,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,4EAA4E;IAC5E,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,aAAa,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,SAAS,EAAE,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAE7F,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,EAAE,uBAAuB,CAAC;CAC/B;AAED,MAAM,WAAW,uBAAuB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,OAAO,4BAA4B,CAAC;IAC9C,aAAa,EAAE,OAAO,kCAAkC,CAAC;IACzD,UAAU,EAAE,4BAA4B,CAAC;IACzC,KAAK,EAAE,uBAAuB,CAAC;IAC/B,IAAI,EAAE,SAAS,GAAG,WAAW,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,6BAA6B;IAC7C,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,4BAA4B,CAAC;IACzC,QAAQ,EAAE,kBAAkB,CAAC;CAC7B;AAED,MAAM,WAAW,wBAAwB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,uBAAuB,CAAC;IAC/B,UAAU,EAAE,4BAA4B,CAAC;IACzC,aAAa,EAAE,OAAO,kCAAkC,CAAC;IACzD,IAAI,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"compaction-types.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction-types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"compaction-types.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction-types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAU,CAAC;AAC7D,MAAM,CAAC,MAAM,4BAA4B,GAAG,gBAAyB,CAAC;AAEtE,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAC7C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC","sourcesContent":["import type { CompactionSettings } from \"./compaction.js\";\n\nexport const VERBATIM_COMPACTION_PROMPT_VERSION = 3 as const;\nexport const VERBATIM_COMPACTION_STRATEGY = \"verbatim-lines\" as const;\n\nexport const DEFAULT_COMPRESSION_RATIO = 0.5;\nexport const DEFAULT_PRESERVE_RECENT = 2;\nexport const MIN_COMPACTABLE_REGION_LINES = 20;\n\nexport interface VerbatimCompactionParameters {\n\t/** Fraction of compactable region lines to keep. */\n\tcompression_ratio: number;\n\t/** Recent context-eligible messages retained outside the compactable region. */\n\tpreserve_recent: number;\n\t/** Relevance focus used by the range planner. */\n\tquery: string;\n}\n\nexport interface LineRange {\n\t/** One-based inclusive first line. */\n\tstart: number;\n\t/** One-based inclusive last line. */\n\tend: number;\n}\n\nexport type RawLineEndpoint = number | string | boolean | null;\n\nexport interface RawLineRange {\n\tstart?: RawLineEndpoint;\n\tend?: RawLineEndpoint;\n}\n\nexport interface NumberedRegion {\n\treadonly __brand: \"NumberedRegion\";\n\tlines: string[];\n\theaderLineNumbers: ReadonlySet<number>;\n\tpriorMarkerNs: ReadonlyMap<number, number>;\n\t/** Optional future protected spans, expressed as one-based line numbers. */\n\tprotectedLineNumbers?: ReadonlySet<number>;\n\ttokenEstimate: number;\n}\n\nexport type ValidatedRanges = readonly LineRange[] & { readonly __brand: \"ValidatedRanges\" };\n\nexport interface CompactedTranscript {\n\ttext: string;\n\tranges: LineRange[];\n\tstats: VerbatimCompactionStats;\n}\n\nexport interface VerbatimCompactionStats {\n\tlinesBefore: number;\n\tlinesDeleted: number;\n\tlinesKept: number;\n\trangeCount: number;\n\ttokensBefore: number;\n\ttokensAfter: number;\n\tpercentReduction: number;\n}\n\nexport interface VerbatimCompactionDetails {\n\tstrategy: typeof VERBATIM_COMPACTION_STRATEGY;\n\tpromptVersion: typeof VERBATIM_COMPACTION_PROMPT_VERSION;\n\tparameters: VerbatimCompactionParameters;\n\tstats: VerbatimCompactionStats;\n\trung: \"planned\" | \"extension\";\n\tbackupPath?: string;\n}\n\nexport interface VerbatimCompactionPreparation {\n\tfirstKeptEntryId: string;\n\tregion: NumberedRegion;\n\tregionEntryIds: string[];\n\tkeptTailMessageCount: number;\n\ttokensBefore: number;\n\tparameters: VerbatimCompactionParameters;\n\tsettings: CompactionSettings;\n}\n\nexport interface VerbatimCompactionResult {\n\tcompactedText: string;\n\tfirstKeptEntryId: string;\n\ttokensBefore: number;\n\tstats: VerbatimCompactionStats;\n\tparameters: VerbatimCompactionParameters;\n\tpromptVersion: typeof VERBATIM_COMPACTION_PROMPT_VERSION;\n\trung: VerbatimCompactionDetails[\"rung\"];\n\tbackupPath?: string;\n}\n"]}
1
+ {"version":3,"file":"compaction-types.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction-types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAU,CAAC;AAC7D,MAAM,CAAC,MAAM,4BAA4B,GAAG,gBAAyB,CAAC;AAEtE,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAC7C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC","sourcesContent":["import type { CompactionSettings } from \"./compaction.js\";\n\nexport const VERBATIM_COMPACTION_PROMPT_VERSION = 3 as const;\nexport const VERBATIM_COMPACTION_STRATEGY = \"verbatim-lines\" as const;\n\nexport const DEFAULT_COMPRESSION_RATIO = 0.5;\nexport const DEFAULT_PRESERVE_RECENT = 2;\nexport const MIN_COMPACTABLE_REGION_LINES = 20;\n\nexport interface VerbatimCompactionParameters {\n\t/** Fraction of compactable region lines to keep. */\n\tcompression_ratio: number;\n\t/** Recent context-eligible messages retained outside the compactable region. */\n\tpreserve_recent: number;\n\t/** Relevance focus used by the range planner. */\n\tquery: string;\n}\n\nexport interface LineRange {\n\t/** One-based inclusive first line. */\n\tstart: number;\n\t/** One-based inclusive last line. */\n\tend: number;\n}\n\nexport type RawLineEndpoint = number | string | boolean | null;\n\nexport interface RawLineRange {\n\tstart?: RawLineEndpoint;\n\tend?: RawLineEndpoint;\n}\n\nexport interface NumberedRegion {\n\treadonly __brand: \"NumberedRegion\";\n\tlines: string[];\n\theaderLineNumbers: ReadonlySet<number>;\n\tpriorMarkerNs: ReadonlyMap<number, number>;\n\t/** Optional future protected spans, expressed as one-based line numbers. */\n\tprotectedLineNumbers?: ReadonlySet<number>;\n\ttokenEstimate: number;\n}\n\nexport type ValidatedRanges = readonly LineRange[] & { readonly __brand: \"ValidatedRanges\" };\n\nexport interface CompactedTranscript {\n\ttext: string;\n\tranges: LineRange[];\n\tstats: VerbatimCompactionStats;\n}\n\nexport interface VerbatimCompactionStats {\n\tlinesBefore: number;\n\tlinesDeleted: number;\n\tlinesKept: number;\n\trangeCount: number;\n\ttokensBefore: number;\n\ttokensAfter: number;\n\tpercentReduction: number;\n}\n\nexport interface VerbatimCompactionDetails {\n\tstrategy: typeof VERBATIM_COMPACTION_STRATEGY;\n\tpromptVersion: typeof VERBATIM_COMPACTION_PROMPT_VERSION;\n\tparameters: VerbatimCompactionParameters;\n\tstats: VerbatimCompactionStats;\n\trung: \"planned\" | \"extension\";\n\tbackupPath?: string;\n}\n\nexport interface VerbatimCompactionPreparation {\n\t/** First context-visible tail entry, or null when no pre-boundary message is retained. */\n\tfirstKeptEntryId: string | null;\n\tregion: NumberedRegion;\n\tregionEntryIds: string[];\n\tkeptTailMessageCount: number;\n\ttokensBefore: number;\n\tparameters: VerbatimCompactionParameters;\n\tsettings: CompactionSettings;\n}\n\nexport interface VerbatimCompactionResult {\n\tcompactedText: string;\n\tfirstKeptEntryId: string | null;\n\ttokensBefore: number;\n\tstats: VerbatimCompactionStats;\n\tparameters: VerbatimCompactionParameters;\n\tpromptVersion: typeof VERBATIM_COMPACTION_PROMPT_VERSION;\n\trung: VerbatimCompactionDetails[\"rung\"];\n\tbackupPath?: string;\n}\n"]}
@@ -2,7 +2,7 @@
2
2
  * Neutral context-usage metrics for deciding when a session needs compaction.
3
3
  */
4
4
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
5
- import type { Usage } from "@earendil-works/pi-ai/compat";
5
+ import type { Api, Usage } from "@earendil-works/pi-ai/compat";
6
6
  import type { SessionEntry } from "../session-manager.ts";
7
7
  export interface CompactionSettings {
8
8
  enabled: boolean;
@@ -20,12 +20,12 @@ export declare const DEFAULT_COMPACTION_SETTINGS: CompactionSettings;
20
20
  *
21
21
  * Prefer normalized component fields over `totalTokens`: some providers expose
22
22
  * `totalTokens` as a billing/cumulative total, while the footer needs an active
23
- * context estimate. Anthropic-compatible endpoints can also mirror cached input
24
- * in both `input` and `cacheRead`/`cacheWrite`; when cache buckets are nearly the
25
- * same size as `input`, treat `input` as the full prompt instead of counting the
26
- * same cached prompt twice.
23
+ * context estimate. Some Anthropic-compatible endpoints mirror cached input in
24
+ * both `input` and `cacheRead`/`cacheWrite`; only Anthropic Messages usage uses
25
+ * the near-equal-bucket guard because OpenAI APIs expose disjoint normalized
26
+ * components that must always be summed.
27
27
  */
28
- export declare function calculateContextTokens(usage: Usage): number;
28
+ export declare function calculateContextTokens(usage: Usage, api?: Api): number;
29
29
  /**
30
30
  * Find the last non-aborted assistant message usage from session entries.
31
31
  */
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAoB,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,eAAe,EAAE,MAAM,CAAC;IACxB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,2BAA2B,EAAE,kBAKzC,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAY3D;AAgBD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,GAAG,SAAS,CAShF;AAED,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAkBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,oBAAoB,CA4BpF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAGjH;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAC1C,eAAO,MAAM,sBAAsB,QAAuC,CAAC;AAgC3E,mFAAmF;AACnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,UAAO,GAAG,MAAM,CAIjF;AAYD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAOzF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAE5F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CA6B5D"}
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,GAAG,EAAoB,KAAK,EAAE,MAAM,8BAA8B,CAAC;AACjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,eAAe,EAAE,MAAM,CAAC;IACxB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,2BAA2B,EAAE,kBAKzC,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,CAYtE;AAgBD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,GAAG,SAAS,CAShF;AAED,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAuBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,oBAAoB,CA4BpF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAGjH;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAC1C,eAAO,MAAM,sBAAsB,QAAuC,CAAC;AAgC3E,mFAAmF;AACnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,UAAO,GAAG,MAAM,CAIjF;AAYD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAOzF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAE5F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CA6B5D"}
@@ -13,12 +13,12 @@ export const DEFAULT_COMPACTION_SETTINGS = {
13
13
  *
14
14
  * Prefer normalized component fields over `totalTokens`: some providers expose
15
15
  * `totalTokens` as a billing/cumulative total, while the footer needs an active
16
- * context estimate. Anthropic-compatible endpoints can also mirror cached input
17
- * in both `input` and `cacheRead`/`cacheWrite`; when cache buckets are nearly the
18
- * same size as `input`, treat `input` as the full prompt instead of counting the
19
- * same cached prompt twice.
16
+ * context estimate. Some Anthropic-compatible endpoints mirror cached input in
17
+ * both `input` and `cacheRead`/`cacheWrite`; only Anthropic Messages usage uses
18
+ * the near-equal-bucket guard because OpenAI APIs expose disjoint normalized
19
+ * components that must always be summed.
20
20
  */
21
- export function calculateContextTokens(usage) {
21
+ export function calculateContextTokens(usage, api) {
22
22
  const input = Math.max(0, usage.input || 0);
23
23
  const output = Math.max(0, usage.output || 0);
24
24
  const cacheRead = Math.max(0, usage.cacheRead || 0);
@@ -27,7 +27,7 @@ export function calculateContextTokens(usage) {
27
27
  const hasComponents = input > 0 || output > 0 || cacheTokens > 0;
28
28
  if (!hasComponents)
29
29
  return Math.max(0, usage.totalTokens || 0);
30
- const cacheMirrorsInput = input > 0 && cacheTokens > 0 && cacheTokens >= input * 0.9 && cacheTokens <= input * 1.1;
30
+ const cacheMirrorsInput = api === "anthropic-messages" && input > 0 && cacheTokens > 0 && cacheTokens >= input * 0.9 && cacheTokens <= input * 1.1;
31
31
  const promptTokens = cacheMirrorsInput ? input : input + cacheTokens;
32
32
  return promptTokens + output;
33
33
  }
@@ -64,8 +64,11 @@ function getLastAssistantUsageInfo(messages) {
64
64
  for (let i = 0; i < messages.length; i++) {
65
65
  const message = messages[i];
66
66
  const usage = getAssistantUsage(message);
67
- if (usage && message.timestamp >= latestPrefixTimestamp && calculateContextTokens(usage) > 0) {
68
- usageInfo = { usage, index: i };
67
+ if (usage &&
68
+ message.role === "assistant" &&
69
+ message.timestamp >= latestPrefixTimestamp &&
70
+ calculateContextTokens(usage, message.api) > 0) {
71
+ usageInfo = { usage, api: message.api, index: i };
69
72
  }
70
73
  latestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);
71
74
  }
@@ -89,7 +92,7 @@ export function estimateContextTokens(messages) {
89
92
  lastUsageIndex: null,
90
93
  };
91
94
  }
92
- const usageTokens = calculateContextTokens(usageInfo.usage);
95
+ const usageTokens = calculateContextTokens(usageInfo.usage, usageInfo.api);
93
96
  let trailingTokens = 0;
94
97
  for (let i = usageInfo.index + 1; i < messages.length; i++) {
95
98
  trailingTokens += estimateTokens(messages[i]);
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Neutral context-usage metrics for deciding when a session needs compaction.\n */\n\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { SessionEntry } from \"../session-manager.ts\";\nimport { messageIsLlmVisible, userLikeContentBlockIsLlmVisible } from \"../messages.ts\";\n\nexport interface CompactionSettings {\n\tenabled: boolean;\n\treserveTokens: number;\n\t/** Fraction of compactable context to keep. 0.3 is aggressive, 0.7 is light. */\n\tcompression_ratio: number;\n\t/** Number of recent context-eligible messages to preserve in standard mode. */\n\tpreserve_recent: number;\n\t/** Focus query for relevance-based pruning; auto-detected when omitted in settings/options. */\n\tquery?: string;\n}\n\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tcompression_ratio: 0.5,\n\tpreserve_recent: 2,\n};\n\n/**\n * Calculate active context-window tokens from provider usage.\n *\n * Prefer normalized component fields over `totalTokens`: some providers expose\n * `totalTokens` as a billing/cumulative total, while the footer needs an active\n * context estimate. Anthropic-compatible endpoints can also mirror cached input\n * in both `input` and `cacheRead`/`cacheWrite`; when cache buckets are nearly the\n * same size as `input`, treat `input` as the full prompt instead of counting the\n * same cached prompt twice.\n */\nexport function calculateContextTokens(usage: Usage): number {\n\tconst input = Math.max(0, usage.input || 0);\n\tconst output = Math.max(0, usage.output || 0);\n\tconst cacheRead = Math.max(0, usage.cacheRead || 0);\n\tconst cacheWrite = Math.max(0, usage.cacheWrite || 0);\n\tconst cacheTokens = cacheRead + cacheWrite;\n\tconst hasComponents = input > 0 || output > 0 || cacheTokens > 0;\n\tif (!hasComponents) return Math.max(0, usage.totalTokens || 0);\n\n\tconst cacheMirrorsInput = input > 0 && cacheTokens > 0 && cacheTokens >= input * 0.9 && cacheTokens <= input * 1.1;\n\tconst promptTokens = cacheMirrorsInput ? input : input + cacheTokens;\n\treturn promptTokens + output;\n}\n\n/**\n * Get usage from an assistant message if available.\n * Skips aborted and error messages as they don't have valid usage data.\n */\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (assistantMsg.stopReason !== \"aborted\" && assistantMsg.stopReason !== \"error\" && assistantMsg.usage) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Find the last non-aborted assistant message usage from session entries.\n */\nexport function getLastAssistantUsage(entries: SessionEntry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport interface ContextUsageEstimate {\n\ttokens: number;\n\tusageTokens: number;\n\ttrailingTokens: number;\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; index: number } | undefined {\n\tlet latestPrefixTimestamp = Number.NEGATIVE_INFINITY;\n\tlet usageInfo: { usage: Usage; index: number } | undefined;\n\n\tfor (let i = 0; i < messages.length; i++) {\n\t\tconst message = messages[i];\n\t\tconst usage = getAssistantUsage(message);\n\t\tif (usage && message.timestamp >= latestPrefixTimestamp && calculateContextTokens(usage) > 0) {\n\t\t\tusageInfo = { usage, index: i };\n\t\t}\n\t\tlatestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);\n\t}\n\n\treturn usageInfo;\n}\n\n/**\n * Estimate context tokens from messages, using the last assistant usage when available.\n * If there are messages after the last usage, estimate their tokens with estimateTokens.\n */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/**\n * Check if compaction should trigger based on context usage.\n */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\n/**\n * Shared image-token estimation used by every compaction/context-accounting path.\n *\n * Providers fold image tokens into their reported prompt/input usage, so usage-based\n * accounting already captures actual image cost. For heuristic paths (trailing\n * messages without usage, transcript content-block estimates) a single conservative\n * fixed estimate keeps both the context-window threshold check and the transcript\n * planner consistent.\n */\nexport const ESTIMATED_IMAGE_CHARS = 4800;\nexport const ESTIMATED_IMAGE_TOKENS = Math.ceil(ESTIMATED_IMAGE_CHARS / 4);\n\nfunction safeSerializedPayloadLength(value: unknown, fallback: string): number {\n\ttry {\n\t\tconst serialized = JSON.stringify(value);\n\t\tif (typeof serialized === \"string\") return serialized.length;\n\t} catch {\n\t\t// Cyclic and otherwise unserializable future blocks use a conservative marker below.\n\t}\n\treturn fallback.length;\n}\n\nfunction nonEmptyBlockType(block: unknown): string | undefined {\n\tif (!block || typeof block !== \"object\") return undefined;\n\tconst type = (block as { type?: unknown }).type;\n\treturn typeof type === \"string\" && type.trim().length > 0 ? type : undefined;\n}\n\nfunction estimateContentBlockChars(block: unknown): number {\n\tconst type = nonEmptyBlockType(block);\n\tif (!type) return 0;\n\tconst record = block as Record<string, unknown>;\n\tif (type === \"image\") return ESTIMATED_IMAGE_CHARS;\n\tif (type === \"text\") return typeof record.text === \"string\" ? record.text.length : 0;\n\tif (type === \"thinking\") return typeof record.thinking === \"string\" ? record.thinking.length : 0;\n\tif (type === \"toolCall\") {\n\t\tconst nameLength = typeof record.name === \"string\" ? record.name.length : 0;\n\t\treturn nameLength + safeSerializedPayloadLength(record.arguments, \"[unserializable tool arguments]\");\n\t}\n\treturn safeSerializedPayloadLength(block, `[unserializable ${type} block]`);\n}\n\n/** Estimate one raw content block after the caller applies provider visibility. */\nexport function estimateContentBlockTokens(block: unknown, visible = true): number {\n\tif (!visible) return 0;\n\tconst chars = estimateContentBlockChars(block);\n\treturn chars > 0 ? Math.ceil(chars / 4) : 0;\n}\n\nfunction estimateUserLikeContentTokens(content: unknown): number {\n\tif (typeof content === \"string\") return content.trim().length > 0 ? Math.ceil(content.length / 4) : 0;\n\tif (!Array.isArray(content)) return 0;\n\tconst chars = content.reduce(\n\t\t(total, block) => total + (userLikeContentBlockIsLlmVisible(block) ? estimateContentBlockChars(block) : 0),\n\t\t0,\n\t);\n\treturn chars > 0 ? Math.ceil(chars / 4) : 0;\n}\n\n/**\n * Count image content blocks in a message content array (text or block array).\n *\n * Exported as the canonical image-counting contract so tests can verify the\n * heuristic independently of the transcript-based estimation used in production.\n */\nexport function countImageContentBlocks(content: string | Array<{ type: string }>): number {\n\tif (typeof content === \"string\" || !Array.isArray(content)) return 0;\n\tlet count = 0;\n\tfor (const block of content) {\n\t\tif (block && typeof block === \"object\" && block.type === \"image\") count += 1;\n\t}\n\treturn count;\n}\n\n/**\n * Estimate the token cost of only the image content blocks in a message content array.\n *\n * Exported as the canonical image-token-estimation contract so tests can verify\n * the heuristic independently of the transcript-based estimation used in production.\n */\nexport function estimateImageContentTokens(content: string | Array<{ type: string }>): number {\n\treturn countImageContentBlocks(content) * ESTIMATED_IMAGE_TOKENS;\n}\n\n/**\n * Estimate token count for a message using chars/4 heuristic.\n * This is conservative (overestimates tokens).\n */\nexport function estimateTokens(message: AgentMessage): number {\n\tif (!message || typeof message !== \"object\" || !messageIsLlmVisible(message)) return 0;\n\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"custom\":\n\t\t\treturn estimateUserLikeContentTokens((message as { content?: unknown }).content);\n\t\tcase \"assistant\": {\n\t\t\tconst content = (message as { content?: unknown }).content;\n\t\t\tif (!Array.isArray(content)) return 0;\n\t\t\tconst chars = content.reduce((total, block) => total + estimateContentBlockChars(block), 0);\n\t\t\treturn chars > 0 ? Math.ceil(chars / 4) : 0;\n\t\t}\n\t\tcase \"toolResult\": {\n\t\t\tconst content = (message as { content?: unknown }).content;\n\t\t\tif (!Array.isArray(content)) return 0;\n\t\t\tconst chars = content.reduce((total, block) => total + estimateContentBlockChars(block), 0);\n\t\t\treturn chars > 0 ? Math.ceil(chars / 4) : 0;\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tconst command = typeof message.command === \"string\" ? message.command : \"\";\n\t\t\tconst output = typeof message.output === \"string\" ? message.output : \"\";\n\t\t\treturn Math.ceil((command.length + output.length) / 4);\n\t\t}\n\t\tcase \"branchSummary\":\n\t\t\treturn typeof message.summary === \"string\" ? Math.ceil(message.summary.length / 4) : 0;\n\t}\n\n\treturn 0;\n}\n"]}
1
+ {"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,mBAAmB,EAAE,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAavF,MAAM,CAAC,MAAM,2BAA2B,GAAuB;IAC9D,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,KAAK;IACpB,iBAAiB,EAAE,GAAG;IACtB,eAAe,EAAE,CAAC;CAClB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAY,EAAE,GAAS;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;IAC3C,MAAM,aAAa,GAAG,KAAK,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC;IACjE,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAE/D,MAAM,iBAAiB,GAAG,GAAG,KAAK,oBAAoB,IAAI,KAAK,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,IAAI,KAAK,GAAG,GAAG,IAAI,WAAW,IAAI,KAAK,GAAG,GAAG,CAAC;IACnJ,MAAM,YAAY,GAAG,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,WAAW,CAAC;IACrE,OAAO,YAAY,GAAG,MAAM,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,GAAiB;IAC3C,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,IAAI,GAAG,EAAE,CAAC;QAChD,MAAM,YAAY,GAAG,GAAuB,CAAC;QAC7C,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,IAAI,YAAY,CAAC,UAAU,KAAK,OAAO,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;YACxG,OAAO,YAAY,CAAC,KAAK,CAAC;QAC3B,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAuB;IAC5D,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC/C,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;QACzB,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AASD,SAAS,yBAAyB,CAAC,QAAwB;IAC1D,IAAI,qBAAqB,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACrD,IAAI,SAAgE,CAAC;IAErE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACzC,IACC,KAAK;YACL,OAAO,CAAC,IAAI,KAAK,WAAW;YAC5B,OAAO,CAAC,SAAS,IAAI,qBAAqB;YAC1C,sBAAsB,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAC7C,CAAC;YACF,SAAS,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACnD,CAAC;QACD,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAwB;IAC7D,MAAM,SAAS,GAAG,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IAEtD,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAChC,SAAS,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;QACD,OAAO;YACN,MAAM,EAAE,SAAS;YACjB,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,SAAS;YACzB,cAAc,EAAE,IAAI;SACpB,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,sBAAsB,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;IAC3E,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5D,cAAc,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO;QACN,MAAM,EAAE,WAAW,GAAG,cAAc;QACpC,WAAW;QACX,cAAc;QACd,cAAc,EAAE,SAAS,CAAC,KAAK;KAC/B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,aAAqB,EAAE,aAAqB,EAAE,QAA4B;IACvG,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IACpC,OAAO,aAAa,GAAG,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;AAC/D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAC1C,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,IAAI,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAC;AAE3E,SAAS,2BAA2B,CAAC,KAAc,EAAE,QAAgB;IACpE,IAAI,CAAC;QACJ,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,OAAO,UAAU,KAAK,QAAQ;YAAE,OAAO,UAAU,CAAC,MAAM,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACR,qFAAqF;IACtF,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC;AACxB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACxC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;IAChD,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAc;IAChD,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IACpB,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,qBAAqB,CAAC;IACnD,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACjG,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,OAAO,UAAU,GAAG,2BAA2B,CAAC,MAAM,CAAC,SAAS,EAAE,iCAAiC,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,2BAA2B,CAAC,KAAK,EAAE,mBAAmB,IAAI,SAAS,CAAC,CAAC;AAC7E,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,0BAA0B,CAAC,KAAc,EAAE,OAAO,GAAG,IAAI;IACxE,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,6BAA6B,CAAC,OAAgB;IACtD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAC3B,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,gCAAgC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1G,CAAC,CACD,CAAC;IACF,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAyC;IAChF,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,CAAC;IACrE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;YAAE,KAAK,IAAI,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAyC;IACnF,OAAO,uBAAuB,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAqB;IACnD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,CAAC;IAEvF,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ;YACZ,OAAO,6BAA6B,CAAE,OAAiC,CAAC,OAAO,CAAC,CAAC;QAClF,KAAK,WAAW,EAAE,CAAC;YAClB,MAAM,OAAO,GAAI,OAAiC,CAAC,OAAO,CAAC;YAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBAAE,OAAO,CAAC,CAAC;YACtC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5F,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,YAAY,EAAE,CAAC;YACnB,MAAM,OAAO,GAAI,OAAiC,CAAC,OAAO,CAAC;YAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBAAE,OAAO,CAAC,CAAC;YACtC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5F,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,eAAe,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,MAAM,MAAM,GAAG,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YACxE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,KAAK,eAAe;YACnB,OAAO,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;IAED,OAAO,CAAC,CAAC;AACV,CAAC","sourcesContent":["/**\n * Neutral context-usage metrics for deciding when a session needs compaction.\n */\n\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Api, AssistantMessage, Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { SessionEntry } from \"../session-manager.ts\";\nimport { messageIsLlmVisible, userLikeContentBlockIsLlmVisible } from \"../messages.ts\";\n\nexport interface CompactionSettings {\n\tenabled: boolean;\n\treserveTokens: number;\n\t/** Fraction of compactable context to keep. 0.3 is aggressive, 0.7 is light. */\n\tcompression_ratio: number;\n\t/** Number of recent context-eligible messages to preserve in standard mode. */\n\tpreserve_recent: number;\n\t/** Focus query for relevance-based pruning; auto-detected when omitted in settings/options. */\n\tquery?: string;\n}\n\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tcompression_ratio: 0.5,\n\tpreserve_recent: 2,\n};\n\n/**\n * Calculate active context-window tokens from provider usage.\n *\n * Prefer normalized component fields over `totalTokens`: some providers expose\n * `totalTokens` as a billing/cumulative total, while the footer needs an active\n * context estimate. Some Anthropic-compatible endpoints mirror cached input in\n * both `input` and `cacheRead`/`cacheWrite`; only Anthropic Messages usage uses\n * the near-equal-bucket guard because OpenAI APIs expose disjoint normalized\n * components that must always be summed.\n */\nexport function calculateContextTokens(usage: Usage, api?: Api): number {\n\tconst input = Math.max(0, usage.input || 0);\n\tconst output = Math.max(0, usage.output || 0);\n\tconst cacheRead = Math.max(0, usage.cacheRead || 0);\n\tconst cacheWrite = Math.max(0, usage.cacheWrite || 0);\n\tconst cacheTokens = cacheRead + cacheWrite;\n\tconst hasComponents = input > 0 || output > 0 || cacheTokens > 0;\n\tif (!hasComponents) return Math.max(0, usage.totalTokens || 0);\n\n\tconst cacheMirrorsInput = api === \"anthropic-messages\" && input > 0 && cacheTokens > 0 && cacheTokens >= input * 0.9 && cacheTokens <= input * 1.1;\n\tconst promptTokens = cacheMirrorsInput ? input : input + cacheTokens;\n\treturn promptTokens + output;\n}\n\n/**\n * Get usage from an assistant message if available.\n * Skips aborted and error messages as they don't have valid usage data.\n */\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (assistantMsg.stopReason !== \"aborted\" && assistantMsg.stopReason !== \"error\" && assistantMsg.usage) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Find the last non-aborted assistant message usage from session entries.\n */\nexport function getLastAssistantUsage(entries: SessionEntry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport interface ContextUsageEstimate {\n\ttokens: number;\n\tusageTokens: number;\n\ttrailingTokens: number;\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; api: Api; index: number } | undefined {\n\tlet latestPrefixTimestamp = Number.NEGATIVE_INFINITY;\n\tlet usageInfo: { usage: Usage; api: Api; index: number } | undefined;\n\n\tfor (let i = 0; i < messages.length; i++) {\n\t\tconst message = messages[i];\n\t\tconst usage = getAssistantUsage(message);\n\t\tif (\n\t\t\tusage &&\n\t\t\tmessage.role === \"assistant\" &&\n\t\t\tmessage.timestamp >= latestPrefixTimestamp &&\n\t\t\tcalculateContextTokens(usage, message.api) > 0\n\t\t) {\n\t\t\tusageInfo = { usage, api: message.api, index: i };\n\t\t}\n\t\tlatestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);\n\t}\n\n\treturn usageInfo;\n}\n\n/**\n * Estimate context tokens from messages, using the last assistant usage when available.\n * If there are messages after the last usage, estimate their tokens with estimateTokens.\n */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage, usageInfo.api);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/**\n * Check if compaction should trigger based on context usage.\n */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\n/**\n * Shared image-token estimation used by every compaction/context-accounting path.\n *\n * Providers fold image tokens into their reported prompt/input usage, so usage-based\n * accounting already captures actual image cost. For heuristic paths (trailing\n * messages without usage, transcript content-block estimates) a single conservative\n * fixed estimate keeps both the context-window threshold check and the transcript\n * planner consistent.\n */\nexport const ESTIMATED_IMAGE_CHARS = 4800;\nexport const ESTIMATED_IMAGE_TOKENS = Math.ceil(ESTIMATED_IMAGE_CHARS / 4);\n\nfunction safeSerializedPayloadLength(value: unknown, fallback: string): number {\n\ttry {\n\t\tconst serialized = JSON.stringify(value);\n\t\tif (typeof serialized === \"string\") return serialized.length;\n\t} catch {\n\t\t// Cyclic and otherwise unserializable future blocks use a conservative marker below.\n\t}\n\treturn fallback.length;\n}\n\nfunction nonEmptyBlockType(block: unknown): string | undefined {\n\tif (!block || typeof block !== \"object\") return undefined;\n\tconst type = (block as { type?: unknown }).type;\n\treturn typeof type === \"string\" && type.trim().length > 0 ? type : undefined;\n}\n\nfunction estimateContentBlockChars(block: unknown): number {\n\tconst type = nonEmptyBlockType(block);\n\tif (!type) return 0;\n\tconst record = block as Record<string, unknown>;\n\tif (type === \"image\") return ESTIMATED_IMAGE_CHARS;\n\tif (type === \"text\") return typeof record.text === \"string\" ? record.text.length : 0;\n\tif (type === \"thinking\") return typeof record.thinking === \"string\" ? record.thinking.length : 0;\n\tif (type === \"toolCall\") {\n\t\tconst nameLength = typeof record.name === \"string\" ? record.name.length : 0;\n\t\treturn nameLength + safeSerializedPayloadLength(record.arguments, \"[unserializable tool arguments]\");\n\t}\n\treturn safeSerializedPayloadLength(block, `[unserializable ${type} block]`);\n}\n\n/** Estimate one raw content block after the caller applies provider visibility. */\nexport function estimateContentBlockTokens(block: unknown, visible = true): number {\n\tif (!visible) return 0;\n\tconst chars = estimateContentBlockChars(block);\n\treturn chars > 0 ? Math.ceil(chars / 4) : 0;\n}\n\nfunction estimateUserLikeContentTokens(content: unknown): number {\n\tif (typeof content === \"string\") return content.trim().length > 0 ? Math.ceil(content.length / 4) : 0;\n\tif (!Array.isArray(content)) return 0;\n\tconst chars = content.reduce(\n\t\t(total, block) => total + (userLikeContentBlockIsLlmVisible(block) ? estimateContentBlockChars(block) : 0),\n\t\t0,\n\t);\n\treturn chars > 0 ? Math.ceil(chars / 4) : 0;\n}\n\n/**\n * Count image content blocks in a message content array (text or block array).\n *\n * Exported as the canonical image-counting contract so tests can verify the\n * heuristic independently of the transcript-based estimation used in production.\n */\nexport function countImageContentBlocks(content: string | Array<{ type: string }>): number {\n\tif (typeof content === \"string\" || !Array.isArray(content)) return 0;\n\tlet count = 0;\n\tfor (const block of content) {\n\t\tif (block && typeof block === \"object\" && block.type === \"image\") count += 1;\n\t}\n\treturn count;\n}\n\n/**\n * Estimate the token cost of only the image content blocks in a message content array.\n *\n * Exported as the canonical image-token-estimation contract so tests can verify\n * the heuristic independently of the transcript-based estimation used in production.\n */\nexport function estimateImageContentTokens(content: string | Array<{ type: string }>): number {\n\treturn countImageContentBlocks(content) * ESTIMATED_IMAGE_TOKENS;\n}\n\n/**\n * Estimate token count for a message using chars/4 heuristic.\n * This is conservative (overestimates tokens).\n */\nexport function estimateTokens(message: AgentMessage): number {\n\tif (!message || typeof message !== \"object\" || !messageIsLlmVisible(message)) return 0;\n\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"custom\":\n\t\t\treturn estimateUserLikeContentTokens((message as { content?: unknown }).content);\n\t\tcase \"assistant\": {\n\t\t\tconst content = (message as { content?: unknown }).content;\n\t\t\tif (!Array.isArray(content)) return 0;\n\t\t\tconst chars = content.reduce((total, block) => total + estimateContentBlockChars(block), 0);\n\t\t\treturn chars > 0 ? Math.ceil(chars / 4) : 0;\n\t\t}\n\t\tcase \"toolResult\": {\n\t\t\tconst content = (message as { content?: unknown }).content;\n\t\t\tif (!Array.isArray(content)) return 0;\n\t\t\tconst chars = content.reduce((total, block) => total + estimateContentBlockChars(block), 0);\n\t\t\treturn chars > 0 ? Math.ceil(chars / 4) : 0;\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tconst command = typeof message.command === \"string\" ? message.command : \"\";\n\t\t\tconst output = typeof message.output === \"string\" ? message.output : \"\";\n\t\t\treturn Math.ceil((command.length + output.length) / 4);\n\t\t}\n\t\tcase \"branchSummary\":\n\t\t\treturn typeof message.summary === \"string\" ? Math.ceil(message.summary.length / 4) : 0;\n\t}\n\n\treturn 0;\n}\n"]}
@@ -7,6 +7,7 @@ export * from "./compaction-types.js";
7
7
  export * from "./compaction-parameters.js";
8
8
  export * from "./compaction-boundary.js";
9
9
  export * from "./range-planner.js";
10
+ export * from "./range-planner-diagnostics.js";
10
11
  export * from "./compaction-runner.js";
11
12
  export * from "./deleted-ranges.js";
12
13
  export * from "./transcript-serialization.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC"}
@@ -7,6 +7,7 @@ export * from "./compaction-types.js";
7
7
  export * from "./compaction-parameters.js";
8
8
  export * from "./compaction-boundary.js";
9
9
  export * from "./range-planner.js";
10
+ export * from "./range-planner-diagnostics.js";
10
11
  export * from "./compaction-runner.js";
11
12
  export * from "./deleted-ranges.js";
12
13
  export * from "./transcript-serialization.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC","sourcesContent":["/**\n * Compaction support utilities.\n */\n\nexport * from \"./branch-summarization.ts\";\nexport * from \"./compaction.ts\";\nexport * from \"./compaction-types.js\";\nexport * from \"./compaction-parameters.js\";\nexport * from \"./compaction-boundary.js\";\nexport * from \"./range-planner.js\";\nexport * from \"./compaction-runner.js\";\nexport * from \"./deleted-ranges.js\";\nexport * from \"./transcript-serialization.js\";\nexport * from \"./utils.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC","sourcesContent":["/**\n * Compaction support utilities.\n */\n\nexport * from \"./branch-summarization.ts\";\nexport * from \"./compaction.ts\";\nexport * from \"./compaction-types.js\";\nexport * from \"./compaction-parameters.js\";\nexport * from \"./compaction-boundary.js\";\nexport * from \"./range-planner.js\";\nexport * from \"./range-planner-diagnostics.js\";\nexport * from \"./compaction-runner.js\";\nexport * from \"./deleted-ranges.js\";\nexport * from \"./transcript-serialization.js\";\nexport * from \"./utils.ts\";\n"]}