@sema-ai/core 1.275.1

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 (962) hide show
  1. package/CHANGELOG.md +5433 -0
  2. package/LICENSE +27 -0
  3. package/NOTICE.md +30 -0
  4. package/README.md +1040 -0
  5. package/dist/agents/agent-definition.d.ts +10 -0
  6. package/dist/agents/agent-definition.d.ts.map +1 -0
  7. package/dist/agents/agent-definition.js +18 -0
  8. package/dist/agents/agent-definition.js.map +1 -0
  9. package/dist/agents/builtin-agents.d.ts +69 -0
  10. package/dist/agents/builtin-agents.d.ts.map +1 -0
  11. package/dist/agents/builtin-agents.js +177 -0
  12. package/dist/agents/builtin-agents.js.map +1 -0
  13. package/dist/agents/cascade.d.ts +101 -0
  14. package/dist/agents/cascade.d.ts.map +1 -0
  15. package/dist/agents/cascade.js +189 -0
  16. package/dist/agents/cascade.js.map +1 -0
  17. package/dist/agents/observer.d.ts +209 -0
  18. package/dist/agents/observer.d.ts.map +1 -0
  19. package/dist/agents/observer.js +495 -0
  20. package/dist/agents/observer.js.map +1 -0
  21. package/dist/agents/repair-loop.d.ts +236 -0
  22. package/dist/agents/repair-loop.d.ts.map +1 -0
  23. package/dist/agents/repair-loop.js +293 -0
  24. package/dist/agents/repair-loop.js.map +1 -0
  25. package/dist/agents/session-util.d.ts +8 -0
  26. package/dist/agents/session-util.d.ts.map +1 -0
  27. package/dist/agents/session-util.js +9 -0
  28. package/dist/agents/session-util.js.map +1 -0
  29. package/dist/agents/subagent-steps.d.ts +93 -0
  30. package/dist/agents/subagent-steps.d.ts.map +1 -0
  31. package/dist/agents/subagent-steps.js +206 -0
  32. package/dist/agents/subagent-steps.js.map +1 -0
  33. package/dist/agents/subagent.d.ts +441 -0
  34. package/dist/agents/subagent.d.ts.map +1 -0
  35. package/dist/agents/subagent.js +2492 -0
  36. package/dist/agents/subagent.js.map +1 -0
  37. package/dist/agents/suspend-guard.d.ts +35 -0
  38. package/dist/agents/suspend-guard.d.ts.map +1 -0
  39. package/dist/agents/suspend-guard.js +48 -0
  40. package/dist/agents/suspend-guard.js.map +1 -0
  41. package/dist/agents/teacher.d.ts +137 -0
  42. package/dist/agents/teacher.d.ts.map +1 -0
  43. package/dist/agents/teacher.js +575 -0
  44. package/dist/agents/teacher.js.map +1 -0
  45. package/dist/agents/team.d.ts +211 -0
  46. package/dist/agents/team.d.ts.map +1 -0
  47. package/dist/agents/team.js +293 -0
  48. package/dist/agents/team.js.map +1 -0
  49. package/dist/agents/tool-filter.d.ts +29 -0
  50. package/dist/agents/tool-filter.d.ts.map +1 -0
  51. package/dist/agents/tool-filter.js +50 -0
  52. package/dist/agents/tool-filter.js.map +1 -0
  53. package/dist/agents/verify.d.ts +177 -0
  54. package/dist/agents/verify.d.ts.map +1 -0
  55. package/dist/agents/verify.js +305 -0
  56. package/dist/agents/verify.js.map +1 -0
  57. package/dist/bench/metrics.d.ts +714 -0
  58. package/dist/bench/metrics.d.ts.map +1 -0
  59. package/dist/bench/metrics.js +618 -0
  60. package/dist/bench/metrics.js.map +1 -0
  61. package/dist/bin/sema-tb.d.ts +3 -0
  62. package/dist/bin/sema-tb.d.ts.map +1 -0
  63. package/dist/bin/sema-tb.js +516 -0
  64. package/dist/bin/sema-tb.js.map +1 -0
  65. package/dist/bin/tb-env.d.ts +13 -0
  66. package/dist/bin/tb-env.d.ts.map +1 -0
  67. package/dist/bin/tb-env.js +26 -0
  68. package/dist/bin/tb-env.js.map +1 -0
  69. package/dist/brain/anthropic.d.ts +46 -0
  70. package/dist/brain/anthropic.d.ts.map +1 -0
  71. package/dist/brain/anthropic.js +830 -0
  72. package/dist/brain/anthropic.js.map +1 -0
  73. package/dist/brain/circuit-breaker.d.ts +46 -0
  74. package/dist/brain/circuit-breaker.d.ts.map +1 -0
  75. package/dist/brain/circuit-breaker.js +173 -0
  76. package/dist/brain/circuit-breaker.js.map +1 -0
  77. package/dist/brain/degrading.d.ts +98 -0
  78. package/dist/brain/degrading.d.ts.map +1 -0
  79. package/dist/brain/degrading.js +249 -0
  80. package/dist/brain/degrading.js.map +1 -0
  81. package/dist/brain/errors.d.ts +31 -0
  82. package/dist/brain/errors.d.ts.map +1 -0
  83. package/dist/brain/errors.js +58 -0
  84. package/dist/brain/errors.js.map +1 -0
  85. package/dist/brain/failover.d.ts +18 -0
  86. package/dist/brain/failover.d.ts.map +1 -0
  87. package/dist/brain/failover.js +118 -0
  88. package/dist/brain/failover.js.map +1 -0
  89. package/dist/brain/model-presets.d.ts +36 -0
  90. package/dist/brain/model-presets.d.ts.map +1 -0
  91. package/dist/brain/model-presets.js +54 -0
  92. package/dist/brain/model-presets.js.map +1 -0
  93. package/dist/brain/openai.d.ts +43 -0
  94. package/dist/brain/openai.d.ts.map +1 -0
  95. package/dist/brain/openai.js +784 -0
  96. package/dist/brain/openai.js.map +1 -0
  97. package/dist/brain/reasoning.d.ts +138 -0
  98. package/dist/brain/reasoning.d.ts.map +1 -0
  99. package/dist/brain/reasoning.js +146 -0
  100. package/dist/brain/reasoning.js.map +1 -0
  101. package/dist/brain/repetition.d.ts +60 -0
  102. package/dist/brain/repetition.d.ts.map +1 -0
  103. package/dist/brain/repetition.js +121 -0
  104. package/dist/brain/repetition.js.map +1 -0
  105. package/dist/brain/request-params.d.ts +29 -0
  106. package/dist/brain/request-params.d.ts.map +1 -0
  107. package/dist/brain/request-params.js +78 -0
  108. package/dist/brain/request-params.js.map +1 -0
  109. package/dist/brain/retry.d.ts +18 -0
  110. package/dist/brain/retry.d.ts.map +1 -0
  111. package/dist/brain/retry.js +42 -0
  112. package/dist/brain/retry.js.map +1 -0
  113. package/dist/brain/routing.d.ts +19 -0
  114. package/dist/brain/routing.d.ts.map +1 -0
  115. package/dist/brain/routing.js +44 -0
  116. package/dist/brain/routing.js.map +1 -0
  117. package/dist/brain/status-sink.d.ts +46 -0
  118. package/dist/brain/status-sink.d.ts.map +1 -0
  119. package/dist/brain/status-sink.js +36 -0
  120. package/dist/brain/status-sink.js.map +1 -0
  121. package/dist/brain/stream-engine.d.ts +85 -0
  122. package/dist/brain/stream-engine.d.ts.map +1 -0
  123. package/dist/brain/stream-engine.js +391 -0
  124. package/dist/brain/stream-engine.js.map +1 -0
  125. package/dist/brain/timeout.d.ts +44 -0
  126. package/dist/brain/timeout.d.ts.map +1 -0
  127. package/dist/brain/timeout.js +41 -0
  128. package/dist/brain/timeout.js.map +1 -0
  129. package/dist/brain/tool-call-repair.d.ts +15 -0
  130. package/dist/brain/tool-call-repair.d.ts.map +1 -0
  131. package/dist/brain/tool-call-repair.js +67 -0
  132. package/dist/brain/tool-call-repair.js.map +1 -0
  133. package/dist/brain/walltime.d.ts +14 -0
  134. package/dist/brain/walltime.d.ts.map +1 -0
  135. package/dist/brain/walltime.js +14 -0
  136. package/dist/brain/walltime.js.map +1 -0
  137. package/dist/core/arg-summary.d.ts +19 -0
  138. package/dist/core/arg-summary.d.ts.map +1 -0
  139. package/dist/core/arg-summary.js +96 -0
  140. package/dist/core/arg-summary.js.map +1 -0
  141. package/dist/core/ask-question.d.ts +113 -0
  142. package/dist/core/ask-question.d.ts.map +1 -0
  143. package/dist/core/ask-question.js +246 -0
  144. package/dist/core/ask-question.js.map +1 -0
  145. package/dist/core/auto-compaction.d.ts +341 -0
  146. package/dist/core/auto-compaction.d.ts.map +1 -0
  147. package/dist/core/auto-compaction.js +495 -0
  148. package/dist/core/auto-compaction.js.map +1 -0
  149. package/dist/core/auto-promote.d.ts +126 -0
  150. package/dist/core/auto-promote.d.ts.map +1 -0
  151. package/dist/core/auto-promote.js +171 -0
  152. package/dist/core/auto-promote.js.map +1 -0
  153. package/dist/core/background-shell.d.ts +128 -0
  154. package/dist/core/background-shell.d.ts.map +1 -0
  155. package/dist/core/background-shell.js +42 -0
  156. package/dist/core/background-shell.js.map +1 -0
  157. package/dist/core/cache-break-detector.d.ts +63 -0
  158. package/dist/core/cache-break-detector.d.ts.map +1 -0
  159. package/dist/core/cache-break-detector.js +0 -0
  160. package/dist/core/cache-break-detector.js.map +1 -0
  161. package/dist/core/canonical-json.d.ts +45 -0
  162. package/dist/core/canonical-json.d.ts.map +1 -0
  163. package/dist/core/canonical-json.js +132 -0
  164. package/dist/core/canonical-json.js.map +1 -0
  165. package/dist/core/checkpoint-store.d.ts +1101 -0
  166. package/dist/core/checkpoint-store.d.ts.map +1 -0
  167. package/dist/core/checkpoint-store.js +514 -0
  168. package/dist/core/checkpoint-store.js.map +1 -0
  169. package/dist/core/consolidate-scope.d.ts +94 -0
  170. package/dist/core/consolidate-scope.d.ts.map +1 -0
  171. package/dist/core/consolidate-scope.js +158 -0
  172. package/dist/core/consolidate-scope.js.map +1 -0
  173. package/dist/core/context-edit.d.ts +82 -0
  174. package/dist/core/context-edit.d.ts.map +1 -0
  175. package/dist/core/context-edit.js +149 -0
  176. package/dist/core/context-edit.js.map +1 -0
  177. package/dist/core/context-guard.d.ts +43 -0
  178. package/dist/core/context-guard.d.ts.map +1 -0
  179. package/dist/core/context-guard.js +171 -0
  180. package/dist/core/context-guard.js.map +1 -0
  181. package/dist/core/dynamic-recall.d.ts +100 -0
  182. package/dist/core/dynamic-recall.d.ts.map +1 -0
  183. package/dist/core/dynamic-recall.js +108 -0
  184. package/dist/core/dynamic-recall.js.map +1 -0
  185. package/dist/core/exec-gate.d.ts +74 -0
  186. package/dist/core/exec-gate.d.ts.map +1 -0
  187. package/dist/core/exec-gate.js +143 -0
  188. package/dist/core/exec-gate.js.map +1 -0
  189. package/dist/core/exec-output-tail.d.ts +37 -0
  190. package/dist/core/exec-output-tail.d.ts.map +1 -0
  191. package/dist/core/exec-output-tail.js +63 -0
  192. package/dist/core/exec-output-tail.js.map +1 -0
  193. package/dist/core/file-snapshot-store.d.ts +137 -0
  194. package/dist/core/file-snapshot-store.d.ts.map +1 -0
  195. package/dist/core/file-snapshot-store.js +319 -0
  196. package/dist/core/file-snapshot-store.js.map +1 -0
  197. package/dist/core/git-worktree-env.d.ts +41 -0
  198. package/dist/core/git-worktree-env.d.ts.map +1 -0
  199. package/dist/core/git-worktree-env.js +64 -0
  200. package/dist/core/git-worktree-env.js.map +1 -0
  201. package/dist/core/hooks.d.ts +372 -0
  202. package/dist/core/hooks.d.ts.map +1 -0
  203. package/dist/core/hooks.js +269 -0
  204. package/dist/core/hooks.js.map +1 -0
  205. package/dist/core/lsp-diagnostics.d.ts +74 -0
  206. package/dist/core/lsp-diagnostics.d.ts.map +1 -0
  207. package/dist/core/lsp-diagnostics.js +125 -0
  208. package/dist/core/lsp-diagnostics.js.map +1 -0
  209. package/dist/core/lsp-protocol.d.ts +28 -0
  210. package/dist/core/lsp-protocol.d.ts.map +1 -0
  211. package/dist/core/lsp-protocol.js +179 -0
  212. package/dist/core/lsp-protocol.js.map +1 -0
  213. package/dist/core/lsp-session.d.ts +56 -0
  214. package/dist/core/lsp-session.d.ts.map +1 -0
  215. package/dist/core/lsp-session.js +185 -0
  216. package/dist/core/lsp-session.js.map +1 -0
  217. package/dist/core/lsp.d.ts +132 -0
  218. package/dist/core/lsp.d.ts.map +1 -0
  219. package/dist/core/lsp.js +147 -0
  220. package/dist/core/lsp.js.map +1 -0
  221. package/dist/core/mcp.d.ts +294 -0
  222. package/dist/core/mcp.d.ts.map +1 -0
  223. package/dist/core/mcp.js +992 -0
  224. package/dist/core/mcp.js.map +1 -0
  225. package/dist/core/media-byte-cap.d.ts +34 -0
  226. package/dist/core/media-byte-cap.d.ts.map +1 -0
  227. package/dist/core/media-byte-cap.js +76 -0
  228. package/dist/core/media-byte-cap.js.map +1 -0
  229. package/dist/core/memory-engine/data-plane.d.ts +103 -0
  230. package/dist/core/memory-engine/data-plane.d.ts.map +1 -0
  231. package/dist/core/memory-engine/data-plane.js +272 -0
  232. package/dist/core/memory-engine/data-plane.js.map +1 -0
  233. package/dist/core/memory-engine/dual-root.d.ts +40 -0
  234. package/dist/core/memory-engine/dual-root.d.ts.map +1 -0
  235. package/dist/core/memory-engine/dual-root.js +95 -0
  236. package/dist/core/memory-engine/dual-root.js.map +1 -0
  237. package/dist/core/memory-engine/engine.d.ts +161 -0
  238. package/dist/core/memory-engine/engine.d.ts.map +1 -0
  239. package/dist/core/memory-engine/engine.js +1110 -0
  240. package/dist/core/memory-engine/engine.js.map +1 -0
  241. package/dist/core/memory-engine/file-backend.d.ts +162 -0
  242. package/dist/core/memory-engine/file-backend.d.ts.map +1 -0
  243. package/dist/core/memory-engine/file-backend.js +948 -0
  244. package/dist/core/memory-engine/file-backend.js.map +1 -0
  245. package/dist/core/memory-engine/frontmatter.d.ts +24 -0
  246. package/dist/core/memory-engine/frontmatter.d.ts.map +1 -0
  247. package/dist/core/memory-engine/frontmatter.js +135 -0
  248. package/dist/core/memory-engine/frontmatter.js.map +1 -0
  249. package/dist/core/memory-engine/index.d.ts +13 -0
  250. package/dist/core/memory-engine/index.d.ts.map +1 -0
  251. package/dist/core/memory-engine/index.js +28 -0
  252. package/dist/core/memory-engine/index.js.map +1 -0
  253. package/dist/core/memory-engine/layout.d.ts +123 -0
  254. package/dist/core/memory-engine/layout.d.ts.map +1 -0
  255. package/dist/core/memory-engine/layout.js +643 -0
  256. package/dist/core/memory-engine/layout.js.map +1 -0
  257. package/dist/core/memory-engine/memory-backend-contract.d.ts +22 -0
  258. package/dist/core/memory-engine/memory-backend-contract.d.ts.map +1 -0
  259. package/dist/core/memory-engine/memory-backend-contract.js +271 -0
  260. package/dist/core/memory-engine/memory-backend-contract.js.map +1 -0
  261. package/dist/core/memory-engine/migrate.d.ts +17 -0
  262. package/dist/core/memory-engine/migrate.d.ts.map +1 -0
  263. package/dist/core/memory-engine/migrate.js +35 -0
  264. package/dist/core/memory-engine/migrate.js.map +1 -0
  265. package/dist/core/memory-engine/scan.d.ts +20 -0
  266. package/dist/core/memory-engine/scan.d.ts.map +1 -0
  267. package/dist/core/memory-engine/scan.js +84 -0
  268. package/dist/core/memory-engine/scan.js.map +1 -0
  269. package/dist/core/memory-engine/scope-contract.d.ts +104 -0
  270. package/dist/core/memory-engine/scope-contract.d.ts.map +1 -0
  271. package/dist/core/memory-engine/scope-contract.js +288 -0
  272. package/dist/core/memory-engine/scope-contract.js.map +1 -0
  273. package/dist/core/memory-engine/sync-client.d.ts +100 -0
  274. package/dist/core/memory-engine/sync-client.d.ts.map +1 -0
  275. package/dist/core/memory-engine/sync-client.js +328 -0
  276. package/dist/core/memory-engine/sync-client.js.map +1 -0
  277. package/dist/core/memory-engine/sync.d.ts +97 -0
  278. package/dist/core/memory-engine/sync.d.ts.map +1 -0
  279. package/dist/core/memory-engine/sync.js +91 -0
  280. package/dist/core/memory-engine/sync.js.map +1 -0
  281. package/dist/core/memory-engine/types.d.ts +279 -0
  282. package/dist/core/memory-engine/types.d.ts.map +1 -0
  283. package/dist/core/memory-engine/types.js +9 -0
  284. package/dist/core/memory-engine/types.js.map +1 -0
  285. package/dist/core/memory-recall.d.ts +261 -0
  286. package/dist/core/memory-recall.d.ts.map +1 -0
  287. package/dist/core/memory-recall.js +600 -0
  288. package/dist/core/memory-recall.js.map +1 -0
  289. package/dist/core/memory-vector.d.ts +24 -0
  290. package/dist/core/memory-vector.d.ts.map +1 -0
  291. package/dist/core/memory-vector.js +51 -0
  292. package/dist/core/memory-vector.js.map +1 -0
  293. package/dist/core/memory.d.ts +502 -0
  294. package/dist/core/memory.d.ts.map +1 -0
  295. package/dist/core/memory.js +881 -0
  296. package/dist/core/memory.js.map +1 -0
  297. package/dist/core/message-utils.d.ts +7 -0
  298. package/dist/core/message-utils.d.ts.map +1 -0
  299. package/dist/core/message-utils.js +10 -0
  300. package/dist/core/message-utils.js.map +1 -0
  301. package/dist/core/oracle-isolation.d.ts +85 -0
  302. package/dist/core/oracle-isolation.d.ts.map +1 -0
  303. package/dist/core/oracle-isolation.js +121 -0
  304. package/dist/core/oracle-isolation.js.map +1 -0
  305. package/dist/core/permission-rules.d.ts +102 -0
  306. package/dist/core/permission-rules.d.ts.map +1 -0
  307. package/dist/core/permission-rules.js +357 -0
  308. package/dist/core/permission-rules.js.map +1 -0
  309. package/dist/core/present-plan-tool.d.ts +28 -0
  310. package/dist/core/present-plan-tool.d.ts.map +1 -0
  311. package/dist/core/present-plan-tool.js +119 -0
  312. package/dist/core/present-plan-tool.js.map +1 -0
  313. package/dist/core/pricing.d.ts +48 -0
  314. package/dist/core/pricing.d.ts.map +1 -0
  315. package/dist/core/pricing.js +46 -0
  316. package/dist/core/pricing.js.map +1 -0
  317. package/dist/core/property-harness.d.ts +126 -0
  318. package/dist/core/property-harness.d.ts.map +1 -0
  319. package/dist/core/property-harness.js +192 -0
  320. package/dist/core/property-harness.js.map +1 -0
  321. package/dist/core/push-queue.d.ts +10 -0
  322. package/dist/core/push-queue.d.ts.map +1 -0
  323. package/dist/core/push-queue.js +42 -0
  324. package/dist/core/push-queue.js.map +1 -0
  325. package/dist/core/remote-env.d.ts +432 -0
  326. package/dist/core/remote-env.d.ts.map +1 -0
  327. package/dist/core/remote-env.js +77 -0
  328. package/dist/core/remote-env.js.map +1 -0
  329. package/dist/core/roles.d.ts +74 -0
  330. package/dist/core/roles.d.ts.map +1 -0
  331. package/dist/core/roles.js +272 -0
  332. package/dist/core/roles.js.map +1 -0
  333. package/dist/core/runner/active-skill-scope.d.ts +64 -0
  334. package/dist/core/runner/active-skill-scope.d.ts.map +1 -0
  335. package/dist/core/runner/active-skill-scope.js +197 -0
  336. package/dist/core/runner/active-skill-scope.js.map +1 -0
  337. package/dist/core/runner/assemble-result.d.ts +191 -0
  338. package/dist/core/runner/assemble-result.d.ts.map +1 -0
  339. package/dist/core/runner/assemble-result.js +250 -0
  340. package/dist/core/runner/assemble-result.js.map +1 -0
  341. package/dist/core/runner/call-cap.d.ts +130 -0
  342. package/dist/core/runner/call-cap.d.ts.map +1 -0
  343. package/dist/core/runner/call-cap.js +151 -0
  344. package/dist/core/runner/call-cap.js.map +1 -0
  345. package/dist/core/runner/grounding-signal.d.ts +12 -0
  346. package/dist/core/runner/grounding-signal.d.ts.map +1 -0
  347. package/dist/core/runner/grounding-signal.js +94 -0
  348. package/dist/core/runner/grounding-signal.js.map +1 -0
  349. package/dist/core/runner/image.d.ts +23 -0
  350. package/dist/core/runner/image.d.ts.map +1 -0
  351. package/dist/core/runner/image.js +151 -0
  352. package/dist/core/runner/image.js.map +1 -0
  353. package/dist/core/runner/memory-consolidation.d.ts +112 -0
  354. package/dist/core/runner/memory-consolidation.d.ts.map +1 -0
  355. package/dist/core/runner/memory-consolidation.js +372 -0
  356. package/dist/core/runner/memory-consolidation.js.map +1 -0
  357. package/dist/core/runner/prepare-task.d.ts +583 -0
  358. package/dist/core/runner/prepare-task.d.ts.map +1 -0
  359. package/dist/core/runner/prepare-task.js +3612 -0
  360. package/dist/core/runner/prepare-task.js.map +1 -0
  361. package/dist/core/runner/prompt-suggestions.d.ts +33 -0
  362. package/dist/core/runner/prompt-suggestions.d.ts.map +1 -0
  363. package/dist/core/runner/prompt-suggestions.js +116 -0
  364. package/dist/core/runner/prompt-suggestions.js.map +1 -0
  365. package/dist/core/runner/runtask.d.ts +274 -0
  366. package/dist/core/runner/runtask.d.ts.map +1 -0
  367. package/dist/core/runner/runtask.js +4606 -0
  368. package/dist/core/runner/runtask.js.map +1 -0
  369. package/dist/core/runner/session-rule-policy.d.ts +28 -0
  370. package/dist/core/runner/session-rule-policy.d.ts.map +1 -0
  371. package/dist/core/runner/session-rule-policy.js +110 -0
  372. package/dist/core/runner/session-rule-policy.js.map +1 -0
  373. package/dist/core/runner/strict-output-schema.d.ts +36 -0
  374. package/dist/core/runner/strict-output-schema.d.ts.map +1 -0
  375. package/dist/core/runner/strict-output-schema.js +365 -0
  376. package/dist/core/runner/strict-output-schema.js.map +1 -0
  377. package/dist/core/runner/synthetic-tools.d.ts +72 -0
  378. package/dist/core/runner/synthetic-tools.d.ts.map +1 -0
  379. package/dist/core/runner/synthetic-tools.js +203 -0
  380. package/dist/core/runner/synthetic-tools.js.map +1 -0
  381. package/dist/core/runner/tool-disclosure.d.ts +117 -0
  382. package/dist/core/runner/tool-disclosure.d.ts.map +1 -0
  383. package/dist/core/runner/tool-disclosure.js +0 -0
  384. package/dist/core/runner/tool-disclosure.js.map +1 -0
  385. package/dist/core/runner/turn-attachments.d.ts +381 -0
  386. package/dist/core/runner/turn-attachments.d.ts.map +1 -0
  387. package/dist/core/runner/turn-attachments.js +596 -0
  388. package/dist/core/runner/turn-attachments.js.map +1 -0
  389. package/dist/core/runner/usage-accounting.d.ts +35 -0
  390. package/dist/core/runner/usage-accounting.d.ts.map +1 -0
  391. package/dist/core/runner/usage-accounting.js +45 -0
  392. package/dist/core/runner/usage-accounting.js.map +1 -0
  393. package/dist/core/runtime.d.ts +9 -0
  394. package/dist/core/runtime.d.ts.map +1 -0
  395. package/dist/core/runtime.js +17 -0
  396. package/dist/core/runtime.js.map +1 -0
  397. package/dist/core/safety-axis-vocab.d.ts +33 -0
  398. package/dist/core/safety-axis-vocab.d.ts.map +1 -0
  399. package/dist/core/safety-axis-vocab.js +35 -0
  400. package/dist/core/safety-axis-vocab.js.map +1 -0
  401. package/dist/core/safety-merge-corpus.d.ts +48 -0
  402. package/dist/core/safety-merge-corpus.d.ts.map +1 -0
  403. package/dist/core/safety-merge-corpus.js +203 -0
  404. package/dist/core/safety-merge-corpus.js.map +1 -0
  405. package/dist/core/scheduler.d.ts +126 -0
  406. package/dist/core/scheduler.d.ts.map +1 -0
  407. package/dist/core/scheduler.js +54 -0
  408. package/dist/core/scheduler.js.map +1 -0
  409. package/dist/core/secret-env.d.ts +23 -0
  410. package/dist/core/secret-env.d.ts.map +1 -0
  411. package/dist/core/secret-env.js +35 -0
  412. package/dist/core/secret-env.js.map +1 -0
  413. package/dist/core/select-model.d.ts +26 -0
  414. package/dist/core/select-model.d.ts.map +1 -0
  415. package/dist/core/select-model.js +58 -0
  416. package/dist/core/select-model.js.map +1 -0
  417. package/dist/core/sensitive-path-policy.d.ts +24 -0
  418. package/dist/core/sensitive-path-policy.d.ts.map +1 -0
  419. package/dist/core/sensitive-path-policy.js +96 -0
  420. package/dist/core/sensitive-path-policy.js.map +1 -0
  421. package/dist/core/session-policy-store.d.ts +102 -0
  422. package/dist/core/session-policy-store.d.ts.map +1 -0
  423. package/dist/core/session-policy-store.js +177 -0
  424. package/dist/core/session-policy-store.js.map +1 -0
  425. package/dist/core/session-reconcile.d.ts +63 -0
  426. package/dist/core/session-reconcile.d.ts.map +1 -0
  427. package/dist/core/session-reconcile.js +71 -0
  428. package/dist/core/session-reconcile.js.map +1 -0
  429. package/dist/core/session-store.d.ts +99 -0
  430. package/dist/core/session-store.d.ts.map +1 -0
  431. package/dist/core/session-store.js +298 -0
  432. package/dist/core/session-store.js.map +1 -0
  433. package/dist/core/session.d.ts +144 -0
  434. package/dist/core/session.d.ts.map +1 -0
  435. package/dist/core/session.js +56 -0
  436. package/dist/core/session.js.map +1 -0
  437. package/dist/core/spec-contract.d.ts +147 -0
  438. package/dist/core/spec-contract.d.ts.map +1 -0
  439. package/dist/core/spec-contract.js +340 -0
  440. package/dist/core/spec-contract.js.map +1 -0
  441. package/dist/core/strategy-store.d.ts +50 -0
  442. package/dist/core/strategy-store.d.ts.map +1 -0
  443. package/dist/core/strategy-store.js +100 -0
  444. package/dist/core/strategy-store.js.map +1 -0
  445. package/dist/core/stub-env.d.ts +35 -0
  446. package/dist/core/stub-env.d.ts.map +1 -0
  447. package/dist/core/stub-env.js +69 -0
  448. package/dist/core/stub-env.js.map +1 -0
  449. package/dist/core/task-notification.d.ts +115 -0
  450. package/dist/core/task-notification.d.ts.map +1 -0
  451. package/dist/core/task-notification.js +247 -0
  452. package/dist/core/task-notification.js.map +1 -0
  453. package/dist/core/task-outcome.d.ts +80 -0
  454. package/dist/core/task-outcome.d.ts.map +1 -0
  455. package/dist/core/task-outcome.js +40 -0
  456. package/dist/core/task-outcome.js.map +1 -0
  457. package/dist/core/task-registry.d.ts +349 -0
  458. package/dist/core/task-registry.d.ts.map +1 -0
  459. package/dist/core/task-registry.js +1751 -0
  460. package/dist/core/task-registry.js.map +1 -0
  461. package/dist/core/tighten-task-spec.d.ts +27 -0
  462. package/dist/core/tighten-task-spec.d.ts.map +1 -0
  463. package/dist/core/tighten-task-spec.js +95 -0
  464. package/dist/core/tighten-task-spec.js.map +1 -0
  465. package/dist/core/tool-detach.d.ts +31 -0
  466. package/dist/core/tool-detach.d.ts.map +1 -0
  467. package/dist/core/tool-detach.js +62 -0
  468. package/dist/core/tool-detach.js.map +1 -0
  469. package/dist/core/tool-errors.d.ts +72 -0
  470. package/dist/core/tool-errors.d.ts.map +1 -0
  471. package/dist/core/tool-errors.js +194 -0
  472. package/dist/core/tool-errors.js.map +1 -0
  473. package/dist/core/tool-name-aliases.d.ts +5 -0
  474. package/dist/core/tool-name-aliases.d.ts.map +1 -0
  475. package/dist/core/tool-name-aliases.js +130 -0
  476. package/dist/core/tool-name-aliases.js.map +1 -0
  477. package/dist/core/tool-policy.d.ts +295 -0
  478. package/dist/core/tool-policy.d.ts.map +1 -0
  479. package/dist/core/tool-policy.js +567 -0
  480. package/dist/core/tool-policy.js.map +1 -0
  481. package/dist/core/tool-result-budget.d.ts +44 -0
  482. package/dist/core/tool-result-budget.d.ts.map +1 -0
  483. package/dist/core/tool-result-budget.js +140 -0
  484. package/dist/core/tool-result-budget.js.map +1 -0
  485. package/dist/core/tool-result-store.d.ts +136 -0
  486. package/dist/core/tool-result-store.d.ts.map +1 -0
  487. package/dist/core/tool-result-store.js +219 -0
  488. package/dist/core/tool-result-store.js.map +1 -0
  489. package/dist/core/tools.d.ts +14 -0
  490. package/dist/core/tools.d.ts.map +1 -0
  491. package/dist/core/tools.js +98 -0
  492. package/dist/core/tools.js.map +1 -0
  493. package/dist/core/trace.d.ts +340 -0
  494. package/dist/core/trace.d.ts.map +1 -0
  495. package/dist/core/trace.js +12 -0
  496. package/dist/core/trace.js.map +1 -0
  497. package/dist/core/types.d.ts +2828 -0
  498. package/dist/core/types.d.ts.map +1 -0
  499. package/dist/core/types.js +2 -0
  500. package/dist/core/types.js.map +1 -0
  501. package/dist/core/untrusted-egress.d.ts +32 -0
  502. package/dist/core/untrusted-egress.d.ts.map +1 -0
  503. package/dist/core/untrusted-egress.js +49 -0
  504. package/dist/core/untrusted-egress.js.map +1 -0
  505. package/dist/core/untrusted-text.d.ts +64 -0
  506. package/dist/core/untrusted-text.d.ts.map +1 -0
  507. package/dist/core/untrusted-text.js +119 -0
  508. package/dist/core/untrusted-text.js.map +1 -0
  509. package/dist/core/warm-resume.d.ts +23 -0
  510. package/dist/core/warm-resume.d.ts.map +1 -0
  511. package/dist/core/warm-resume.js +28 -0
  512. package/dist/core/warm-resume.js.map +1 -0
  513. package/dist/core/with-retry.d.ts +43 -0
  514. package/dist/core/with-retry.d.ts.map +1 -0
  515. package/dist/core/with-retry.js +59 -0
  516. package/dist/core/with-retry.js.map +1 -0
  517. package/dist/core/workflow-journal-store.d.ts +44 -0
  518. package/dist/core/workflow-journal-store.d.ts.map +1 -0
  519. package/dist/core/workflow-journal-store.js +47 -0
  520. package/dist/core/workflow-journal-store.js.map +1 -0
  521. package/dist/core/workflow-run-store-contract.d.ts +31 -0
  522. package/dist/core/workflow-run-store-contract.d.ts.map +1 -0
  523. package/dist/core/workflow-run-store-contract.js +191 -0
  524. package/dist/core/workflow-run-store-contract.js.map +1 -0
  525. package/dist/core/workflow-run-store.d.ts +149 -0
  526. package/dist/core/workflow-run-store.d.ts.map +1 -0
  527. package/dist/core/workflow-run-store.js +110 -0
  528. package/dist/core/workflow-run-store.js.map +1 -0
  529. package/dist/engine/compaction/compaction.d.ts +139 -0
  530. package/dist/engine/compaction/compaction.d.ts.map +1 -0
  531. package/dist/engine/compaction/compaction.js +1030 -0
  532. package/dist/engine/compaction/compaction.js.map +1 -0
  533. package/dist/engine/compaction/utils.d.ts +45 -0
  534. package/dist/engine/compaction/utils.d.ts.map +1 -0
  535. package/dist/engine/compaction/utils.js +203 -0
  536. package/dist/engine/compaction/utils.js.map +1 -0
  537. package/dist/engine/execution-env/kill-tree.d.ts +20 -0
  538. package/dist/engine/execution-env/kill-tree.d.ts.map +1 -0
  539. package/dist/engine/execution-env/kill-tree.js +183 -0
  540. package/dist/engine/execution-env/kill-tree.js.map +1 -0
  541. package/dist/engine/execution-env/node-execution-env.d.ts +133 -0
  542. package/dist/engine/execution-env/node-execution-env.d.ts.map +1 -0
  543. package/dist/engine/execution-env/node-execution-env.js +1031 -0
  544. package/dist/engine/execution-env/node-execution-env.js.map +1 -0
  545. package/dist/engine/harness/agent-harness.d.ts +174 -0
  546. package/dist/engine/harness/agent-harness.d.ts.map +1 -0
  547. package/dist/engine/harness/agent-harness.js +1053 -0
  548. package/dist/engine/harness/agent-harness.js.map +1 -0
  549. package/dist/engine/harness/messages.d.ts +17 -0
  550. package/dist/engine/harness/messages.d.ts.map +1 -0
  551. package/dist/engine/harness/messages.js +122 -0
  552. package/dist/engine/harness/messages.js.map +1 -0
  553. package/dist/engine/harness/types.d.ts +713 -0
  554. package/dist/engine/harness/types.d.ts.map +1 -0
  555. package/dist/engine/harness/types.js +100 -0
  556. package/dist/engine/harness/types.js.map +1 -0
  557. package/dist/engine/llm/diagnostics.d.ts +23 -0
  558. package/dist/engine/llm/diagnostics.d.ts.map +1 -0
  559. package/dist/engine/llm/diagnostics.js +32 -0
  560. package/dist/engine/llm/diagnostics.js.map +1 -0
  561. package/dist/engine/llm/event-stream.d.ts +25 -0
  562. package/dist/engine/llm/event-stream.d.ts.map +1 -0
  563. package/dist/engine/llm/event-stream.js +103 -0
  564. package/dist/engine/llm/event-stream.js.map +1 -0
  565. package/dist/engine/llm/index.d.ts +12 -0
  566. package/dist/engine/llm/index.d.ts.map +1 -0
  567. package/dist/engine/llm/index.js +12 -0
  568. package/dist/engine/llm/index.js.map +1 -0
  569. package/dist/engine/llm/types.d.ts +753 -0
  570. package/dist/engine/llm/types.d.ts.map +1 -0
  571. package/dist/engine/llm/types.js +2 -0
  572. package/dist/engine/llm/types.js.map +1 -0
  573. package/dist/engine/llm/validation.d.ts +8 -0
  574. package/dist/engine/llm/validation.d.ts.map +1 -0
  575. package/dist/engine/llm/validation.js +318 -0
  576. package/dist/engine/llm/validation.js.map +1 -0
  577. package/dist/engine/loop/agent-loop.d.ts +74 -0
  578. package/dist/engine/loop/agent-loop.d.ts.map +1 -0
  579. package/dist/engine/loop/agent-loop.js +1490 -0
  580. package/dist/engine/loop/agent-loop.js.map +1 -0
  581. package/dist/engine/loop/runtime-deps.d.ts +17 -0
  582. package/dist/engine/loop/runtime-deps.d.ts.map +1 -0
  583. package/dist/engine/loop/runtime-deps.js +21 -0
  584. package/dist/engine/loop/runtime-deps.js.map +1 -0
  585. package/dist/engine/loop/types.d.ts +609 -0
  586. package/dist/engine/loop/types.d.ts.map +1 -0
  587. package/dist/engine/loop/types.js +2 -0
  588. package/dist/engine/loop/types.js.map +1 -0
  589. package/dist/engine/lsp/frame-decoder.d.ts +16 -0
  590. package/dist/engine/lsp/frame-decoder.d.ts.map +1 -0
  591. package/dist/engine/lsp/frame-decoder.js +53 -0
  592. package/dist/engine/lsp/frame-decoder.js.map +1 -0
  593. package/dist/engine/lsp/node-lsp-manager.d.ts +105 -0
  594. package/dist/engine/lsp/node-lsp-manager.d.ts.map +1 -0
  595. package/dist/engine/lsp/node-lsp-manager.js +343 -0
  596. package/dist/engine/lsp/node-lsp-manager.js.map +1 -0
  597. package/dist/engine/lsp/stdio-lsp-transport.d.ts +37 -0
  598. package/dist/engine/lsp/stdio-lsp-transport.d.ts.map +1 -0
  599. package/dist/engine/lsp/stdio-lsp-transport.js +185 -0
  600. package/dist/engine/lsp/stdio-lsp-transport.js.map +1 -0
  601. package/dist/engine/session/import-validate.d.ts +44 -0
  602. package/dist/engine/session/import-validate.d.ts.map +1 -0
  603. package/dist/engine/session/import-validate.js +92 -0
  604. package/dist/engine/session/import-validate.js.map +1 -0
  605. package/dist/engine/session/memory-repo.d.ts +25 -0
  606. package/dist/engine/session/memory-repo.d.ts.map +1 -0
  607. package/dist/engine/session/memory-repo.js +59 -0
  608. package/dist/engine/session/memory-repo.js.map +1 -0
  609. package/dist/engine/session/memory-storage.d.ts +14 -0
  610. package/dist/engine/session/memory-storage.d.ts.map +1 -0
  611. package/dist/engine/session/memory-storage.js +17 -0
  612. package/dist/engine/session/memory-storage.js.map +1 -0
  613. package/dist/engine/session/repo-utils.d.ts +11 -0
  614. package/dist/engine/session/repo-utils.d.ts.map +1 -0
  615. package/dist/engine/session/repo-utils.js +40 -0
  616. package/dist/engine/session/repo-utils.js.map +1 -0
  617. package/dist/engine/session/session.d.ts +34 -0
  618. package/dist/engine/session/session.d.ts.map +1 -0
  619. package/dist/engine/session/session.js +227 -0
  620. package/dist/engine/session/session.js.map +1 -0
  621. package/dist/engine/session/storage-base.d.ts +38 -0
  622. package/dist/engine/session/storage-base.d.ts.map +1 -0
  623. package/dist/engine/session/storage-base.js +157 -0
  624. package/dist/engine/session/storage-base.js.map +1 -0
  625. package/dist/engine/session/timestamps.d.ts +3 -0
  626. package/dist/engine/session/timestamps.d.ts.map +1 -0
  627. package/dist/engine/session/timestamps.js +15 -0
  628. package/dist/engine/session/timestamps.js.map +1 -0
  629. package/dist/engine/session/uuid.d.ts +2 -0
  630. package/dist/engine/session/uuid.d.ts.map +1 -0
  631. package/dist/engine/session/uuid.js +50 -0
  632. package/dist/engine/session/uuid.js.map +1 -0
  633. package/dist/index.d.ts +160 -0
  634. package/dist/index.d.ts.map +1 -0
  635. package/dist/index.js +374 -0
  636. package/dist/index.js.map +1 -0
  637. package/dist/internal/harness.d.ts +26 -0
  638. package/dist/internal/harness.d.ts.map +1 -0
  639. package/dist/internal/harness.js +24 -0
  640. package/dist/internal/harness.js.map +1 -0
  641. package/dist/internal/llm.d.ts +9 -0
  642. package/dist/internal/llm.d.ts.map +1 -0
  643. package/dist/internal/llm.js +8 -0
  644. package/dist/internal/llm.js.map +1 -0
  645. package/dist/orchestration/builtin-workflows.d.ts +44 -0
  646. package/dist/orchestration/builtin-workflows.d.ts.map +1 -0
  647. package/dist/orchestration/builtin-workflows.js +165 -0
  648. package/dist/orchestration/builtin-workflows.js.map +1 -0
  649. package/dist/orchestration/dev-vm-script-runner.d.ts +24 -0
  650. package/dist/orchestration/dev-vm-script-runner.d.ts.map +1 -0
  651. package/dist/orchestration/dev-vm-script-runner.js +106 -0
  652. package/dist/orchestration/dev-vm-script-runner.js.map +1 -0
  653. package/dist/orchestration/goal.d.ts +97 -0
  654. package/dist/orchestration/goal.d.ts.map +1 -0
  655. package/dist/orchestration/goal.js +248 -0
  656. package/dist/orchestration/goal.js.map +1 -0
  657. package/dist/orchestration/run-spec.d.ts +63 -0
  658. package/dist/orchestration/run-spec.d.ts.map +1 -0
  659. package/dist/orchestration/run-spec.js +274 -0
  660. package/dist/orchestration/run-spec.js.map +1 -0
  661. package/dist/orchestration/run-workflow-tool.d.ts +187 -0
  662. package/dist/orchestration/run-workflow-tool.d.ts.map +1 -0
  663. package/dist/orchestration/run-workflow-tool.js +612 -0
  664. package/dist/orchestration/run-workflow-tool.js.map +1 -0
  665. package/dist/orchestration/workflow-governance.d.ts +70 -0
  666. package/dist/orchestration/workflow-governance.d.ts.map +1 -0
  667. package/dist/orchestration/workflow-governance.js +176 -0
  668. package/dist/orchestration/workflow-governance.js.map +1 -0
  669. package/dist/orchestration/workflow-meta.d.ts +41 -0
  670. package/dist/orchestration/workflow-meta.d.ts.map +1 -0
  671. package/dist/orchestration/workflow-meta.js +426 -0
  672. package/dist/orchestration/workflow-meta.js.map +1 -0
  673. package/dist/orchestration/workflow-observe.d.ts +77 -0
  674. package/dist/orchestration/workflow-observe.d.ts.map +1 -0
  675. package/dist/orchestration/workflow-observe.js +177 -0
  676. package/dist/orchestration/workflow-observe.js.map +1 -0
  677. package/dist/orchestration/workflow-primitives.d.ts +31 -0
  678. package/dist/orchestration/workflow-primitives.d.ts.map +1 -0
  679. package/dist/orchestration/workflow-primitives.js +104 -0
  680. package/dist/orchestration/workflow-primitives.js.map +1 -0
  681. package/dist/orchestration/workflow-sandbox-conformance.d.ts +34 -0
  682. package/dist/orchestration/workflow-sandbox-conformance.d.ts.map +1 -0
  683. package/dist/orchestration/workflow-sandbox-conformance.js +301 -0
  684. package/dist/orchestration/workflow-sandbox-conformance.js.map +1 -0
  685. package/dist/orchestration/workflow-script-runner.d.ts +127 -0
  686. package/dist/orchestration/workflow-script-runner.d.ts.map +1 -0
  687. package/dist/orchestration/workflow-script-runner.js +48 -0
  688. package/dist/orchestration/workflow-script-runner.js.map +1 -0
  689. package/dist/orchestration/workflow-script-store.d.ts +99 -0
  690. package/dist/orchestration/workflow-script-store.d.ts.map +1 -0
  691. package/dist/orchestration/workflow-script-store.js +133 -0
  692. package/dist/orchestration/workflow-script-store.js.map +1 -0
  693. package/dist/orchestration/workflow-size-guideline.d.ts +50 -0
  694. package/dist/orchestration/workflow-size-guideline.d.ts.map +1 -0
  695. package/dist/orchestration/workflow-size-guideline.js +78 -0
  696. package/dist/orchestration/workflow-size-guideline.js.map +1 -0
  697. package/dist/orchestration/workflow.d.ts +624 -0
  698. package/dist/orchestration/workflow.d.ts.map +1 -0
  699. package/dist/orchestration/workflow.js +1596 -0
  700. package/dist/orchestration/workflow.js.map +1 -0
  701. package/dist/prompts/default.d.ts +474 -0
  702. package/dist/prompts/default.d.ts.map +1 -0
  703. package/dist/prompts/default.js +676 -0
  704. package/dist/prompts/default.js.map +1 -0
  705. package/dist/prompts/supervisor.d.ts +60 -0
  706. package/dist/prompts/supervisor.d.ts.map +1 -0
  707. package/dist/prompts/supervisor.js +162 -0
  708. package/dist/prompts/supervisor.js.map +1 -0
  709. package/dist/scenarios/env.d.ts +41 -0
  710. package/dist/scenarios/env.d.ts.map +1 -0
  711. package/dist/scenarios/env.js +65 -0
  712. package/dist/scenarios/env.js.map +1 -0
  713. package/dist/scenarios/full-body.d.ts +47 -0
  714. package/dist/scenarios/full-body.d.ts.map +1 -0
  715. package/dist/scenarios/full-body.js +36 -0
  716. package/dist/scenarios/full-body.js.map +1 -0
  717. package/dist/scenarios/scenario-registry.d.ts +107 -0
  718. package/dist/scenarios/scenario-registry.d.ts.map +1 -0
  719. package/dist/scenarios/scenario-registry.js +192 -0
  720. package/dist/scenarios/scenario-registry.js.map +1 -0
  721. package/dist/scenarios/teacher-quickstart.d.ts +41 -0
  722. package/dist/scenarios/teacher-quickstart.d.ts.map +1 -0
  723. package/dist/scenarios/teacher-quickstart.js +32 -0
  724. package/dist/scenarios/teacher-quickstart.js.map +1 -0
  725. package/dist/server/http.d.ts +36 -0
  726. package/dist/server/http.d.ts.map +1 -0
  727. package/dist/server/http.js +144 -0
  728. package/dist/server/http.js.map +1 -0
  729. package/dist/stores/file/checkpoint-store.d.ts +62 -0
  730. package/dist/stores/file/checkpoint-store.d.ts.map +1 -0
  731. package/dist/stores/file/checkpoint-store.js +250 -0
  732. package/dist/stores/file/checkpoint-store.js.map +1 -0
  733. package/dist/stores/file/file-snapshot-store.d.ts +43 -0
  734. package/dist/stores/file/file-snapshot-store.d.ts.map +1 -0
  735. package/dist/stores/file/file-snapshot-store.js +374 -0
  736. package/dist/stores/file/file-snapshot-store.js.map +1 -0
  737. package/dist/stores/file/fs-atomic.d.ts +95 -0
  738. package/dist/stores/file/fs-atomic.d.ts.map +1 -0
  739. package/dist/stores/file/fs-atomic.js +415 -0
  740. package/dist/stores/file/fs-atomic.js.map +1 -0
  741. package/dist/stores/file/index.d.ts +98 -0
  742. package/dist/stores/file/index.d.ts.map +1 -0
  743. package/dist/stores/file/index.js +109 -0
  744. package/dist/stores/file/index.js.map +1 -0
  745. package/dist/stores/file/memory-store.d.ts +95 -0
  746. package/dist/stores/file/memory-store.d.ts.map +1 -0
  747. package/dist/stores/file/memory-store.js +393 -0
  748. package/dist/stores/file/memory-store.js.map +1 -0
  749. package/dist/stores/file/session-policy-store.d.ts +24 -0
  750. package/dist/stores/file/session-policy-store.d.ts.map +1 -0
  751. package/dist/stores/file/session-policy-store.js +123 -0
  752. package/dist/stores/file/session-policy-store.js.map +1 -0
  753. package/dist/stores/file/session-store.d.ts +34 -0
  754. package/dist/stores/file/session-store.d.ts.map +1 -0
  755. package/dist/stores/file/session-store.js +175 -0
  756. package/dist/stores/file/session-store.js.map +1 -0
  757. package/dist/stores/file/tool-result-store.d.ts +23 -0
  758. package/dist/stores/file/tool-result-store.d.ts.map +1 -0
  759. package/dist/stores/file/tool-result-store.js +61 -0
  760. package/dist/stores/file/tool-result-store.js.map +1 -0
  761. package/dist/stores/file/workflow-journal-store.d.ts +36 -0
  762. package/dist/stores/file/workflow-journal-store.d.ts.map +1 -0
  763. package/dist/stores/file/workflow-journal-store.js +157 -0
  764. package/dist/stores/file/workflow-journal-store.js.map +1 -0
  765. package/dist/stores/file/workflow-run-store.d.ts +58 -0
  766. package/dist/stores/file/workflow-run-store.d.ts.map +1 -0
  767. package/dist/stores/file/workflow-run-store.js +178 -0
  768. package/dist/stores/file/workflow-run-store.js.map +1 -0
  769. package/dist/stores/pg.d.ts +210 -0
  770. package/dist/stores/pg.d.ts.map +1 -0
  771. package/dist/stores/pg.js +652 -0
  772. package/dist/stores/pg.js.map +1 -0
  773. package/dist/tools/fs/encoding.d.ts +51 -0
  774. package/dist/tools/fs/encoding.d.ts.map +1 -0
  775. package/dist/tools/fs/encoding.js +74 -0
  776. package/dist/tools/fs/encoding.js.map +1 -0
  777. package/dist/tools/fs/gh-rate-limit.d.ts +19 -0
  778. package/dist/tools/fs/gh-rate-limit.d.ts.map +1 -0
  779. package/dist/tools/fs/gh-rate-limit.js +35 -0
  780. package/dist/tools/fs/gh-rate-limit.js.map +1 -0
  781. package/dist/tools/fs/index.d.ts +246 -0
  782. package/dist/tools/fs/index.d.ts.map +1 -0
  783. package/dist/tools/fs/index.js +2130 -0
  784. package/dist/tools/fs/index.js.map +1 -0
  785. package/dist/tools/fs/pdf.d.ts +106 -0
  786. package/dist/tools/fs/pdf.d.ts.map +1 -0
  787. package/dist/tools/fs/pdf.js +178 -0
  788. package/dist/tools/fs/pdf.js.map +1 -0
  789. package/dist/tools/fs/repo-map.d.ts +15 -0
  790. package/dist/tools/fs/repo-map.d.ts.map +1 -0
  791. package/dist/tools/fs/repo-map.js +251 -0
  792. package/dist/tools/fs/repo-map.js.map +1 -0
  793. package/dist/tools/fs/safety.d.ts +168 -0
  794. package/dist/tools/fs/safety.d.ts.map +1 -0
  795. package/dist/tools/fs/safety.js +479 -0
  796. package/dist/tools/fs/safety.js.map +1 -0
  797. package/dist/tools/fs/search.d.ts +118 -0
  798. package/dist/tools/fs/search.d.ts.map +1 -0
  799. package/dist/tools/fs/search.js +650 -0
  800. package/dist/tools/fs/search.js.map +1 -0
  801. package/dist/tools/gitea-issue.d.ts +39 -0
  802. package/dist/tools/gitea-issue.d.ts.map +1 -0
  803. package/dist/tools/gitea-issue.js +91 -0
  804. package/dist/tools/gitea-issue.js.map +1 -0
  805. package/dist/tools/monitor.d.ts +64 -0
  806. package/dist/tools/monitor.d.ts.map +1 -0
  807. package/dist/tools/monitor.js +135 -0
  808. package/dist/tools/monitor.js.map +1 -0
  809. package/dist/tools/scheduler-tools.d.ts +48 -0
  810. package/dist/tools/scheduler-tools.d.ts.map +1 -0
  811. package/dist/tools/scheduler-tools.js +449 -0
  812. package/dist/tools/scheduler-tools.js.map +1 -0
  813. package/dist/tools/sql-adapters.d.ts +32 -0
  814. package/dist/tools/sql-adapters.d.ts.map +1 -0
  815. package/dist/tools/sql-adapters.js +31 -0
  816. package/dist/tools/sql-adapters.js.map +1 -0
  817. package/dist/tools/sql.d.ts +36 -0
  818. package/dist/tools/sql.d.ts.map +1 -0
  819. package/dist/tools/sql.js +131 -0
  820. package/dist/tools/sql.js.map +1 -0
  821. package/dist/tools/task-list.d.ts +26 -0
  822. package/dist/tools/task-list.d.ts.map +1 -0
  823. package/dist/tools/task-list.js +352 -0
  824. package/dist/tools/task-list.js.map +1 -0
  825. package/dist/tools/todo.d.ts +11 -0
  826. package/dist/tools/todo.d.ts.map +1 -0
  827. package/dist/tools/todo.js +126 -0
  828. package/dist/tools/todo.js.map +1 -0
  829. package/dist/tools/web.d.ts +59 -0
  830. package/dist/tools/web.d.ts.map +1 -0
  831. package/dist/tools/web.js +607 -0
  832. package/dist/tools/web.js.map +1 -0
  833. package/dist/tools/worktree.d.ts +88 -0
  834. package/dist/tools/worktree.d.ts.map +1 -0
  835. package/dist/tools/worktree.js +434 -0
  836. package/dist/tools/worktree.js.map +1 -0
  837. package/docs/A1-ATTRIBUTION-ROUND1-2026-07-09.md +181 -0
  838. package/docs/AB-ORACLE-GATE-VERDICT-2026-07-10.md +100 -0
  839. package/docs/ANCHOR-GAP-INVENTORY-2026-07-09.md +143 -0
  840. package/docs/ARCHITECTURE.md +125 -0
  841. package/docs/BUGHUNT-2026-07-05-NIGHT.md +98 -0
  842. package/docs/BUILD.md +63 -0
  843. package/docs/CANCEL-ASYNC-ATTRIBUTION-2026-07-09.md +98 -0
  844. package/docs/CC-198-VS-201-DRIFT-2026-07-09.md +70 -0
  845. package/docs/CC-BASELINE-FAKE-ZERO-AUDIT-2026-07-09.md +51 -0
  846. package/docs/CC-DRIFT-198-206-AGENT-TYPES-2026-07-10.md +82 -0
  847. package/docs/CC-DRIFT-198-206-CHANGELOG-2026-07-10.md +82 -0
  848. package/docs/CC-DRIFT-198-206-REMINDERS-2026-07-10.md +96 -0
  849. package/docs/CC-DRIFT-198-206-ROADMAP-2026-07-10.md +110 -0
  850. package/docs/CC-DRIFT-198-206-TOOL-INVENTORY-2026-07-10.md +53 -0
  851. package/docs/CC-DRIFT-198-206-USAGE-CONSTANTS-2026-07-10.md +64 -0
  852. package/docs/CC-DRIFT-198-206-WORKFLOW-2026-07-10.md +83 -0
  853. package/docs/CC-PARITY-CHECKLIST.md +220 -0
  854. package/docs/CC-PARITY-DEEP-SWEEP-2026-07-07.md +149 -0
  855. package/docs/CC-SUBAGENT-PROMPT-STUDY-2026-07-09.md +219 -0
  856. package/docs/CC-TASK-REMINDER-CADENCE-STUDY-2026-07-09.md +396 -0
  857. package/docs/CC-TOOL-PARITY-SWEEP-2026-07.md +56 -0
  858. package/docs/CC-TOOL-PROMPT-DEEP-DIFF-2026-07-08.md +274 -0
  859. package/docs/CC-TOOLSURFACE-DEEP-DIVE-2026-07-07.md +197 -0
  860. package/docs/CC206-OBSERVER-ANCHORS-2026-07-11.md +463 -0
  861. package/docs/CC207-CORE-SWEEP-BACKLOG-2026-07-12.md +155 -0
  862. package/docs/CENTER-CONTROL-PLANE-SEAM.md +86 -0
  863. package/docs/CLEANUP-CONTRACT-ANCHOR-2026-07-09.md +83 -0
  864. package/docs/COLD-START-RSI-2026-07-09.md +72 -0
  865. package/docs/COMPACTION-LIVE-AUDIT-2026-07-09.md +114 -0
  866. package/docs/CONTEXT-lifecycle-extension-points-and-stop-attribution.md +71 -0
  867. package/docs/COREWARS-POLYGLOT-TRIAGE-2026-07-09.md +85 -0
  868. package/docs/DEADTARGET-OVERFULL-HBOX-2026-07-10.md +92 -0
  869. package/docs/DEADTARGET-PATH-TRACING-REVERSE-2026-07-10.md +87 -0
  870. package/docs/DEADTARGET-WINNING-AVG-COREWARS-2026-07-10.md +96 -0
  871. package/docs/DEEPSEEK-API-LIMITS-PROBE-2026-07-09.md +118 -0
  872. package/docs/DESIGN-140-MOCK-VERIFY-2026-07-11.md +79 -0
  873. package/docs/DESIGN-140-VERIFICATION-2026-07-11.md +43 -0
  874. package/docs/DESIGN-DRAFT-workflow-collab-2026-07-11.md +56 -0
  875. package/docs/DESIGN-ORACLE-GROUNDING-GATE-2026-07-10.md +167 -0
  876. package/docs/DESIGN-TFRAG-RECONCILE-SCAFFOLD-2026-07-09.md +102 -0
  877. package/docs/EXP-PA2-PE-DESIGN-2026-07-11.md +220 -0
  878. package/docs/EXT-DOGFOOD-2026-07-12.md +50 -0
  879. package/docs/FINAL-VERIFY-SURFACE-AUDIT-2026-07-09.md +44 -0
  880. package/docs/FRAG-RECON-INVESTIGATION-2026-07-09.md +183 -0
  881. package/docs/HANDOFF.md +121 -0
  882. package/docs/KNOWN-ISSUES.md +96 -0
  883. package/docs/LEGW-WINDOW-TAX-2026-07-10.md +82 -0
  884. package/docs/LIVE-PROBE-BATCH-2026-07-11.md +207 -0
  885. package/docs/M2-CERT-ATTRIBUTION-2026-07-10.md +61 -0
  886. package/docs/M25-LEG-VARIANCE-ATTRIBUTION-2026-07-10.md +81 -0
  887. package/docs/MAILMAN-TIMEOUT-ATTRIBUTION-2026-07-10.md +88 -0
  888. package/docs/MEMORY-BACKEND-DIALECT-NOTES.md +69 -0
  889. package/docs/MTEB-ESCAPE-HATCH-ATTRIBUTION-2026-07-09.md +57 -0
  890. package/docs/MTEB-LEADERBOARD-ATTRIBUTION-2026-07-10.md +134 -0
  891. package/docs/ORACLE-GATE-NEGATIVE-SAMPLE-2026-07-11.md +28 -0
  892. package/docs/PARITY-CONTEXT-TRANSACTIONS-2026-07-10.md +67 -0
  893. package/docs/PARITY-PROGRESS-MATRIX-2026-07-10.md +37 -0
  894. package/docs/PARITY-SPOT-AGENT-TYPES-2026-07-10.md +70 -0
  895. package/docs/PARITY-SPOT-REMINDERS-2026-07-10.md +144 -0
  896. package/docs/PARITY-SPOT-TOOL-INVENTORY-2026-07-10.md +61 -0
  897. package/docs/PARITY-SPOT-USAGE-CONSTANTS-2026-07-10.md +95 -0
  898. package/docs/PARITY-SPOT-WORKFLOW-2026-07-10.md +93 -0
  899. package/docs/PASSWORD-RECOVERY-PANEL-VERDICT-2026-07-10.md +62 -0
  900. package/docs/R8-R9-FINALIZE-COORDINATION-2026-07-09.md +124 -0
  901. package/docs/REPL-CODE-MODE-EVALUATION-2026-07-10.md +187 -0
  902. package/docs/REPORT-1249-TARGETED.md +48 -0
  903. package/docs/RESEARCH-3P-MEMORY-SWAP-2026-07-12.md +273 -0
  904. package/docs/ROADMAP.md +111 -0
  905. package/docs/RSI-CLOUD-DEPLOY-2026-07-06.md +289 -0
  906. package/docs/RSI-PROCESS-AI-COLDSTART-2026-07-11.md +68 -0
  907. package/docs/S18-THOROUGHNESS-AUDIT-2026-07-09.md +113 -0
  908. package/docs/SERVICE-INTEGRATION-GUIDE.md +298 -0
  909. package/docs/SUBAGENT-STREAM-RESILIENCE-PARITY-2026-07-10.md +118 -0
  910. package/docs/SWEBENCH-PRO-RECON-2026-07-11.md +31 -0
  911. package/docs/TB-EFFICIENCY-TELEMETRY-2026-07-08.md +114 -0
  912. package/docs/TB-FAILURE-AUTOPSY-2026-07-05-RERUN.md +67 -0
  913. package/docs/TB-FAIRNESS-AUDIT-2026-07-08.md +141 -0
  914. package/docs/TB-FULL-1257-2026-07-08.md +77 -0
  915. package/docs/TB-LEG-GAP-ATTRIBUTION-1261-1263-2026-07-11.md +154 -0
  916. package/docs/TB-REGRESSION-DAEMON-KILL-2026-07-08.md +58 -0
  917. package/docs/TB-RSI-CROSSCHECK-2026-07-06.md +68 -0
  918. package/docs/TB-RSI-LEDGER.md +30 -0
  919. package/docs/TB-STABLE-SET-2026-07-08.md +127 -0
  920. package/docs/TB21-RECON-2026-07-11.md +28 -0
  921. package/docs/TEST-DESIGN-BATCH-1-2-3.md +97 -0
  922. package/docs/THIRD-PARTY-INTEGRATION.md +45 -0
  923. package/docs/TOKEN-ESTIMATE-CALIBRATION-LIVE-2026-07-09.md +102 -0
  924. package/docs/audit-2026-06-10-/347/254/254/344/272/214/350/275/256-/347/251/272/347/231/275/345/214/272/344/270/216/345/277/230/346/216/245/347/272/277.md +147 -0
  925. package/docs/audit-2026-06-10-/350/256/241/347/256/227bug/346/211/253/346/217/217.md +163 -0
  926. package/docs/audit-2026-06-11-/344/277/256/345/244/215/345/244/215/345/256/241/344/270/216/345/233/236/345/275/222/344/270/223/346/211/253.md +95 -0
  927. package/docs/audit-2026-06-12-design71-P1/346/275/234/344/274/217/351/235/242/350/243/201/345/206/263/344/270/216/345/220/236/351/224/231/345/256/241/350/256/241.md +45 -0
  928. package/docs/audit-2026-06-12-/345/205/254/345/274/200/346/227/213/351/222/256/346/264/273/346/200/247/344/270/216vendored/346/255/273/350/267/257.md +63 -0
  929. package/docs/audit-2026-06-15/ADDENDUM-second-pass.md +88 -0
  930. package/docs/audit-2026-06-15/ARCHITECTURE-AND-ROADMAP.md +187 -0
  931. package/docs/audit-2026-06-15/DOC-CORRECTIONS.md +105 -0
  932. package/docs/audit-2026-06-15/INDEX.md +49 -0
  933. package/docs/audit-2026-06-15/ORCHESTRATION-STATUS.md +98 -0
  934. package/docs/audit-2026-06-15/PRODUCTION-ISSUES.md +189 -0
  935. package/docs/audit-2026-06-15/REFERENCES-literature.md +139 -0
  936. package/docs/audit-2026-06-15/VENDOR-REFACTOR-PLAN.md +96 -0
  937. package/docs/cc-probe-198/README.md +72 -0
  938. package/docs/cc-probe-198/STABILITY-AUDIT.md +118 -0
  939. package/docs/cc-probe-198/live-schema-monitor-worktree-2026-07-09.json +56 -0
  940. package/docs/cc-probe-198/mount-variants.json +536 -0
  941. package/docs/cc-probe-198/plan-mode-run.json +1 -0
  942. package/docs/cc-probe-198/probe-bash-bg.json +224 -0
  943. package/docs/cc-probe-198/probe-edit-mismatch.json +120 -0
  944. package/docs/cc-probe-198/probe-read-missing.json +62 -0
  945. package/docs/cc-probe-198/probe-search-empty.json +127 -0
  946. package/docs/cc-probe-198/probe-task-family.json +227 -0
  947. package/docs/cc-probe-198/probes.status +6 -0
  948. package/docs/cc-probe-198/raw-capture-interactive.json +948 -0
  949. package/docs/cc-probe-198/raw-capture-print.json +787 -0
  950. package/docs/cc-probe-198/raw-capture2-interactive.json +948 -0
  951. package/docs/cc-probe-198/raw-capture2-print.json +787 -0
  952. package/docs/cc-probe-198/system-prompt.txt +135 -0
  953. package/docs/cc-probe-198/tools-array.json +962 -0
  954. package/docs/durability-boundary.md +63 -0
  955. package/docs/fix-2026-06-10-/350/256/241/347/256/227bug/344/277/256/345/244/215-search/346/211/271.md +75 -0
  956. package/docs/fix-2026-06-11-/347/254/254/344/272/214/350/275/256-/344/277/256/345/244/215-search/346/211/271.md +62 -0
  957. package/docs/parity-sweep/REPORT-DYNAMIC.md +97 -0
  958. package/docs/parity-sweep/REPORT-STATIC-GGB.md +127 -0
  959. package/docs/parity-sweep/REPORT-STATIC-RWE.md +133 -0
  960. package/docs/vendor-history.md +385 -0
  961. package/docs/vendored-upstream-diff-2026-07.md +83 -0
  962. package/package.json +70 -0
@@ -0,0 +1,1030 @@
1
+ import { resolveAgentCoreCompleteFn, } from "../loop/runtime-deps.js";
2
+ import { asAgentMessage, convertToLlm, createCompactionSummaryMessage, createCustomMessage, } from "../harness/messages.js";
3
+ import { buildSessionContext } from "../session/session.js";
4
+ import { CompactionError, err, ok, } from "../harness/types.js";
5
+ import { computeFileLists, createFileOps, extractFileOpsFromMessage, formatFileOperations, serializeConversation, stripFileOperationsFooter, } from "./utils.js";
6
+ function safeJsonStringify(value) {
7
+ try {
8
+ return JSON.stringify(value) ?? "undefined";
9
+ }
10
+ catch {
11
+ return "[unserializable]";
12
+ }
13
+ }
14
+ function extractFileOperations(messages, entries, prevCompactionIndex) {
15
+ const fileOps = createFileOps();
16
+ if (prevCompactionIndex >= 0) {
17
+ const prevCompaction = entries[prevCompactionIndex];
18
+ if (!prevCompaction.fromHook && prevCompaction.details) {
19
+ const details = prevCompaction.details;
20
+ if (Array.isArray(details.readFiles)) {
21
+ for (const f of details.readFiles) {
22
+ fileOps.read.add(f);
23
+ }
24
+ }
25
+ if (Array.isArray(details.modifiedFiles)) {
26
+ for (const f of details.modifiedFiles) {
27
+ fileOps.edited.add(f);
28
+ }
29
+ // Seed recency from the previous compaction when it recorded one (newest-first → insert in
30
+ // reverse so the order set stays oldest→newest); files touched by THIS range's messages are
31
+ // extracted after this and move to newer positions naturally.
32
+ const prevRecency = details.modifiedFilesByRecency;
33
+ if (Array.isArray(prevRecency)) {
34
+ for (const f of prevRecency.toReversed()) {
35
+ fileOps.modifiedOrder.add(f);
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ for (const msg of messages) {
42
+ extractFileOpsFromMessage(msg, fileOps);
43
+ }
44
+ return fileOps;
45
+ }
46
+ function getMessageFromEntry(entry) {
47
+ if (entry.type === "message") {
48
+ return entry.message;
49
+ }
50
+ if (entry.type === "custom_message") {
51
+ return asAgentMessage(createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp));
52
+ }
53
+ if (entry.type === "compaction") {
54
+ return asAgentMessage(createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp));
55
+ }
56
+ return undefined;
57
+ }
58
+ function getMessageFromEntryForCompaction(entry) {
59
+ if (entry.type === "compaction") {
60
+ return undefined;
61
+ }
62
+ return getMessageFromEntry(entry);
63
+ }
64
+ /** Default compaction settings used by the harness. */
65
+ export const DEFAULT_COMPACTION_SETTINGS = {
66
+ enabled: true,
67
+ reserveTokens: 16384,
68
+ keepRecentTokens: 20000,
69
+ };
70
+ /**
71
+ * design/123 D2 — default structural coefficient (chars per token) for every structural token
72
+ * estimate. 4 = the historical chars/4 heuristic (CC 198's legacy-family value); per-model override
73
+ * via `Model.charsPerToken` (newer families → 3, CJK-heavy → 2–3). Threaded as an explicit parameter
74
+ * through the estimate chain so caller-side coordinates never split (estimate vs cut-point vs defense).
75
+ */
76
+ export const DEFAULT_CHARS_PER_TOKEN = 4;
77
+ /**
78
+ * design/123 D2 image pin — an inline image contributes a FIXED token weight, deliberately NOT
79
+ * derived from `chars / charsPerToken`: the old `chars += 4800` shape would silently re-price an
80
+ * image from 1200 to 1600 tokens under charsPerToken=3. Image-size specialization stays deferred;
81
+ * this constant keeps the estimate coefficient-invariant.
82
+ *
83
+ * 批③ P2 value bump 1200→2000 = the CC estimate ("Images/documents are approximately 2000 tokens
84
+ * regardless of format" — services/compact/microCompact.ts:152; services/tokenEstimation.ts:409-411
85
+ * returns 2000 per image, noting the API actually charges ~2000 where naive base64/4 estimated ~325k).
86
+ * At 1200 a vision-heavy session under-estimated by ~40% per image ⇒ compaction fired late ⇒
87
+ * provider-side overflow risk. Mechanism (fixed pin) unchanged; value only.
88
+ */
89
+ const IMAGE_TOKEN_ESTIMATE = 2000;
90
+ /** Calculate total context tokens from provider usage. */
91
+ export function calculateContextTokens(usage) {
92
+ return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
93
+ }
94
+ // VENDORED EDIT (design/64 §26.5 council #1): anchor on USAGE SIGNAL, not on stopReason alone.
95
+ // - An "error" assistant often carries VALID usage (the provider billed the request before failing) —
96
+ // the old unconditional skip could drop the anchor entirely when the visible history holds only
97
+ // error assistants (shared session across failed tasks), silently falling back to the chars/4
98
+ // heuristic for the WHOLE history, which underestimates code-dense content (≈2×) → compaction
99
+ // skipped → provider-side truncation.
100
+ // - Conversely, zero/empty usage (a synthetic loop-failure message carries EMPTY_USAGE — a truthy
101
+ // object) must NEVER anchor: anchoring at 0 would swallow the entire prior history from the
102
+ // estimate, far worse than the chars/4 fallback.
103
+ // "aborted" stays excluded: its usage may reflect a partially consumed stream.
104
+ function getAssistantUsage(msg) {
105
+ if (msg.role === "assistant" && "usage" in msg) {
106
+ const assistantMsg = msg;
107
+ if (assistantMsg.stopReason !== "aborted" &&
108
+ assistantMsg.usage &&
109
+ calculateContextTokens(assistantMsg.usage) > 0) {
110
+ return assistantMsg.usage;
111
+ }
112
+ }
113
+ return undefined;
114
+ }
115
+ /**
116
+ * Return usage from the last successful assistant message in session entries.
117
+ *
118
+ * design/123 D1 stale-anchor note (fable-m2, same-family point): this scans RAW session entries, so
119
+ * unlike `buildSessionContext` (which shallow-strips the usage of kept-tail assistants replayed
120
+ * across a compaction boundary — the anchor "naturally disappears", CC 198 parity) it CAN still see
121
+ * a pre-compaction anchor. Any consumer using this across a compaction boundary must treat such an
122
+ * anchor as STALE: it reflects the pre-compaction request and overestimates the post-compaction
123
+ * context. (Currently exported with no in-repo production consumer.)
124
+ */
125
+ export function getLastAssistantUsage(entries) {
126
+ for (let i = entries.length - 1; i >= 0; i--) {
127
+ const entry = entries[i];
128
+ if (entry.type === "message") {
129
+ const usage = getAssistantUsage(entry.message);
130
+ if (usage) {
131
+ return usage;
132
+ }
133
+ }
134
+ }
135
+ return undefined;
136
+ }
137
+ function getLastAssistantUsageInfo(messages) {
138
+ for (let i = messages.length - 1; i >= 0; i--) {
139
+ const usage = getAssistantUsage(messages[i]);
140
+ if (usage) {
141
+ return { usage, index: i };
142
+ }
143
+ }
144
+ return undefined;
145
+ }
146
+ /** Estimate context tokens for messages using provider usage when available.
147
+ * `charsPerToken` (design/123 D2): structural coefficient for the anchor-less fallback and the
148
+ * trailing (post-anchor) increment — pass `Model.charsPerToken` so the estimate matches the model. */
149
+ export function estimateContextTokens(messages, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
150
+ const usageInfo = getLastAssistantUsageInfo(messages);
151
+ if (!usageInfo) {
152
+ let estimated = 0;
153
+ for (const message of messages) {
154
+ estimated += estimateTokens(message, charsPerToken);
155
+ }
156
+ return {
157
+ tokens: estimated,
158
+ usageTokens: 0,
159
+ trailingTokens: estimated,
160
+ lastUsageIndex: null,
161
+ };
162
+ }
163
+ const usageTokens = calculateContextTokens(usageInfo.usage);
164
+ let trailingTokens = 0;
165
+ for (let i = usageInfo.index + 1; i < messages.length; i++) {
166
+ trailingTokens += estimateTokens(messages[i], charsPerToken);
167
+ }
168
+ return {
169
+ tokens: usageTokens + trailingTokens,
170
+ usageTokens,
171
+ trailingTokens,
172
+ lastUsageIndex: usageInfo.index,
173
+ };
174
+ }
175
+ /** Return whether context usage exceeds the configured compaction threshold. */
176
+ export function shouldCompact(contextTokens, contextWindow, settings) {
177
+ if (!settings.enabled) {
178
+ return false;
179
+ }
180
+ return contextTokens > contextWindow - settings.reserveTokens;
181
+ }
182
+ /** Estimate token count for one message using a conservative character heuristic.
183
+ * `charsPerToken` (design/123 D2): per-model structural coefficient (default 4 = byte-compatible
184
+ * legacy heuristic). Images contribute a FIXED token weight independent of the coefficient. */
185
+ export function estimateTokens(message, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
186
+ let chars = 0;
187
+ const harnessMessage = message;
188
+ switch (harnessMessage.role) {
189
+ case "user": {
190
+ const content = harnessMessage.content;
191
+ let imageTokens = 0;
192
+ if (typeof content === "string") {
193
+ chars = content.length;
194
+ }
195
+ else if (Array.isArray(content)) {
196
+ for (const block of content) {
197
+ if (block.type === "text" && block.text) {
198
+ chars += block.text.length;
199
+ }
200
+ // Upstream-parity fix (2026-07 diff, openclaw 2ece2945ae class): user-message image blocks
201
+ // previously counted 0 tokens, so image-heavy sessions systematically UNDER-estimated context
202
+ // and compaction triggered late. Mirror the toolResult branch's fixed-weight accounting
203
+ // (image pin + PDF page approximation) so the estimate is symmetric across roles.
204
+ if (block.type === "image") {
205
+ imageTokens += IMAGE_TOKEN_ESTIMATE;
206
+ }
207
+ if (block.type === "document" && typeof block.data === "string") {
208
+ imageTokens += Math.max(IMAGE_TOKEN_ESTIMATE, Math.ceil(block.data.length / 36));
209
+ }
210
+ }
211
+ }
212
+ return Math.ceil(chars / charsPerToken) + imageTokens;
213
+ }
214
+ case "assistant": {
215
+ const assistant = harnessMessage;
216
+ for (const block of assistant.content) {
217
+ if (block.type === "text") {
218
+ chars += block.text.length;
219
+ }
220
+ else if (block.type === "thinking") {
221
+ // Count the signature payload too: redacted thinking carries its (billed) content in
222
+ // `thinkingSignature` with an EMPTY `thinking` text, and the block is replayed to the
223
+ // provider on the next request — a structural estimate blind to it under-counts exactly
224
+ // the content the anchor legitimately billed (stale-anchor gate false positive; verify
225
+ // leg F1 on docs/TOKEN-ESTIMATE-CALIBRATION-LIVE-2026-07-09.md). No-op for providers
226
+ // that don't return signatures (e.g. deepseek).
227
+ chars += block.thinking.length + (block.thinkingSignature?.length ?? 0);
228
+ }
229
+ else if (block.type === "toolCall") {
230
+ chars += block.name.length + safeJsonStringify(block.arguments).length;
231
+ }
232
+ }
233
+ return Math.ceil(chars / charsPerToken);
234
+ }
235
+ case "custom":
236
+ case "toolResult": {
237
+ let imageTokens = 0;
238
+ if (typeof harnessMessage.content === "string") {
239
+ chars = harnessMessage.content.length;
240
+ }
241
+ else {
242
+ for (const block of harnessMessage.content) {
243
+ if (block.type === "text" && block.text) {
244
+ chars += block.text.length;
245
+ }
246
+ if (block.type === "image") {
247
+ // Fixed token weight (design/123 D2 image pin): NOT chars-derived, so the estimate does
248
+ // not drift when the coefficient changes (4800 chars was 1200 tokens at /4 but would
249
+ // become 1600 at /3).
250
+ imageTokens += IMAGE_TOKEN_ESTIMATE;
251
+ }
252
+ if (block.type === "document" && typeof block.data === "string") {
253
+ // PDF read: a document block's cost scales with PAGE COUNT (Anthropic bills ~1,500-3,000
254
+ // tokens/page: each page is charged as an image plus its extracted text), which we cannot
255
+ // see here — approximate pages from payload size (~60KB raw ≈ 80K base64 chars per typical
256
+ // page ⇒ tokens ≈ base64Len × 0.75/61440 × 2250 ≈ len/36), floored at one IMAGE-pin worth
257
+ // so a tiny PDF never under-counts below the CC "≈2000 tokens regardless of format" floor.
258
+ imageTokens += Math.max(IMAGE_TOKEN_ESTIMATE, Math.ceil(block.data.length / 36));
259
+ }
260
+ }
261
+ }
262
+ return Math.ceil(chars / charsPerToken) + imageTokens;
263
+ }
264
+ case "bashExecution": {
265
+ chars = harnessMessage.command.length + harnessMessage.output.length;
266
+ return Math.ceil(chars / charsPerToken);
267
+ }
268
+ case "compactionSummary": {
269
+ chars = harnessMessage.summary.length;
270
+ return Math.ceil(chars / charsPerToken);
271
+ }
272
+ }
273
+ return 0;
274
+ }
275
+ function findValidCutPoints(entries, startIndex, endIndex) {
276
+ const cutPoints = [];
277
+ // message-identity Phase 1 coupling (verified 2026-06-28): the chosen cut point becomes `firstKeptEntryId`
278
+ // (the `compacted.preserved_segment` floor a consumer resolves via the `message_committed` wire event, which
279
+ // covers user/assistant/toolResult). This switch ALSO admits `bashExecution`/`custom`/`compactionSummary`
280
+ // message roles + `custom_message` entries as floors — but those have NO producer in this engine (no
281
+ // appendMessage of those roles; nothing queues a `custom_message` write; compactionSummary/custom are
282
+ // build-context reconstructions, not persisted message entries), so a real floor is always user/assistant. If a
283
+ // future change ADDS such a producer, a floor could land on an entry `message_committed` does not emit → extend
284
+ // message-identity coverage (or adopt the first-party `onEntryCommitted` escape hatch). The compaction-floor
285
+ // tripwire in `test/compaction.test.ts` ("message-identity Phase 1") goes RED if that invariant ever breaks.
286
+ for (let i = startIndex; i < endIndex; i++) {
287
+ const entry = entries[i];
288
+ switch (entry.type) {
289
+ case "message": {
290
+ const role = entry.message.role;
291
+ switch (role) {
292
+ case "bashExecution":
293
+ case "custom":
294
+ case "compactionSummary":
295
+ case "user":
296
+ case "assistant":
297
+ cutPoints.push(i);
298
+ break;
299
+ case "toolResult":
300
+ break;
301
+ }
302
+ break;
303
+ }
304
+ // VENDORED EDIT (design/71 council fold, 2026-06-13): custom_message used to sit in the no-op
305
+ // fall-through AND get pushed by a standalone if AFTER the switch (upstream shape, shared with
306
+ // the deleted branch_summary) — a maintenance trap where editing the switch silently misses the
307
+ // out-of-band push. One source of truth: it IS a valid cut point, said in its own case.
308
+ case "custom_message":
309
+ cutPoints.push(i);
310
+ break;
311
+ case "thinking_level_change":
312
+ case "model_change":
313
+ case "compaction":
314
+ case "custom":
315
+ case "label":
316
+ case "session_info":
317
+ case "leaf":
318
+ break;
319
+ }
320
+ }
321
+ return cutPoints;
322
+ }
323
+ /** Find the user-visible message that starts the turn containing an entry. */
324
+ export function findTurnStartIndex(entries, entryIndex, startIndex) {
325
+ for (let i = entryIndex; i >= startIndex; i--) {
326
+ const entry = entries[i];
327
+ if (entry.type === "custom_message") {
328
+ return i;
329
+ }
330
+ if (entry.type === "message") {
331
+ const role = entry.message.role;
332
+ if (role === "user" || role === "bashExecution") {
333
+ return i;
334
+ }
335
+ }
336
+ }
337
+ return -1;
338
+ }
339
+ /** Find the compaction cut point that keeps approximately the requested recent-token budget.
340
+ * `charsPerToken` (design/123 D2): the keep-recent accumulation must live in the SAME structural
341
+ * coordinate as the trigger estimate, or the kept tail is systematically over/under-sized. */
342
+ export function findCutPoint(entries, startIndex, endIndex, keepRecentTokens, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
343
+ const cutPoints = findValidCutPoints(entries, startIndex, endIndex);
344
+ if (cutPoints.length === 0) {
345
+ return { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };
346
+ }
347
+ let accumulatedTokens = 0;
348
+ let cutIndex = cutPoints[0];
349
+ for (let i = endIndex - 1; i >= startIndex; i--) {
350
+ const entry = entries[i];
351
+ if (entry.type !== "message") {
352
+ continue;
353
+ }
354
+ const messageTokens = estimateTokens(entry.message, charsPerToken);
355
+ accumulatedTokens += messageTokens;
356
+ if (accumulatedTokens >= keepRecentTokens) {
357
+ let found = false;
358
+ for (const cutPoint of cutPoints) {
359
+ if (cutPoint >= i) {
360
+ cutIndex = cutPoint;
361
+ found = true;
362
+ break;
363
+ }
364
+ }
365
+ // VENDORED EDIT (audit A-2 / design/64 §28.3): when the keep budget is exhausted INSIDE the
366
+ // trailing tool-result batch (tool results are not valid cut points, so no cutPoint ≥ i
367
+ // exists — e.g. two parallel 50KB reads ≥ keepRecentTokens at a within-task boundary), the
368
+ // old fallback was cutPoints[0] = the EARLIEST cut point: nearly the whole history was kept,
369
+ // messagesToSummarize came out empty, the model hallucinated a summary from an empty
370
+ // conversation (bypassing the empty-summary guard), context GREW, freedTokens=0 inflated the
371
+ // §25.2 regrowth floor past the window, and within-task compaction shut down for the rest of
372
+ // the task. Correct fallback: the LARGEST cut point ≤ i — keep the oversized batch (slightly
373
+ // over budget) and summarize everything before it. The normal path (a cut point at/after i
374
+ // exists) is unchanged.
375
+ if (!found) {
376
+ for (let c = cutPoints.length - 1; c >= 0; c--) {
377
+ if (cutPoints[c] <= i) {
378
+ cutIndex = cutPoints[c];
379
+ break;
380
+ }
381
+ }
382
+ }
383
+ break;
384
+ }
385
+ }
386
+ while (cutIndex > startIndex) {
387
+ const prevEntry = entries[cutIndex - 1];
388
+ if (prevEntry.type === "compaction") {
389
+ break;
390
+ }
391
+ if (prevEntry.type === "message") {
392
+ break;
393
+ }
394
+ cutIndex--;
395
+ }
396
+ const cutEntry = entries[cutIndex];
397
+ const isUserMessage = cutEntry.type === "message" && cutEntry.message.role === "user";
398
+ const turnStartIndex = isUserMessage ? -1 : findTurnStartIndex(entries, cutIndex, startIndex);
399
+ return {
400
+ firstKeptEntryIndex: cutIndex,
401
+ turnStartIndex,
402
+ isSplitTurn: !isUserMessage && turnStartIndex !== -1,
403
+ };
404
+ }
405
+ export const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.
406
+
407
+ Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;
408
+ // VENDORED EDIT (design/64 §22 / design/66 D / channel [73], clay 2026-06-10 vendored-edit policy), realigned
409
+ // 2026-07-08 (CC 2.1.198 compaction parity batch W:C1/C2/C3, bench/cc-parity-toolsuite/
410
+ // compaction-cc198-verbatim-capture-2026-07-08.md §A1a): the 9 section names, the analysis checklist, and the
411
+ // security-relevant-instructions preservation clauses (two occurrences — analysis checklist + section 6) are
412
+ // CC 198 T$n VERBATIM. Deliberate sema supersets kept: the fenced `<conversation>` input framing (C9/H5
413
+ // posture — CC sees the raw fork context instead) and the `<analysis>` scratch block being STRIPPED before
414
+ // persisting (maybeCompact; CC keeps its own <analysis>/<summary> post-processing). No `<summary>` output tag
415
+ // requested: our injection adds the fencing at render time (COMPACTION_SUMMARY_PREFIX/SUFFIX).
416
+ // Mirrored in UPDATE_SUMMARIZATION_PROMPT (the update pass is a sema superset — CC is fresh-pass only).
417
+ const SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
418
+ This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context. Another LLM will use it to continue the work.
419
+
420
+ Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. This analysis is scratch work — it will be stripped and NOT kept, so it is only to help you write a faithful summary. In your analysis process:
421
+
422
+ 1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
423
+ - The user's explicit requests and intents
424
+ - Your approach to addressing the user's requests
425
+ - Key decisions, technical concepts and code patterns
426
+ - Specific details like:
427
+ - file names
428
+ - full code snippets
429
+ - function signatures
430
+ - file edits
431
+ - Errors that you ran into and how you fixed them
432
+ - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
433
+ - Note any security-relevant instructions or constraints the user stated (e.g., sensitive files or data to avoid, operations that must not be performed, credential or secret handling rules). These MUST be preserved verbatim in the summary so they continue to apply after compaction.
434
+ 2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.
435
+
436
+ Then, after </analysis>, write the summary. Your summary should include the following sections:
437
+
438
+ 1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
439
+ 2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
440
+ 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
441
+ 4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
442
+ 5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
443
+ 6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent. Preserve any security-relevant instructions or constraints verbatim so they remain in effect after compaction.
444
+ 7. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
445
+ 8. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
446
+ 9. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests or really old requests that were already completed without confirming with the user first.
447
+ If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.
448
+
449
+ Please provide your summary based on the conversation so far, following this structure and ensuring precision and thoroughness in your response.
450
+
451
+ Keep each section concise. Preserve exact file paths, function names, and error messages.`;
452
+ const UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.
453
+
454
+ Update the existing structured summary with new information. RULES:
455
+ - PRESERVE all existing information from the previous summary
456
+ - ADD new progress, decisions, and context from the new messages
457
+ - UPDATE "Pending Tasks" and "Current Work" based on what was accomplished
458
+ - UPDATE "Optional Next Step" based on the most recent work
459
+ - PRESERVE exact file paths, function names, and error messages
460
+ - Preserve any security-relevant instructions or constraints verbatim so they remain in effect after compaction
461
+ - If something is no longer relevant, you may remove it
462
+
463
+ First, inside an <analysis>...</analysis> block, note what is new since the previous summary and what must change. This analysis is scratch work — it will be stripped and NOT kept. Then, after </analysis>, write the updated summary with the following sections:
464
+
465
+ 1. Primary Request and Intent: [Preserve existing requests and intents, add new ones if the task expanded]
466
+ 2. Key Technical Concepts: [Preserve existing, add newly discussed concepts, technologies, and frameworks]
467
+ 3. Files and Code Sections: [Preserve entries still relevant; add newly examined, modified, or created files with full code snippets where applicable]
468
+ 4. Errors and fixes: [Preserve previous errors and fixes and add new ones; keep any user correction or "change of approach" feedback verbatim.]
469
+ 5. Problem Solving: [Update problems solved and any ongoing troubleshooting efforts]
470
+ 6. All user messages: [Preserve previously-recorded user messages VERBATIM and append any new ones that are not tool results, in order. To bound growth across repeated compactions, keep roughly the most recent 20 messages verbatim; older ones beyond that may be condensed to a single line each — but NEVER drop or paraphrase a user correction or change of direction. The exact words of recent messages are the strongest anti-drift signal. Preserve any security-relevant instructions or constraints verbatim so they remain in effect after compaction.]
471
+ 7. Pending Tasks: [Update based on progress — remove completed tasks, add newly requested ones]
472
+ 8. Current Work: [Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant]
473
+ 9. Optional Next Step: [Update based on current state. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request — include a direct verbatim quote of that request. Do not start on tangential requests or really old requests that were already completed.]
474
+
475
+ Keep each section concise. Preserve exact file paths, function names, and error messages.`;
476
+ function createSummarizationOptions(model, maxTokens, apiKey, headers, signal, thinkingLevel) {
477
+ const options = { maxTokens, signal, apiKey, headers };
478
+ if (model.reasoning && thinkingLevel && thinkingLevel !== "off") {
479
+ options.reasoning = thinkingLevel;
480
+ }
481
+ return options;
482
+ }
483
+ async function completeSummarization(model, context, options, streamFn, runtime) {
484
+ if (streamFn) {
485
+ return (await streamFn(model, context, options)).result();
486
+ }
487
+ return await resolveAgentCoreCompleteFn(runtime)(model, context, options);
488
+ }
489
+ // design/118 follow-up (live-caught 2026-07-02): a reserve-derived output budget (0.8×/0.5× reserveTokens —
490
+ // 320/200 tokens at the 400 default) is fully consumed by REASONING before any summary text on a reasoning
491
+ // model. Proven live on Qwen with thinking:"off": the gateway reasons by DEFAULT regardless of the requested
492
+ // thinking level, and the brain surfaces "max_tokens cut with no answer text" as `stopReason:"error"` +
493
+ // `errorKind:"length_empty"` — NOT a "length" stop (see brain/openai.ts `truncatedEmpty`). Both summary paths
494
+ // (history AND turn-prefix — the live-observed failure was the turn-prefix one) then fail at every boundary
495
+ // and compaction never lands. Recovery, shared by both paths:
496
+ // (a) a reasoning model's budget is floored at SUMMARY_REASONING_FLOOR up front — gated on `model.reasoning`
497
+ // alone, because the thinking level is irrelevant when the gateway thinks by default;
498
+ // (b) `length_empty` errors escalate the budget to at least the floor and then ×2 per retry
499
+ // (≤SUMMARY_MAX_ESCALATIONS) — the error is DIRECT evidence the model reasons (stronger than the
500
+ // catalog flag), so a mis-catalogued `reasoning:false` model jumps straight to the floor instead of
501
+ // doubling from a tiny reserve-derived base that three retries can never rescue;
502
+ // (c) a "length"-truncated response whose text is ONLY <analysis> scratch (closed, or an unterminated
503
+ // LINE-ANCHORED tail — provably scratch: the cut landed before the summary) escalates the same way
504
+ // instead of flowing a scratch-only "summary" upstream (the persisted strip removes closed pairs only,
505
+ // by design).
506
+ // Budget legality (dual-track review MAJOR): every candidate is clamped to the WINDOW headroom left by the
507
+ // summarization request itself — compaction fires when the context is at its fullest, and on strict gateways
508
+ // `input + max_tokens > contextWindow` is a hard HTTP 400 (no finish_reason, no errorKind → unrecoverable).
509
+ // The reserve-derived base is constructively safe (< reserveTokens ≤ headroom), so the clamp never goes
510
+ // below it; the floor/escalations get whatever headroom actually exists.
511
+ // The floor deliberately lets the OUTPUT budget exceed the reserve-derived cap: the summary TEXT length is
512
+ // bounded by the prompt's format/brevity constraints, the headroom is for reasoning scratch, and the
513
+ // alternative is proven to produce NO summary at all (maybeCompact's empty-summary and freed-tokens guards
514
+ // bound the pathological cases).
515
+ const SUMMARY_REASONING_FLOOR = 2048;
516
+ const SUMMARY_MAX_ESCALATIONS = 2;
517
+ const SUMMARY_WINDOW_MARGIN = 256; // slack for the chars/4 input estimate vs the gateway's real tokenizer
518
+ // design/123 D2 (应改): coefficient-aware — the input estimated here is sent to the SUMMARY model,
519
+ // so the caller passes that model's charsPerToken. An underestimate risks a strict-gateway 400
520
+ // (`input + max_tokens > contextWindow`); on cpt=3-class models chars/4 was exactly that underestimate.
521
+ function estimateSummarizationInputTokens(context, charsPerToken) {
522
+ let chars = context.systemPrompt?.length ?? 0;
523
+ for (const m of context.messages) {
524
+ const content = m.content;
525
+ if (typeof content === "string") {
526
+ chars += content.length;
527
+ }
528
+ else if (Array.isArray(content)) {
529
+ for (const c of content) {
530
+ chars += c.text?.length ?? 0;
531
+ }
532
+ }
533
+ }
534
+ return Math.ceil(chars / charsPerToken);
535
+ }
536
+ // MF-18 修② (blackboard [496]③ E-leg): the summarization INPUT was unbounded — generateSummary
537
+ // serialized the WHOLE summarized span into one prompt, so a ~300K-token session became a request far
538
+ // past the COMPACTION model's own window. A strict gateway hard-rejects it (prompt-too-long →
539
+ // CompactionError("summarization_failed")) at EVERY boundary; three strikes open the §17.4 breaker,
540
+ // which then silently moots a later manual /compact — the diagnosed E→C compound. Clamp the
541
+ // CONVERSATION text (never the instructions / system prompt) to the window headroom left after the
542
+ // fixed prompt parts, the output budget the length-recovery loop may escalate to (the reasoning
543
+ // floor), and the estimate margin. Shape: head + elision marker + tail — the head keeps the
544
+ // objective / early decisions, the tail keeps the span closest to the kept history (and on an UPDATE
545
+ // pass `previousSummary` already covers the older ground); the middle is the cheapest loss for a
546
+ // summary. A lossy-but-landing summary strictly beats the status quo (no summary, breaker open,
547
+ // compaction dead for the rest of the task — trimToBudget then drops the same content with zero
548
+ // summarization at all).
549
+ const SUMMARY_INPUT_HEAD_RATIO = 0.25;
550
+ const SUMMARY_INPUT_MIN_KEEP_CHARS = 1024; // pathological tiny window: still send SOMETHING (the gateway, not core, is then the honest failure)
551
+ const SUMMARY_INPUT_MARKER_RESERVE = 200; // elision marker + splice slack, chars
552
+ function clampSummarizationConversation(conversationText, model, charsPerToken, fixedPromptChars, baseMaxTokens,
553
+ // W:C16 — a reactive PTL retry tightens the budget below the window-derived estimate (the gateway's
554
+ // real tokenizer proved the estimate too generous). Applies even when the window is unknown: the
555
+ // gateway's prompt-too-long error is then the only budget evidence there is.
556
+ budgetCapChars) {
557
+ let budgetChars = Number.POSITIVE_INFINITY;
558
+ if (model.contextWindow > 0) {
559
+ // Output reservation matches summarizeWithLengthRecovery's worst legal ask: the reasoning floor
560
+ // (length_empty/scratch escalation jumps straight to it, even on a mis-catalogued model) or the
561
+ // reserve-derived base when that is already larger. Double margin: input estimate slack on top of
562
+ // the same slack the windowCap math applies on the output side.
563
+ const outputReserve = Math.max(baseMaxTokens, SUMMARY_REASONING_FLOOR);
564
+ budgetChars =
565
+ (model.contextWindow - outputReserve - 2 * SUMMARY_WINDOW_MARGIN) * charsPerToken - fixedPromptChars;
566
+ }
567
+ if (budgetCapChars !== undefined) {
568
+ budgetChars = Math.min(budgetChars, budgetCapChars);
569
+ }
570
+ if (!Number.isFinite(budgetChars) || conversationText.length <= budgetChars) {
571
+ return { text: conversationText, droppedChars: 0, keptChars: conversationText.length }; // in budget (or window unknown and no retry cap — nothing sound to clamp against)
572
+ }
573
+ const keep = Math.max(budgetChars - SUMMARY_INPUT_MARKER_RESERVE, SUMMARY_INPUT_MIN_KEEP_CHARS);
574
+ const headChars = Math.floor(keep * SUMMARY_INPUT_HEAD_RATIO);
575
+ const tailChars = keep - headChars;
576
+ const elided = conversationText.length - headChars - tailChars;
577
+ const text = conversationText.slice(0, headChars) +
578
+ `\n\n[... ${elided} characters of the conversation elided so the summarization request fits the compaction model's context window ...]\n\n` +
579
+ conversationText.slice(conversationText.length - tailChars);
580
+ return { text, droppedChars: elided, keptChars: headChars + tailChars };
581
+ }
582
+ // ---------------------------------------------------------------------------------------------------
583
+ // W:C16 (CC 2.1.198 compaction parity batch 2026-07-08) — REACTIVE prompt-too-long retry, the CC-family
584
+ // complement to the proactive clamp above. CC has NO pre-send truncation at all: T$n + the full
585
+ // conversation are sent as-is and a PTL error drives the KNl retry loop (≤ VNl=3 attempts, dropping
586
+ // whole message GROUPS from the head, gap-guided by the token counts in the error text, marking the
587
+ // cut with the jNl meta message). sema keeps the clamp as first line of defense (estimate-based,
588
+ // prevents most PTLs before they happen) and adds this loop as the second: when the gateway's REAL
589
+ // tokenizer still rejects the clamped request (chars/N is an estimate; strict gateways count exactly),
590
+ // tighten the budget by the reported gap, drop the OLDEST assistant-turn groups to fit, mark the cut
591
+ // with CC's verbatim retry marker, and try again — only an unrecoverable failure after
592
+ // COMPACTION_PTL_MAX_RETRIES walks the existing failure path (CompactionError → caller breaker).
593
+ // ---------------------------------------------------------------------------------------------------
594
+ const COMPACTION_PTL_MAX_RETRIES = 3; // CC 198 VNl = 3
595
+ /** CC 198 jNl — verbatim marker inserted where the oldest conversation groups were dropped. */
596
+ export const COMPACTION_PTL_RETRY_MARKER = "[earlier conversation truncated for compaction retry]";
597
+ const PTL_NO_GAP_DROP_FRACTION = 0.2; // CC 198 KNl fallback: gap unparsable → shave ~20% (at least one group)
598
+ const PTL_GAP_SAFETY = 1.2; // slack when converting a token gap to chars — under-shaving guarantees another PTL
599
+ // CC 198 L231884 verbatim gap regex ("prompt is too long: 12345 tokens > 10000 maximum" family).
600
+ const PTL_CC_GAP_RE = /prompt is too long[^0-9]*(\d+) tokens? > (\d+)/i;
601
+ // OpenAI-completions-family gateways (our brain surfaces the provider text verbatim in errorMessage):
602
+ // "This model's maximum context length is 128000 tokens. However, your messages resulted in 131072 tokens".
603
+ const PTL_OPENAI_GAP_RE = /maximum context length is (\d+) tokens?[^0-9]*?(\d+) tokens?/i;
604
+ // Classifier for gap-less PTL variants across gateways. Consulted ONLY for summarization-request
605
+ // failures, and a false positive merely burns ≤3 bounded, smaller retries.
606
+ const PTL_CLASS_RE = /prompt is too long|too many tokens|input is too long|context[ _-]?length|context window|exceeds? the (?:model'?s? )?context/i;
607
+ // 双轨复审 1.257.3 (codex LOW + opus confirmed): the gap-less class above is deliberately broad (missing
608
+ // a real PTL variant opens the breaker permanently — worse than ≤3 bounded retries), but a message that
609
+ // merely MENTIONS the context window while being a server/config fault must not trigger history-dropping
610
+ // retries. Deny wins over the class match; the gap'd regexes above stay authoritative either way.
611
+ const PTL_DENY_RE = /internal (?:server )?error|http 5\d\d|status(?: code)?[: ]5\d\d|invalid (?:api key|request)|configuration|unauthorized|permission/i;
612
+ function parsePromptTooLong(message) {
613
+ if (!message) {
614
+ return { isPtl: false };
615
+ }
616
+ const cc = PTL_CC_GAP_RE.exec(message);
617
+ if (cc) {
618
+ const actual = Number(cc[1]);
619
+ const limit = Number(cc[2]);
620
+ return { isPtl: true, ...(actual > limit ? { gapTokens: actual - limit } : {}) };
621
+ }
622
+ const oa = PTL_OPENAI_GAP_RE.exec(message);
623
+ if (oa) {
624
+ const limit = Number(oa[1]);
625
+ const requested = Number(oa[2]);
626
+ return { isPtl: true, ...(requested > limit ? { gapTokens: requested - limit } : {}) };
627
+ }
628
+ return { isPtl: PTL_CLASS_RE.test(message) && !PTL_DENY_RE.test(message) };
629
+ }
630
+ /** CC 198 wpt-family grouping: one assistant turn = one group (the assistant message plus its tool
631
+ * results; any user/context messages leading into that turn ride with it). Dropping whole groups from
632
+ * the head keeps tool_use/tool_result pairs and turn coherence intact — a mid-turn char cut does not. */
633
+ function splitMessageGroups(messages) {
634
+ const groups = [];
635
+ let current = [];
636
+ let sawAssistant = false;
637
+ for (const m of messages) {
638
+ if (sawAssistant && m.role !== "toolResult") {
639
+ groups.push(current);
640
+ current = [];
641
+ sawAssistant = false;
642
+ }
643
+ current.push(m);
644
+ if (m.role === "assistant") {
645
+ sawAssistant = true;
646
+ }
647
+ }
648
+ if (current.length > 0) {
649
+ groups.push(current);
650
+ }
651
+ return groups;
652
+ }
653
+ /** Serialize → clamp (proactive, sema superset) → summarize; on a gateway prompt-too-long, tighten the
654
+ * budget by the reported token gap, drop the OLDEST groups (CC KNl shape), mark the cut with
655
+ * {@link COMPACTION_PTL_RETRY_MARKER}, and retry ≤ {@link COMPACTION_PTL_MAX_RETRIES} times. Each drop
656
+ * is disclosed through the same `compaction.input_truncated` observer the clamp uses. */
657
+ async function summarizeWithPtlRetry(req) {
658
+ const disclose = (droppedChars, keptChars) => {
659
+ if (droppedChars <= 0) {
660
+ return;
661
+ }
662
+ // Observer isolation: a throwing callback must never fail the compaction it merely observes.
663
+ try {
664
+ req.onInputTruncated?.({ label: req.truncationLabel, droppedChars, keptChars });
665
+ }
666
+ catch {
667
+ /* observe-only */
668
+ }
669
+ };
670
+ let groups = splitMessageGroups(req.llmMessages);
671
+ let droppedForRetry = false;
672
+ let budgetCapChars;
673
+ for (let retry = 0;; retry++) {
674
+ const serialized = serializeConversation(groups.flat());
675
+ const conversationText = droppedForRetry
676
+ ? `${COMPACTION_PTL_RETRY_MARKER}\n\n${serialized}`
677
+ : serialized;
678
+ const clamped = clampSummarizationConversation(conversationText, req.model, req.cpt, req.fixedPromptChars, req.baseMaxTokens, budgetCapChars);
679
+ // Fired BEFORE the summary call (fidelity disclosure survives a later failure).
680
+ disclose(clamped.droppedChars, clamped.keptChars);
681
+ const context = {
682
+ systemPrompt: SUMMARIZATION_SYSTEM_PROMPT,
683
+ messages: [
684
+ {
685
+ role: "user",
686
+ content: [{ type: "text", text: req.buildPromptText(clamped.text) }],
687
+ timestamp: Date.now(),
688
+ },
689
+ ],
690
+ };
691
+ let result;
692
+ let thrown;
693
+ let didThrow = false;
694
+ try {
695
+ result = await summarizeWithLengthRecovery(req.label, req.model, context, req.baseMaxTokens, req.apiKey, req.headers, req.signal, req.thinkingLevel, req.streamFn, req.runtime, req.charsPerToken);
696
+ }
697
+ catch (e) {
698
+ // A strict gateway may surface the 400 as a THROW instead of a stopReason:"error" response —
699
+ // classify it the same way; anything non-PTL rethrows untouched.
700
+ didThrow = true;
701
+ thrown = e;
702
+ }
703
+ if (!didThrow && result && result.ok) {
704
+ return result;
705
+ }
706
+ const failureMessage = didThrow
707
+ ? thrown instanceof Error
708
+ ? thrown.message
709
+ : String(thrown)
710
+ : result && !result.ok
711
+ ? result.error.message
712
+ : "";
713
+ const ptl = parsePromptTooLong(failureMessage);
714
+ if (!ptl.isPtl || retry >= COMPACTION_PTL_MAX_RETRIES || req.signal?.aborted) {
715
+ if (didThrow) {
716
+ throw thrown;
717
+ }
718
+ return result;
719
+ }
720
+ // Gap-guided budget tightening (CC w_a shape): the error's own token counts say how far over the
721
+ // request was; without them fall back to a fixed fraction. The tightened budget also caps every
722
+ // LATER attempt's clamp (monotonically decreasing — the loop cannot oscillate).
723
+ const sentChars = clamped.text.length;
724
+ const gapChars = ptl.gapTokens !== undefined
725
+ ? Math.ceil(ptl.gapTokens * req.cpt * PTL_GAP_SAFETY)
726
+ : Math.ceil(sentChars * PTL_NO_GAP_DROP_FRACTION);
727
+ budgetCapChars = Math.max(SUMMARY_INPUT_MIN_KEEP_CHARS, sentChars - Math.max(gapChars, 1));
728
+ // CC-family group rollback: drop the OLDEST assistant-turn groups until the remaining serialized
729
+ // conversation fits the tightened budget. Always keep at least one group — the clamp cap above is
730
+ // the backstop when a single group is itself oversized (head+tail char cut, sema shape).
731
+ // opus 1.257.3 review (LOW, scale fix): the rollback target lives on the PRE-clamp serialized scale,
732
+ // so it must be derived on that scale too (beforeChars − gap) — comparing the full serialized length
733
+ // against the POST-clamp budgetCapChars would, after a heavy proactive clamp (serialized ≫ sent),
734
+ // shed almost every group on the first retry regardless of the reported gap. budgetCapChars (the
735
+ // clamp's cap, post-clamp scale) is unchanged — each leg tightens on its own scale.
736
+ const beforeChars = serialized.length;
737
+ const rollbackTargetChars = Math.max(SUMMARY_INPUT_MIN_KEEP_CHARS, beforeChars - Math.max(gapChars, 1));
738
+ let remainingChars = beforeChars;
739
+ while (groups.length > 1 && remainingChars > rollbackTargetChars) {
740
+ const dropped = groups.shift();
741
+ remainingChars -= serializeConversation(dropped).length + 2; // +2 ≈ the "\n\n" part joiner
742
+ }
743
+ droppedForRetry = true;
744
+ disclose(beforeChars - Math.max(remainingChars, 0), Math.max(remainingChars, 0));
745
+ }
746
+ }
747
+ function stripAnalysisScratch(text, lengthTruncated) {
748
+ // Closed pairs always (mirrors the persisted strip in maybeCompact); an UNTERMINATED trailing block only
749
+ // when the response was length-truncated — then the tail is provably scratch. Outside the truncation case
750
+ // an unterminated tag is left intact rather than swallowing a real summary (design/66 D #1).
751
+ let out = text.replace(/<analysis>[\s\S]*?<\/analysis>\s*/gi, "");
752
+ if (lengthTruncated) {
753
+ // Line-anchored (dual-track review): the model's scratch block always opens at the start of the response
754
+ // or of a line, while a literal "<analysis>" QUOTED by the summary (verbatim user messages / error text —
755
+ // the prompt demands verbatim preservation) is almost always mid-line. Anchoring keeps the target case
756
+ // (pure-scratch tail) while not swallowing real summary text from a mid-line quotation onward.
757
+ out = out.replace(/(?:^|\n)<analysis>[\s\S]*$/i, "");
758
+ }
759
+ return out;
760
+ }
761
+ async function summarizeWithLengthRecovery(label, model, context, baseMaxTokens, apiKey, headers, signal, thinkingLevel, streamFn, runtime, charsPerToken) {
762
+ // design/123 D2: the structural coefficient for the SUMMARY model's input estimate — explicit
763
+ // caller override first, then the model's own declaration, then the /4 default.
764
+ const cpt = charsPerToken ?? model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN;
765
+ const modelCap = model.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY;
766
+ const windowCap = model.contextWindow > 0
767
+ ? Math.max(baseMaxTokens, model.contextWindow - estimateSummarizationInputTokens(context, cpt) - SUMMARY_WINDOW_MARGIN)
768
+ : Number.POSITIVE_INFINITY;
769
+ const cap = Math.min(modelCap, windowCap);
770
+ let maxTokens = Math.min(cap, model.reasoning ? Math.max(baseMaxTokens, SUMMARY_REASONING_FLOOR) : baseMaxTokens);
771
+ for (let attempt = 0;; attempt++) {
772
+ const canEscalate = attempt < SUMMARY_MAX_ESCALATIONS && maxTokens < cap;
773
+ const response = await completeSummarization(model, context, createSummarizationOptions(model, maxTokens, apiKey, headers, signal, thinkingLevel), streamFn, runtime);
774
+ if (response.stopReason === "aborted") {
775
+ return err(new CompactionError("aborted", response.errorMessage || `${label} aborted`));
776
+ }
777
+ if (response.stopReason === "error") {
778
+ if (response.errorKind === "length_empty") {
779
+ if (canEscalate) {
780
+ // Direct evidence the model reasons → jump to at least the floor (see header note (b)).
781
+ maxTokens = Math.min(cap, Math.max(maxTokens * 2, SUMMARY_REASONING_FLOOR));
782
+ continue;
783
+ }
784
+ // Unified diagnostics (codex review): an exhausted length_empty IS the empty-summary outcome —
785
+ // keep the C5 "empty summary" phrase so outer matchers see ONE contract for both empty paths.
786
+ return err(new CompactionError("summarization_failed", `${label} produced an empty summary (stopReason=error, max_tokens exhausted by reasoning ` +
787
+ `after ${attempt + 1} attempt(s): ${response.errorMessage || "no detail"})`));
788
+ }
789
+ return err(new CompactionError("summarization_failed", `${label} failed: ${response.errorMessage || "Unknown error"}`));
790
+ }
791
+ const lengthTruncated = response.stopReason === "length";
792
+ const raw = response.content
793
+ .filter((c) => c.type === "text")
794
+ .map((c) => c.text)
795
+ .join("\n");
796
+ const usable = stripAnalysisScratch(raw, lengthTruncated);
797
+ if (usable.trim() !== "") {
798
+ // Partial-but-present beats a skipped compaction. On a length cut return the text minus the
799
+ // provably-scratch unterminated tail; otherwise return raw (the persisted closed-pair strip is upstream).
800
+ return ok(lengthTruncated ? usable : raw);
801
+ }
802
+ if (lengthTruncated && canEscalate) {
803
+ maxTokens = Math.min(cap, Math.max(maxTokens * 2, SUMMARY_REASONING_FLOOR));
804
+ continue;
805
+ }
806
+ // Empty after the scratch strip and no (further) escalation: fail LOUDLY instead of returning "" — an
807
+ // empty ok() would reach compact()'s file-ops footer append and could persist a footer-only "summary"
808
+ // (the maybeCompact empty guard only sees the combined string). Wording keeps the C5 vendor-contract
809
+ // phrase "empty summary" (test/compaction.test.ts §26.7 pins it).
810
+ // Deliberate tradeoff (dual-track review): on the SPLIT-TURN path this also turns the old "empty
811
+ // turn-prefix quietly degrades to a landed history summary + dangling Turn-Context header" into a whole-
812
+ // boundary failure that counts toward maybeCompact's breaker. A silent half-summary hid real gateway
813
+ // flakiness; the breaker exists precisely to surface repeated summary failures.
814
+ return err(new CompactionError("summarization_failed", `${label} produced an empty summary (stopReason=${response.stopReason}` +
815
+ `${lengthTruncated ? ", the output was analysis scratch cut at max_tokens" : ""})`));
816
+ }
817
+ }
818
+ /** Generate or update a conversation summary for compaction. */
819
+ export async function generateSummary(currentMessages, model, reserveTokens, apiKey, headers, signal, customInstructions, previousSummary, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated) {
820
+ let basePrompt = previousSummary ? UPDATE_SUMMARIZATION_PROMPT : SUMMARIZATION_PROMPT;
821
+ if (customInstructions) {
822
+ // W:C6 — CC 198 verbatim injection shape (`\n\nAdditional Instructions:\n${e}`, three prompt家族一致).
823
+ basePrompt = `${basePrompt}\n\nAdditional Instructions:\n${customInstructions}`;
824
+ }
825
+ const llmMessages = convertToLlm(currentMessages);
826
+ // MF-18 修② + W:C16: the serialized conversation is bounded by the SUMMARY model's window BEFORE the
827
+ // call (clampSummarizationConversation, sema proactive superset) and, when the gateway's real
828
+ // tokenizer still rejects it, by the reactive PTL retry loop (CC 198 KNl family — see
829
+ // summarizeWithPtlRetry). Fixed parts = system prompt + instructions + previous summary
830
+ // + tag/format overhead — all sent verbatim, so they charge the budget at full length.
831
+ return summarizeWithPtlRetry({
832
+ label: "Summarization",
833
+ truncationLabel: "history",
834
+ llmMessages,
835
+ buildPromptText: (conversationText) => {
836
+ let promptText = `<conversation>\n${conversationText}\n</conversation>\n\n`;
837
+ if (previousSummary) {
838
+ promptText += `<previous-summary>\n${previousSummary}\n</previous-summary>\n\n`;
839
+ }
840
+ promptText += basePrompt;
841
+ return promptText;
842
+ },
843
+ model,
844
+ cpt: charsPerToken ?? model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN,
845
+ fixedPromptChars: SUMMARIZATION_SYSTEM_PROMPT.length + basePrompt.length + (previousSummary?.length ?? 0) + 128,
846
+ baseMaxTokens: Math.floor(0.8 * reserveTokens),
847
+ apiKey,
848
+ headers,
849
+ signal,
850
+ thinkingLevel,
851
+ streamFn,
852
+ runtime,
853
+ charsPerToken,
854
+ onInputTruncated,
855
+ });
856
+ }
857
+ /** Prepare session entries for compaction, or return undefined when compaction is not applicable.
858
+ * `charsPerToken` (design/123 D2, signature threading): keeps `tokensBefore` and the cut-point
859
+ * accounting in the same per-model structural coordinate as the caller's trigger estimate. */
860
+ export function prepareCompaction(pathEntries, settings, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
861
+ if (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === "compaction") {
862
+ return ok(undefined);
863
+ }
864
+ let prevCompactionIndex = -1;
865
+ for (let i = pathEntries.length - 1; i >= 0; i--) {
866
+ if (pathEntries[i].type === "compaction") {
867
+ prevCompactionIndex = i;
868
+ break;
869
+ }
870
+ }
871
+ let previousSummary;
872
+ let boundaryStart = 0;
873
+ if (prevCompactionIndex >= 0) {
874
+ const prevCompaction = pathEntries[prevCompactionIndex];
875
+ previousSummary = prevCompaction.summary;
876
+ const firstKeptEntryIndex = pathEntries.findIndex((entry) => entry.id === prevCompaction.firstKeptEntryId);
877
+ boundaryStart = firstKeptEntryIndex >= 0 ? firstKeptEntryIndex : prevCompactionIndex + 1;
878
+ }
879
+ const boundaryEnd = pathEntries.length;
880
+ const tokensBefore = estimateContextTokens(buildSessionContext(pathEntries).messages, charsPerToken).tokens;
881
+ const cutPoint = findCutPoint(pathEntries, boundaryStart, boundaryEnd, settings.keepRecentTokens, charsPerToken);
882
+ const firstKeptEntry = pathEntries[cutPoint.firstKeptEntryIndex];
883
+ if (!firstKeptEntry?.id) {
884
+ return err(new CompactionError("invalid_session", "First kept entry has no UUID - session may need migration"));
885
+ }
886
+ const firstKeptEntryId = firstKeptEntry.id;
887
+ const historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;
888
+ const messagesToSummarize = [];
889
+ for (let i = boundaryStart; i < historyEnd; i++) {
890
+ const msg = getMessageFromEntryForCompaction(pathEntries[i]);
891
+ if (msg) {
892
+ messagesToSummarize.push(msg);
893
+ }
894
+ }
895
+ const turnPrefixMessages = [];
896
+ if (cutPoint.isSplitTurn) {
897
+ for (let i = cutPoint.turnStartIndex; i < cutPoint.firstKeptEntryIndex; i++) {
898
+ const msg = getMessageFromEntryForCompaction(pathEntries[i]);
899
+ if (msg) {
900
+ turnPrefixMessages.push(msg);
901
+ }
902
+ }
903
+ }
904
+ // VENDORED EDIT (audit A-2 + R-2 round-3 council): compaction is NOT APPLICABLE when there is nothing
905
+ // to summarize at all — no prior history AND (not a split turn, OR a split turn whose prefix is ALSO
906
+ // empty). The original A-2 guard tested only `!isSplitTurn`, missing the split-turn-with-empty-prefix
907
+ // corner: there `compact()` falls through both branches to `generateSummary([])` and the model
908
+ // hallucinates a "summary" from nothing that ADDS tokens while freeing none. A split turn WITH a
909
+ // non-empty prefix is legitimately compactable (the prefix gets summarized), so it is NOT caught here.
910
+ // Return undefined so the caller treats it as a quiet no-op.
911
+ if (messagesToSummarize.length === 0 && (!cutPoint.isSplitTurn || turnPrefixMessages.length === 0)) {
912
+ return ok(undefined);
913
+ }
914
+ const fileOps = extractFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);
915
+ if (cutPoint.isSplitTurn) {
916
+ for (const msg of turnPrefixMessages) {
917
+ extractFileOpsFromMessage(msg, fileOps);
918
+ }
919
+ }
920
+ return ok({
921
+ firstKeptEntryId,
922
+ messagesToSummarize,
923
+ turnPrefixMessages,
924
+ isSplitTurn: cutPoint.isSplitTurn,
925
+ tokensBefore,
926
+ previousSummary,
927
+ fileOps,
928
+ settings,
929
+ });
930
+ }
931
+ const TURN_PREFIX_SUMMARIZATION_PROMPT = `This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.
932
+
933
+ Summarize the prefix to provide context for the retained suffix:
934
+
935
+ ## Original Request
936
+ [What did the user ask for in this turn?]
937
+
938
+ ## Early Progress
939
+ - [Key decisions and work done in the prefix]
940
+
941
+ ## Context for Suffix
942
+ - [Information needed to understand the retained recent work]
943
+
944
+ Be concise. Focus on what's needed to understand the kept suffix.`;
945
+ export { computeFileLists, serializeConversation } from "./utils.js";
946
+ /** Generate compaction summary data from prepared session history.
947
+ * `charsPerToken` (design/123 D2, signature threading): coefficient for the summarization-input
948
+ * window guard. Defaults to the SUMMARY model's own `charsPerToken` (the estimated input is sent to
949
+ * THAT model), then 4. */
950
+ export async function compact(preparation, model, apiKey, headers, customInstructions, signal, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated) {
951
+ const { firstKeptEntryId, messagesToSummarize, turnPrefixMessages, isSplitTurn, tokensBefore, previousSummary, fileOps, settings, } = preparation;
952
+ if (!firstKeptEntryId) {
953
+ return err(new CompactionError("invalid_session", "First kept entry has no UUID - session may need migration"));
954
+ }
955
+ // VENDORED EDIT (audit A-2 + R-2 round-3 council, defense-in-depth): an empty conversation must never
956
+ // reach generateSummary (the model hallucinates a "summary" from nothing that ADDS tokens, frees none).
957
+ // `prepareCompaction` returns undefined for this shape, so reaching here means a hand-constructed
958
+ // preparation — fail loudly. The condition mirrors the prepare guard: nothing to summarize AND no
959
+ // usable split-turn prefix (the split branch below needs `turnPrefixMessages.length > 0`; without it,
960
+ // an empty `messagesToSummarize` falls through to the else branch's `generateSummary([])`).
961
+ if (messagesToSummarize.length === 0 && (!isSplitTurn || turnPrefixMessages.length === 0)) {
962
+ return err(new CompactionError("summarization_failed", "Nothing to summarize (empty preparation)"));
963
+ }
964
+ let summary;
965
+ if (isSplitTurn && turnPrefixMessages.length > 0) {
966
+ const [historyResult, turnPrefixResult] = await Promise.all([
967
+ messagesToSummarize.length > 0
968
+ ? generateSummary(messagesToSummarize, model, settings.reserveTokens, apiKey, headers, signal, customInstructions, previousSummary, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated)
969
+ : // bug-hunt #1: a split-turn 2nd+ compaction where the cut splits the FIRST turn after the prior
970
+ // boundary leaves `messagesToSummarize` empty (historyEnd === boundaryStart) while `previousSummary`
971
+ // IS set. The old literal `"No prior history."` then fully SUPERSEDED the accumulated S1..Sn chain
972
+ // (buildSessionContext represents all pre-firstKept history with only the latest summary) — a silent,
973
+ // irreversible history erasure AND active contradiction on ordinary long tasks. With nothing new to
974
+ // fold in, the previous summary IS the complete history → thread it through verbatim (no model call,
975
+ // zero hallucination, faithful). Only truly-first compaction (no previousSummary) keeps the literal.
976
+ // Strip the prior summary's embedded file-ops footer (dual-review NIT): the canonical SUPERSET footer
977
+ // is re-appended below from `fileOps` (seeded with `prevCompaction.details`) — keeping the stale
978
+ // embedded one would duplicate it.
979
+ Promise.resolve(ok(previousSummary ? stripFileOperationsFooter(previousSummary) : "No prior history.")),
980
+ generateTurnPrefixSummary(turnPrefixMessages, model, settings.reserveTokens, apiKey, headers, signal, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated),
981
+ ]);
982
+ if (!historyResult.ok) {
983
+ return err(historyResult.error);
984
+ }
985
+ if (!turnPrefixResult.ok) {
986
+ return err(turnPrefixResult.error);
987
+ }
988
+ summary = `${historyResult.value}\n\n---\n\n**Turn Context (split turn):**\n\n${turnPrefixResult.value}`;
989
+ }
990
+ else {
991
+ const summaryResult = await generateSummary(messagesToSummarize, model, settings.reserveTokens, apiKey, headers, signal, customInstructions, previousSummary, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated);
992
+ if (!summaryResult.ok) {
993
+ return err(summaryResult.error);
994
+ }
995
+ summary = summaryResult.value;
996
+ }
997
+ const { readFiles, modifiedFiles, modifiedFilesByRecency } = computeFileLists(fileOps);
998
+ summary += formatFileOperations(readFiles, modifiedFiles);
999
+ return ok({
1000
+ summary,
1001
+ firstKeptEntryId,
1002
+ tokensBefore,
1003
+ details: { readFiles, modifiedFiles, modifiedFilesByRecency },
1004
+ });
1005
+ }
1006
+ async function generateTurnPrefixSummary(messages, model, reserveTokens, apiKey, headers, signal, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated) {
1007
+ const llmMessages = convertToLlm(messages);
1008
+ // MF-18 修② + W:C16: same window bound + reactive PTL retry as generateSummary — the live-caught
1009
+ // failure mode hit BOTH summary paths (an oversized split-turn prefix is rarer but identical in
1010
+ // effect: gateway prompt-too-long).
1011
+ return summarizeWithPtlRetry({
1012
+ label: "Turn prefix summarization",
1013
+ truncationLabel: "turn_prefix",
1014
+ llmMessages,
1015
+ buildPromptText: (conversationText) => `<conversation>\n${conversationText}\n</conversation>\n\n${TURN_PREFIX_SUMMARIZATION_PROMPT}`,
1016
+ model,
1017
+ cpt: charsPerToken ?? model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN,
1018
+ fixedPromptChars: SUMMARIZATION_SYSTEM_PROMPT.length + TURN_PREFIX_SUMMARIZATION_PROMPT.length + 128,
1019
+ baseMaxTokens: Math.floor(0.5 * reserveTokens),
1020
+ apiKey,
1021
+ headers,
1022
+ signal,
1023
+ thinkingLevel,
1024
+ streamFn,
1025
+ runtime,
1026
+ charsPerToken,
1027
+ onInputTruncated,
1028
+ });
1029
+ }
1030
+ //# sourceMappingURL=compaction.js.map