open-multi-agent-kit 0.99.0 → 1.2.0

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 (464) hide show
  1. package/CHANGELOG.md +30 -1
  2. package/README.md +3 -3
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js +1 -0
  5. package/dist/bun/cli.js.map +1 -1
  6. package/dist/bun/register-bundled-coding-agent.d.ts +10 -0
  7. package/dist/bun/register-bundled-coding-agent.d.ts.map +1 -0
  8. package/dist/bun/register-bundled-coding-agent.js +12 -0
  9. package/dist/bun/register-bundled-coding-agent.js.map +1 -0
  10. package/dist/cli/args.d.ts +1 -1
  11. package/dist/cli/args.d.ts.map +1 -1
  12. package/dist/cli/args.js +1 -1
  13. package/dist/cli/args.js.map +1 -1
  14. package/dist/cli/help.d.ts.map +1 -1
  15. package/dist/cli/help.js +2 -1
  16. package/dist/cli/help.js.map +1 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +14 -2
  19. package/dist/cli.js.map +1 -1
  20. package/dist/commands/neo-cli.d.ts +9 -0
  21. package/dist/commands/neo-cli.d.ts.map +1 -0
  22. package/dist/commands/neo-cli.js +61 -0
  23. package/dist/commands/neo-cli.js.map +1 -0
  24. package/dist/coordination/awareness.d.ts +32 -0
  25. package/dist/coordination/awareness.d.ts.map +1 -0
  26. package/dist/coordination/awareness.js +55 -0
  27. package/dist/coordination/awareness.js.map +1 -0
  28. package/dist/coordination/broker.d.ts +79 -0
  29. package/dist/coordination/broker.d.ts.map +1 -0
  30. package/dist/coordination/broker.js +195 -0
  31. package/dist/coordination/broker.js.map +1 -0
  32. package/dist/coordination/index.d.ts +16 -0
  33. package/dist/coordination/index.d.ts.map +1 -0
  34. package/dist/coordination/index.js +16 -0
  35. package/dist/coordination/index.js.map +1 -0
  36. package/dist/coordination/integration.d.ts +59 -0
  37. package/dist/coordination/integration.d.ts.map +1 -0
  38. package/dist/coordination/integration.js +126 -0
  39. package/dist/coordination/integration.js.map +1 -0
  40. package/dist/coordination/operation.d.ts +106 -0
  41. package/dist/coordination/operation.d.ts.map +1 -0
  42. package/dist/coordination/operation.js +179 -0
  43. package/dist/coordination/operation.js.map +1 -0
  44. package/dist/coordination/resource.d.ts +33 -0
  45. package/dist/coordination/resource.d.ts.map +1 -0
  46. package/dist/coordination/resource.js +89 -0
  47. package/dist/coordination/resource.js.map +1 -0
  48. package/dist/coordination/session.d.ts +74 -0
  49. package/dist/coordination/session.d.ts.map +1 -0
  50. package/dist/coordination/session.js +143 -0
  51. package/dist/coordination/session.js.map +1 -0
  52. package/dist/coordination/types.d.ts +68 -0
  53. package/dist/coordination/types.d.ts.map +1 -0
  54. package/dist/coordination/types.js +26 -0
  55. package/dist/coordination/types.js.map +1 -0
  56. package/dist/core/agent-session.d.ts +29 -2
  57. package/dist/core/agent-session.d.ts.map +1 -1
  58. package/dist/core/agent-session.js +135 -37
  59. package/dist/core/agent-session.js.map +1 -1
  60. package/dist/core/bundled-skills.d.ts +4 -0
  61. package/dist/core/bundled-skills.d.ts.map +1 -0
  62. package/dist/core/bundled-skills.js +32 -0
  63. package/dist/core/bundled-skills.js.map +1 -0
  64. package/dist/core/cli-diagnostics.d.ts +6 -0
  65. package/dist/core/cli-diagnostics.d.ts.map +1 -0
  66. package/dist/core/cli-diagnostics.js +20 -0
  67. package/dist/core/cli-diagnostics.js.map +1 -0
  68. package/dist/core/compaction/control-state.d.ts +41 -0
  69. package/dist/core/compaction/control-state.d.ts.map +1 -0
  70. package/dist/core/compaction/control-state.js +85 -0
  71. package/dist/core/compaction/control-state.js.map +1 -0
  72. package/dist/core/compaction/fallback.d.ts +60 -0
  73. package/dist/core/compaction/fallback.d.ts.map +1 -0
  74. package/dist/core/compaction/fallback.js +117 -0
  75. package/dist/core/compaction/fallback.js.map +1 -0
  76. package/dist/core/compaction/index.d.ts +2 -0
  77. package/dist/core/compaction/index.d.ts.map +1 -1
  78. package/dist/core/compaction/index.js +2 -0
  79. package/dist/core/compaction/index.js.map +1 -1
  80. package/dist/core/context-budget-headroom-candidates.d.ts +16 -1
  81. package/dist/core/context-budget-headroom-candidates.d.ts.map +1 -1
  82. package/dist/core/context-budget-headroom-candidates.js +31 -13
  83. package/dist/core/context-budget-headroom-candidates.js.map +1 -1
  84. package/dist/core/context-budget-headroom-types.d.ts +7 -1
  85. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  86. package/dist/core/context-budget-headroom-types.js +0 -1
  87. package/dist/core/context-budget-headroom-types.js.map +1 -1
  88. package/dist/core/context-budget-headroom.d.ts +22 -0
  89. package/dist/core/context-budget-headroom.d.ts.map +1 -1
  90. package/dist/core/context-budget-headroom.js +46 -2
  91. package/dist/core/context-budget-headroom.js.map +1 -1
  92. package/dist/core/context-budget-v2-global-pass.d.ts +21 -0
  93. package/dist/core/context-budget-v2-global-pass.d.ts.map +1 -0
  94. package/dist/core/context-budget-v2-global-pass.js +203 -0
  95. package/dist/core/context-budget-v2-global-pass.js.map +1 -0
  96. package/dist/core/context-budget-v2-input-validation.d.ts +4 -0
  97. package/dist/core/context-budget-v2-input-validation.d.ts.map +1 -0
  98. package/dist/core/context-budget-v2-input-validation.js +79 -0
  99. package/dist/core/context-budget-v2-input-validation.js.map +1 -0
  100. package/dist/core/context-budget-v2-observability.d.ts +15 -0
  101. package/dist/core/context-budget-v2-observability.d.ts.map +1 -0
  102. package/dist/core/context-budget-v2-observability.js +35 -0
  103. package/dist/core/context-budget-v2-observability.js.map +1 -0
  104. package/dist/core/context-budget-v2-planned-items.d.ts +17 -0
  105. package/dist/core/context-budget-v2-planned-items.d.ts.map +1 -0
  106. package/dist/core/context-budget-v2-planned-items.js +59 -0
  107. package/dist/core/context-budget-v2-planned-items.js.map +1 -0
  108. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  109. package/dist/core/context-budget-v2-planner.js +69 -51
  110. package/dist/core/context-budget-v2-planner.js.map +1 -1
  111. package/dist/core/context-budget-v2-scoring.d.ts +7 -1
  112. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  113. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  114. package/dist/core/context-budget-v2-selection.d.ts +22 -3
  115. package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
  116. package/dist/core/context-budget-v2-selection.js +41 -59
  117. package/dist/core/context-budget-v2-selection.js.map +1 -1
  118. package/dist/core/context-budget-v2-tiers.d.ts.map +1 -1
  119. package/dist/core/context-budget-v2-tiers.js +9 -42
  120. package/dist/core/context-budget-v2-tiers.js.map +1 -1
  121. package/dist/core/context-budget-v2-types.d.ts +14 -2
  122. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  123. package/dist/core/context-budget-v2-types.js +6 -1
  124. package/dist/core/context-budget-v2-types.js.map +1 -1
  125. package/dist/core/extensions/bundled-virtual-modules.d.ts +15 -0
  126. package/dist/core/extensions/bundled-virtual-modules.d.ts.map +1 -0
  127. package/dist/core/extensions/bundled-virtual-modules.js +63 -0
  128. package/dist/core/extensions/bundled-virtual-modules.js.map +1 -0
  129. package/dist/core/extensions/loader.d.ts.map +1 -1
  130. package/dist/core/extensions/loader.js +2 -42
  131. package/dist/core/extensions/loader.js.map +1 -1
  132. package/dist/core/extensions/runner.d.ts +1 -0
  133. package/dist/core/extensions/runner.d.ts.map +1 -1
  134. package/dist/core/extensions/runner.js +6 -0
  135. package/dist/core/extensions/runner.js.map +1 -1
  136. package/dist/core/extensions/types.d.ts +10 -0
  137. package/dist/core/extensions/types.d.ts.map +1 -1
  138. package/dist/core/extensions/types.js.map +1 -1
  139. package/dist/core/index.d.ts +2 -1
  140. package/dist/core/index.d.ts.map +1 -1
  141. package/dist/core/index.js +2 -1
  142. package/dist/core/index.js.map +1 -1
  143. package/dist/core/loadout-runtime.d.ts +2 -8
  144. package/dist/core/loadout-runtime.d.ts.map +1 -1
  145. package/dist/core/loadout-runtime.js.map +1 -1
  146. package/dist/core/mcp/client.d.ts +27 -6
  147. package/dist/core/mcp/client.d.ts.map +1 -1
  148. package/dist/core/mcp/client.js +80 -20
  149. package/dist/core/mcp/client.js.map +1 -1
  150. package/dist/core/mcp/manager.d.ts +10 -1
  151. package/dist/core/mcp/manager.d.ts.map +1 -1
  152. package/dist/core/mcp/manager.js +68 -9
  153. package/dist/core/mcp/manager.js.map +1 -1
  154. package/dist/core/mcp/protocol.d.ts +9 -3
  155. package/dist/core/mcp/protocol.d.ts.map +1 -1
  156. package/dist/core/mcp/protocol.js +61 -15
  157. package/dist/core/mcp/protocol.js.map +1 -1
  158. package/dist/core/mcp/stdio-transport.d.ts +12 -1
  159. package/dist/core/mcp/stdio-transport.d.ts.map +1 -1
  160. package/dist/core/mcp/stdio-transport.js +30 -2
  161. package/dist/core/mcp/stdio-transport.js.map +1 -1
  162. package/dist/core/mcp-descriptor-injection.d.ts +26 -0
  163. package/dist/core/mcp-descriptor-injection.d.ts.map +1 -0
  164. package/dist/core/mcp-descriptor-injection.js +25 -0
  165. package/dist/core/mcp-descriptor-injection.js.map +1 -0
  166. package/dist/core/mcp-public-presets.d.ts +1 -3
  167. package/dist/core/mcp-public-presets.d.ts.map +1 -1
  168. package/dist/core/mcp-public-presets.js +3 -15
  169. package/dist/core/mcp-public-presets.js.map +1 -1
  170. package/dist/core/model-registry.d.ts.map +1 -1
  171. package/dist/core/model-registry.js +24 -3
  172. package/dist/core/model-registry.js.map +1 -1
  173. package/dist/core/neo/catalog.d.ts +20 -0
  174. package/dist/core/neo/catalog.d.ts.map +1 -0
  175. package/dist/core/neo/catalog.js +50 -0
  176. package/dist/core/neo/catalog.js.map +1 -0
  177. package/dist/core/neo/setup.d.ts +3 -0
  178. package/dist/core/neo/setup.d.ts.map +1 -0
  179. package/dist/core/neo/setup.js +47 -0
  180. package/dist/core/neo/setup.js.map +1 -0
  181. package/dist/core/provider-default-models.d.ts +2 -0
  182. package/dist/core/provider-default-models.d.ts.map +1 -1
  183. package/dist/core/provider-default-models.js +2 -0
  184. package/dist/core/provider-default-models.js.map +1 -1
  185. package/dist/core/provider-display-names.d.ts.map +1 -1
  186. package/dist/core/provider-display-names.js +2 -0
  187. package/dist/core/provider-display-names.js.map +1 -1
  188. package/dist/core/provider-error-classification.d.ts +57 -0
  189. package/dist/core/provider-error-classification.d.ts.map +1 -0
  190. package/dist/core/provider-error-classification.js +103 -0
  191. package/dist/core/provider-error-classification.js.map +1 -0
  192. package/dist/core/provider-resilience.d.ts +10 -0
  193. package/dist/core/provider-resilience.d.ts.map +1 -1
  194. package/dist/core/provider-resilience.js +36 -3
  195. package/dist/core/provider-resilience.js.map +1 -1
  196. package/dist/core/provider-usage-commandcode.d.ts +9 -0
  197. package/dist/core/provider-usage-commandcode.d.ts.map +1 -0
  198. package/dist/core/provider-usage-commandcode.js +198 -0
  199. package/dist/core/provider-usage-commandcode.js.map +1 -0
  200. package/dist/core/provider-usage-devin.d.ts +5 -3
  201. package/dist/core/provider-usage-devin.d.ts.map +1 -1
  202. package/dist/core/provider-usage-devin.js +15 -5
  203. package/dist/core/provider-usage-devin.js.map +1 -1
  204. package/dist/core/provider-usage-types.d.ts +1 -1
  205. package/dist/core/provider-usage-types.d.ts.map +1 -1
  206. package/dist/core/provider-usage-types.js.map +1 -1
  207. package/dist/core/provider-usage.d.ts.map +1 -1
  208. package/dist/core/provider-usage.js +6 -0
  209. package/dist/core/provider-usage.js.map +1 -1
  210. package/dist/core/reasoning-router-resolver.d.ts +7 -0
  211. package/dist/core/reasoning-router-resolver.d.ts.map +1 -1
  212. package/dist/core/reasoning-router-resolver.js +21 -3
  213. package/dist/core/reasoning-router-resolver.js.map +1 -1
  214. package/dist/core/reasoning-router-v4.d.ts +8 -5
  215. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  216. package/dist/core/reasoning-router-v4.js +8 -5
  217. package/dist/core/reasoning-router-v4.js.map +1 -1
  218. package/dist/core/resource-admission.d.ts +36 -0
  219. package/dist/core/resource-admission.d.ts.map +1 -1
  220. package/dist/core/resource-admission.js +59 -0
  221. package/dist/core/resource-admission.js.map +1 -1
  222. package/dist/core/resource-loader.d.ts.map +1 -1
  223. package/dist/core/resource-loader.js +2 -2
  224. package/dist/core/resource-loader.js.map +1 -1
  225. package/dist/core/run-usage-ledger.d.ts +47 -0
  226. package/dist/core/run-usage-ledger.d.ts.map +1 -0
  227. package/dist/core/run-usage-ledger.js +162 -0
  228. package/dist/core/run-usage-ledger.js.map +1 -0
  229. package/dist/core/run-usage-operation.d.ts +8 -0
  230. package/dist/core/run-usage-operation.d.ts.map +1 -0
  231. package/dist/core/run-usage-operation.js +12 -0
  232. package/dist/core/run-usage-operation.js.map +1 -0
  233. package/dist/core/sdk.d.ts.map +1 -1
  234. package/dist/core/sdk.js +5 -6
  235. package/dist/core/sdk.js.map +1 -1
  236. package/dist/core/session-compaction-service.d.ts +15 -0
  237. package/dist/core/session-compaction-service.d.ts.map +1 -1
  238. package/dist/core/session-compaction-service.js +17 -4
  239. package/dist/core/session-compaction-service.js.map +1 -1
  240. package/dist/core/session-failure-cause.d.ts.map +1 -1
  241. package/dist/core/session-failure-cause.js +14 -5
  242. package/dist/core/session-failure-cause.js.map +1 -1
  243. package/dist/core/session-prompt-lifecycle.d.ts +6 -0
  244. package/dist/core/session-prompt-lifecycle.d.ts.map +1 -1
  245. package/dist/core/session-prompt-lifecycle.js +47 -2
  246. package/dist/core/session-prompt-lifecycle.js.map +1 -1
  247. package/dist/core/session-termination.d.ts.map +1 -1
  248. package/dist/core/session-termination.js +4 -2
  249. package/dist/core/session-termination.js.map +1 -1
  250. package/dist/core/subagent-lane-authority.d.ts +28 -0
  251. package/dist/core/subagent-lane-authority.d.ts.map +1 -0
  252. package/dist/core/subagent-lane-authority.js +119 -0
  253. package/dist/core/subagent-lane-authority.js.map +1 -0
  254. package/dist/core/subagent-lane-contract.d.ts +114 -0
  255. package/dist/core/subagent-lane-contract.d.ts.map +1 -0
  256. package/dist/core/subagent-lane-contract.js +18 -0
  257. package/dist/core/subagent-lane-contract.js.map +1 -0
  258. package/dist/core/subagent-lane-launcher.d.ts +3 -6
  259. package/dist/core/subagent-lane-launcher.d.ts.map +1 -1
  260. package/dist/core/subagent-lane-launcher.js +53 -12
  261. package/dist/core/subagent-lane-launcher.js.map +1 -1
  262. package/dist/core/subagent-orchestration.d.ts +4 -17
  263. package/dist/core/subagent-orchestration.d.ts.map +1 -1
  264. package/dist/core/subagent-orchestration.js.map +1 -1
  265. package/dist/core/todo-runtime-state.d.ts +12 -0
  266. package/dist/core/todo-runtime-state.d.ts.map +1 -1
  267. package/dist/core/todo-runtime-state.js +23 -0
  268. package/dist/core/todo-runtime-state.js.map +1 -1
  269. package/dist/core/verified-run/broker.d.ts.map +1 -1
  270. package/dist/core/verified-run/broker.js +4 -1
  271. package/dist/core/verified-run/broker.js.map +1 -1
  272. package/dist/core/workload-permit-pool.d.ts +1 -1
  273. package/dist/core/workload-permit-pool.d.ts.map +1 -1
  274. package/dist/core/workload-permit-pool.js +3 -0
  275. package/dist/core/workload-permit-pool.js.map +1 -1
  276. package/dist/guardrails/strict-evidence-approval-adapter.d.ts +34 -0
  277. package/dist/guardrails/strict-evidence-approval-adapter.d.ts.map +1 -0
  278. package/dist/guardrails/strict-evidence-approval-adapter.js +70 -0
  279. package/dist/guardrails/strict-evidence-approval-adapter.js.map +1 -0
  280. package/dist/index.d.ts +5 -0
  281. package/dist/index.d.ts.map +1 -1
  282. package/dist/index.js +3 -0
  283. package/dist/index.js.map +1 -1
  284. package/dist/main.d.ts.map +1 -1
  285. package/dist/main.js +11 -18
  286. package/dist/main.js.map +1 -1
  287. package/dist/metacognition/calibration-selective.d.ts +78 -0
  288. package/dist/metacognition/calibration-selective.d.ts.map +1 -0
  289. package/dist/metacognition/calibration-selective.js +161 -0
  290. package/dist/metacognition/calibration-selective.js.map +1 -0
  291. package/dist/metacognition/calibration.d.ts +62 -0
  292. package/dist/metacognition/calibration.d.ts.map +1 -0
  293. package/dist/metacognition/calibration.js +122 -0
  294. package/dist/metacognition/calibration.js.map +1 -0
  295. package/dist/metacognition/checkpoint.d.ts +60 -0
  296. package/dist/metacognition/checkpoint.d.ts.map +1 -0
  297. package/dist/metacognition/checkpoint.js +57 -0
  298. package/dist/metacognition/checkpoint.js.map +1 -0
  299. package/dist/metacognition/context7.d.ts +48 -0
  300. package/dist/metacognition/context7.d.ts.map +1 -0
  301. package/dist/metacognition/context7.js +154 -0
  302. package/dist/metacognition/context7.js.map +1 -0
  303. package/dist/metacognition/decision.d.ts +44 -0
  304. package/dist/metacognition/decision.d.ts.map +1 -0
  305. package/dist/metacognition/decision.js +111 -0
  306. package/dist/metacognition/decision.js.map +1 -0
  307. package/dist/metacognition/evaluation.d.ts +73 -0
  308. package/dist/metacognition/evaluation.d.ts.map +1 -0
  309. package/dist/metacognition/evaluation.js +97 -0
  310. package/dist/metacognition/evaluation.js.map +1 -0
  311. package/dist/metacognition/index.d.ts +31 -0
  312. package/dist/metacognition/index.d.ts.map +1 -0
  313. package/dist/metacognition/index.js +31 -0
  314. package/dist/metacognition/index.js.map +1 -0
  315. package/dist/metacognition/knowledge-action.d.ts +43 -0
  316. package/dist/metacognition/knowledge-action.d.ts.map +1 -0
  317. package/dist/metacognition/knowledge-action.js +60 -0
  318. package/dist/metacognition/knowledge-action.js.map +1 -0
  319. package/dist/metacognition/knowledge.d.ts +84 -0
  320. package/dist/metacognition/knowledge.d.ts.map +1 -0
  321. package/dist/metacognition/knowledge.js +165 -0
  322. package/dist/metacognition/knowledge.js.map +1 -0
  323. package/dist/metacognition/obligations.d.ts +82 -0
  324. package/dist/metacognition/obligations.d.ts.map +1 -0
  325. package/dist/metacognition/obligations.js +139 -0
  326. package/dist/metacognition/obligations.js.map +1 -0
  327. package/dist/metacognition/observation-validity.d.ts +83 -0
  328. package/dist/metacognition/observation-validity.d.ts.map +1 -0
  329. package/dist/metacognition/observation-validity.js +118 -0
  330. package/dist/metacognition/observation-validity.js.map +1 -0
  331. package/dist/metacognition/observe.d.ts +45 -0
  332. package/dist/metacognition/observe.d.ts.map +1 -0
  333. package/dist/metacognition/observe.js +59 -0
  334. package/dist/metacognition/observe.js.map +1 -0
  335. package/dist/metacognition/policy.d.ts +53 -0
  336. package/dist/metacognition/policy.d.ts.map +1 -0
  337. package/dist/metacognition/policy.js +155 -0
  338. package/dist/metacognition/policy.js.map +1 -0
  339. package/dist/metacognition/predictions.d.ts +78 -0
  340. package/dist/metacognition/predictions.d.ts.map +1 -0
  341. package/dist/metacognition/predictions.js +181 -0
  342. package/dist/metacognition/predictions.js.map +1 -0
  343. package/dist/metacognition/retrieval.d.ts +53 -0
  344. package/dist/metacognition/retrieval.d.ts.map +1 -0
  345. package/dist/metacognition/retrieval.js +170 -0
  346. package/dist/metacognition/retrieval.js.map +1 -0
  347. package/dist/metacognition/risk.d.ts +48 -0
  348. package/dist/metacognition/risk.d.ts.map +1 -0
  349. package/dist/metacognition/risk.js +165 -0
  350. package/dist/metacognition/risk.js.map +1 -0
  351. package/dist/metacognition/route-economics.d.ts +95 -0
  352. package/dist/metacognition/route-economics.d.ts.map +1 -0
  353. package/dist/metacognition/route-economics.js +110 -0
  354. package/dist/metacognition/route-economics.js.map +1 -0
  355. package/dist/metacognition/runtime-bridge.d.ts +54 -0
  356. package/dist/metacognition/runtime-bridge.d.ts.map +1 -0
  357. package/dist/metacognition/runtime-bridge.js +140 -0
  358. package/dist/metacognition/runtime-bridge.js.map +1 -0
  359. package/dist/metacognition/skills.d.ts +42 -0
  360. package/dist/metacognition/skills.d.ts.map +1 -0
  361. package/dist/metacognition/skills.js +220 -0
  362. package/dist/metacognition/skills.js.map +1 -0
  363. package/dist/metacognition/state.d.ts +110 -0
  364. package/dist/metacognition/state.d.ts.map +1 -0
  365. package/dist/metacognition/state.js +52 -0
  366. package/dist/metacognition/state.js.map +1 -0
  367. package/dist/metacognition/validation.d.ts +19 -0
  368. package/dist/metacognition/validation.d.ts.map +1 -0
  369. package/dist/metacognition/validation.js +58 -0
  370. package/dist/metacognition/validation.js.map +1 -0
  371. package/dist/metacognition/verification.d.ts +93 -0
  372. package/dist/metacognition/verification.d.ts.map +1 -0
  373. package/dist/metacognition/verification.js +132 -0
  374. package/dist/metacognition/verification.js.map +1 -0
  375. package/dist/metacognition/verifier.d.ts +49 -0
  376. package/dist/metacognition/verifier.d.ts.map +1 -0
  377. package/dist/metacognition/verifier.js +88 -0
  378. package/dist/metacognition/verifier.js.map +1 -0
  379. package/dist/modes/acp/acp-agent.d.ts +24 -0
  380. package/dist/modes/acp/acp-agent.d.ts.map +1 -0
  381. package/dist/modes/acp/acp-agent.js +133 -0
  382. package/dist/modes/acp/acp-agent.js.map +1 -0
  383. package/dist/modes/acp/acp-mode.d.ts +4 -0
  384. package/dist/modes/acp/acp-mode.d.ts.map +1 -0
  385. package/dist/modes/acp/acp-mode.js +34 -0
  386. package/dist/modes/acp/acp-mode.js.map +1 -0
  387. package/dist/modes/acp/acp-session.d.ts +4 -0
  388. package/dist/modes/acp/acp-session.d.ts.map +1 -0
  389. package/dist/modes/acp/acp-session.js +76 -0
  390. package/dist/modes/acp/acp-session.js.map +1 -0
  391. package/dist/modes/acp/acp-transport.d.ts +5 -0
  392. package/dist/modes/acp/acp-transport.d.ts.map +1 -0
  393. package/dist/modes/acp/acp-transport.js +90 -0
  394. package/dist/modes/acp/acp-transport.js.map +1 -0
  395. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  396. package/dist/modes/interactive/interactive-mode.js +1 -0
  397. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  398. package/dist/observation/identity.d.ts +14 -0
  399. package/dist/observation/identity.d.ts.map +1 -0
  400. package/dist/observation/identity.js +29 -0
  401. package/dist/observation/identity.js.map +1 -0
  402. package/dist/observation/index.d.ts +13 -0
  403. package/dist/observation/index.d.ts.map +1 -0
  404. package/dist/observation/index.js +13 -0
  405. package/dist/observation/index.js.map +1 -0
  406. package/dist/observation/observe-mode.d.ts +46 -0
  407. package/dist/observation/observe-mode.d.ts.map +1 -0
  408. package/dist/observation/observe-mode.js +83 -0
  409. package/dist/observation/observe-mode.js.map +1 -0
  410. package/dist/observation/store.d.ts +53 -0
  411. package/dist/observation/store.d.ts.map +1 -0
  412. package/dist/observation/store.js +126 -0
  413. package/dist/observation/store.js.map +1 -0
  414. package/dist/observation/types.d.ts +72 -0
  415. package/dist/observation/types.d.ts.map +1 -0
  416. package/dist/observation/types.js +9 -0
  417. package/dist/observation/types.js.map +1 -0
  418. package/dist/observation/view.d.ts +39 -0
  419. package/dist/observation/view.d.ts.map +1 -0
  420. package/dist/observation/view.js +173 -0
  421. package/dist/observation/view.js.map +1 -0
  422. package/docs/audit-revalidation-2026-09-17.md +77 -0
  423. package/docs/devin-harness.md +33 -4
  424. package/docs/ecraf-normalization.md +83 -0
  425. package/docs/metacognition.md +51 -0
  426. package/docs/model-catalog-refresh.md +110 -1
  427. package/docs/models.md +1 -1
  428. package/docs/neo.md +134 -0
  429. package/docs/providers.md +125 -6
  430. package/docs/run-usage-ledger.md +56 -0
  431. package/docs/runtime-algorithms.md +151 -3
  432. package/docs/skills.md +1 -1
  433. package/docs/usage.md +2 -1
  434. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  435. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  436. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  437. package/examples/extensions/gondolin/package-lock.json +2 -2
  438. package/examples/extensions/gondolin/package.json +1 -1
  439. package/examples/extensions/sandbox/package-lock.json +2 -2
  440. package/examples/extensions/sandbox/package.json +1 -1
  441. package/examples/extensions/subagent/adaptive-agent-runtime.ts +14 -1
  442. package/examples/extensions/subagent/graph-result.ts +48 -0
  443. package/examples/extensions/subagent/index.ts +246 -111
  444. package/examples/extensions/subagent/managed-process-tree.ts +42 -0
  445. package/examples/extensions/subagent/managed-process.test.ts +24 -0
  446. package/examples/extensions/subagent/managed-process.ts +93 -112
  447. package/examples/extensions/subagent/subagent-runtime-types.ts +17 -1
  448. package/examples/extensions/subagent/subagent-stream.ts +161 -0
  449. package/examples/extensions/terminal-browser/README.md +54 -0
  450. package/examples/extensions/terminal-browser/bridge-protocol.ts +29 -0
  451. package/examples/extensions/terminal-browser/bridge.ts +219 -0
  452. package/examples/extensions/terminal-browser/browser-surface.ts +288 -0
  453. package/examples/extensions/terminal-browser/index.ts +215 -0
  454. package/examples/extensions/terminal-browser/placeholders.ts +49 -0
  455. package/examples/extensions/with-deps/package-lock.json +2 -2
  456. package/examples/extensions/with-deps/package.json +1 -1
  457. package/npm-shrinkwrap.json +18 -18
  458. package/package.json +8 -7
  459. package/resources/neo/skills/omk-browser/SKILL.md +32 -0
  460. package/resources/neo/skills/omk-code-review/SKILL.md +24 -0
  461. package/resources/neo/skills/omk-computeruse/SKILL.md +34 -0
  462. package/resources/neo/skills/omk-mcp-setup/SKILL.md +48 -0
  463. package/resources/neo/skills/omk-research/SKILL.md +24 -0
  464. package/resources/neo/skills/omk-site/SKILL.md +28 -0
@@ -0,0 +1,4 @@
1
+ import { type LoadSkillsOptions, type LoadSkillsResult } from "./skills.ts";
2
+ /** User/project/explicit skills keep ownership of names. Bundled instructions grant no tool authority. */
3
+ export declare function loadSkillsWithBundled(noSkills: boolean, options: LoadSkillsOptions): LoadSkillsResult;
4
+ //# sourceMappingURL=bundled-skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundled-skills.d.ts","sourceRoot":"","sources":["../../src/core/bundled-skills.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAiC,MAAM,aAAa,CAAC;AAI3G,0GAA0G;AAC1G,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAuBrG","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getPackageDir } from \"../config.ts\";\nimport { type LoadSkillsOptions, type LoadSkillsResult, loadSkills, loadSkillsFromDir } from \"./skills.ts\";\n\nconst DISABLED = new Set([\"0\", \"false\", \"off\", \"disable\", \"disabled\"]);\n\n/** User/project/explicit skills keep ownership of names. Bundled instructions grant no tool authority. */\nexport function loadSkillsWithBundled(noSkills: boolean, options: LoadSkillsOptions): LoadSkillsResult {\n\tconst selected = loadSkills(options);\n\tif (noSkills || DISABLED.has((process.env.OMK_BUNDLED_SKILLS ?? \"\").trim().toLowerCase())) return selected;\n\tconst dir = join(getPackageDir(), \"resources\", \"neo\", \"skills\");\n\tif (!existsSync(dir)) {\n\t\treturn {\n\t\t\t...selected,\n\t\t\tdiagnostics: [\n\t\t\t\t...selected.diagnostics,\n\t\t\t\t{\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tpath: dir,\n\t\t\t\t\tmessage: \"Bundled Neo skills are missing from this installation; reinstall a complete package.\",\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\tconst bundled = loadSkillsFromDir({ dir, source: \"builtin\" });\n\tconst occupied = new Set(selected.skills.map((skill) => skill.name));\n\treturn {\n\t\tskills: [...selected.skills, ...bundled.skills.filter((skill) => !occupied.has(skill.name))],\n\t\tdiagnostics: [...selected.diagnostics, ...bundled.diagnostics],\n\t};\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { getPackageDir } from "../config.js";
4
+ import { loadSkills, loadSkillsFromDir } from "./skills.js";
5
+ const DISABLED = new Set(["0", "false", "off", "disable", "disabled"]);
6
+ /** User/project/explicit skills keep ownership of names. Bundled instructions grant no tool authority. */
7
+ export function loadSkillsWithBundled(noSkills, options) {
8
+ const selected = loadSkills(options);
9
+ if (noSkills || DISABLED.has((process.env.OMK_BUNDLED_SKILLS ?? "").trim().toLowerCase()))
10
+ return selected;
11
+ const dir = join(getPackageDir(), "resources", "neo", "skills");
12
+ if (!existsSync(dir)) {
13
+ return {
14
+ ...selected,
15
+ diagnostics: [
16
+ ...selected.diagnostics,
17
+ {
18
+ type: "warning",
19
+ path: dir,
20
+ message: "Bundled Neo skills are missing from this installation; reinstall a complete package.",
21
+ },
22
+ ],
23
+ };
24
+ }
25
+ const bundled = loadSkillsFromDir({ dir, source: "builtin" });
26
+ const occupied = new Set(selected.skills.map((skill) => skill.name));
27
+ return {
28
+ skills: [...selected.skills, ...bundled.skills.filter((skill) => !occupied.has(skill.name))],
29
+ diagnostics: [...selected.diagnostics, ...bundled.diagnostics],
30
+ };
31
+ }
32
+ //# sourceMappingURL=bundled-skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundled-skills.js","sourceRoot":"","sources":["../../src/core/bundled-skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAiD,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE3G,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;AAEvE,0GAA0G;AAC1G,MAAM,UAAU,qBAAqB,CAAC,QAAiB,EAAE,OAA0B,EAAoB;IACtG,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC3G,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO;YACN,GAAG,QAAQ;YACX,WAAW,EAAE;gBACZ,GAAG,QAAQ,CAAC,WAAW;gBACvB;oBACC,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,GAAG;oBACT,OAAO,EAAE,sFAAsF;iBAC/F;aACD;SACD,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,OAAO;QACN,MAAM,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5F,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;KAC9D,CAAC;AAAA,CACF","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getPackageDir } from \"../config.ts\";\nimport { type LoadSkillsOptions, type LoadSkillsResult, loadSkills, loadSkillsFromDir } from \"./skills.ts\";\n\nconst DISABLED = new Set([\"0\", \"false\", \"off\", \"disable\", \"disabled\"]);\n\n/** User/project/explicit skills keep ownership of names. Bundled instructions grant no tool authority. */\nexport function loadSkillsWithBundled(noSkills: boolean, options: LoadSkillsOptions): LoadSkillsResult {\n\tconst selected = loadSkills(options);\n\tif (noSkills || DISABLED.has((process.env.OMK_BUNDLED_SKILLS ?? \"\").trim().toLowerCase())) return selected;\n\tconst dir = join(getPackageDir(), \"resources\", \"neo\", \"skills\");\n\tif (!existsSync(dir)) {\n\t\treturn {\n\t\t\t...selected,\n\t\t\tdiagnostics: [\n\t\t\t\t...selected.diagnostics,\n\t\t\t\t{\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tpath: dir,\n\t\t\t\t\tmessage: \"Bundled Neo skills are missing from this installation; reinstall a complete package.\",\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\tconst bundled = loadSkillsFromDir({ dir, source: \"builtin\" });\n\tconst occupied = new Set(selected.skills.map((skill) => skill.name));\n\treturn {\n\t\tskills: [...selected.skills, ...bundled.skills.filter((skill) => !occupied.has(skill.name))],\n\t\tdiagnostics: [...selected.diagnostics, ...bundled.diagnostics],\n\t};\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { AgentSessionRuntimeDiagnostic } from "./agent-session-runtime.ts";
2
+ import type { SettingsManager } from "./settings-manager.ts";
3
+ /** CLI diagnostics presentation, split out of main.ts to hold its module-size ratchet. */
4
+ export declare function collectSettingsDiagnostics(settingsManager: SettingsManager, context: string): AgentSessionRuntimeDiagnostic[];
5
+ export declare function reportDiagnostics(diagnostics: readonly AgentSessionRuntimeDiagnostic[]): void;
6
+ //# sourceMappingURL=cli-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-diagnostics.d.ts","sourceRoot":"","sources":["../../src/core/cli-diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,0FAA0F;AAC1F,wBAAgB,0BAA0B,CACzC,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,MAAM,GACb,6BAA6B,EAAE,CAKjC;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,SAAS,6BAA6B,EAAE,GAAG,IAAI,CAU7F","sourcesContent":["import chalk from \"chalk\";\nimport type { AgentSessionRuntimeDiagnostic } from \"./agent-session-runtime.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/** CLI diagnostics presentation, split out of main.ts to hold its module-size ratchet. */\nexport function collectSettingsDiagnostics(\n\tsettingsManager: SettingsManager,\n\tcontext: string,\n): AgentSessionRuntimeDiagnostic[] {\n\treturn settingsManager.drainErrors().map(({ scope, error }) => ({\n\t\ttype: \"warning\",\n\t\tmessage: `(${context}, ${scope} settings) ${error.message}`,\n\t}));\n}\n\nexport function reportDiagnostics(diagnostics: readonly AgentSessionRuntimeDiagnostic[]): void {\n\tfor (const diagnostic of diagnostics) {\n\t\tconst isError = diagnostic.type === \"error\";\n\t\tconst isWarning = diagnostic.type === \"warning\";\n\t\tconst color = isError ? chalk.red : isWarning ? chalk.yellow : chalk.dim;\n\t\tconst prefix = isError ? \"Error: \" : \"Warning: \";\n\t\t// Diagnostic presentation is intentional stderr, not application logging.\n\t\t// pi-lens-ignore: no-console-except-error\n\t\tconsole.error(color(`${prefix}${diagnostic.message}`));\n\t}\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import chalk from "chalk";
2
+ /** CLI diagnostics presentation, split out of main.ts to hold its module-size ratchet. */
3
+ export function collectSettingsDiagnostics(settingsManager, context) {
4
+ return settingsManager.drainErrors().map(({ scope, error }) => ({
5
+ type: "warning",
6
+ message: `(${context}, ${scope} settings) ${error.message}`,
7
+ }));
8
+ }
9
+ export function reportDiagnostics(diagnostics) {
10
+ for (const diagnostic of diagnostics) {
11
+ const isError = diagnostic.type === "error";
12
+ const isWarning = diagnostic.type === "warning";
13
+ const color = isError ? chalk.red : isWarning ? chalk.yellow : chalk.dim;
14
+ const prefix = isError ? "Error: " : "Warning: ";
15
+ // Diagnostic presentation is intentional stderr, not application logging.
16
+ // pi-lens-ignore: no-console-except-error
17
+ console.error(color(`${prefix}${diagnostic.message}`));
18
+ }
19
+ }
20
+ //# sourceMappingURL=cli-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-diagnostics.js","sourceRoot":"","sources":["../../src/core/cli-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,0FAA0F;AAC1F,MAAM,UAAU,0BAA0B,CACzC,eAAgC,EAChC,OAAe,EACmB;IAClC,OAAO,eAAe,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/D,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI,OAAO,KAAK,KAAK,cAAc,KAAK,CAAC,OAAO,EAAE;KAC3D,CAAC,CAAC,CAAC;AAAA,CACJ;AAED,MAAM,UAAU,iBAAiB,CAAC,WAAqD,EAAQ;IAC9F,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,KAAK,OAAO,CAAC;QAC5C,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,KAAK,SAAS,CAAC;QAChD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QACzE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;QACjD,0EAA0E;QAC1E,0CAA0C;QAC1C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;AAAA,CACD","sourcesContent":["import chalk from \"chalk\";\nimport type { AgentSessionRuntimeDiagnostic } from \"./agent-session-runtime.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/** CLI diagnostics presentation, split out of main.ts to hold its module-size ratchet. */\nexport function collectSettingsDiagnostics(\n\tsettingsManager: SettingsManager,\n\tcontext: string,\n): AgentSessionRuntimeDiagnostic[] {\n\treturn settingsManager.drainErrors().map(({ scope, error }) => ({\n\t\ttype: \"warning\",\n\t\tmessage: `(${context}, ${scope} settings) ${error.message}`,\n\t}));\n}\n\nexport function reportDiagnostics(diagnostics: readonly AgentSessionRuntimeDiagnostic[]): void {\n\tfor (const diagnostic of diagnostics) {\n\t\tconst isError = diagnostic.type === \"error\";\n\t\tconst isWarning = diagnostic.type === \"warning\";\n\t\tconst color = isError ? chalk.red : isWarning ? chalk.yellow : chalk.dim;\n\t\tconst prefix = isError ? \"Error: \" : \"Warning: \";\n\t\t// Diagnostic presentation is intentional stderr, not application logging.\n\t\t// pi-lens-ignore: no-console-except-error\n\t\tconsole.error(color(`${prefix}${diagnostic.message}`));\n\t}\n}\n"]}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Host control snapshot bound into a compaction envelope's preserved provenance.
3
+ *
4
+ * A natural-language summary cannot restore the obligation set: if the only
5
+ * record of "what is still open" is prose the summarizer wrote, a dropped line
6
+ * silently closes real work. The host supplies this structured snapshot
7
+ * instead, and the compaction commit compares its digest so a summary generated
8
+ * under different control state is discarded rather than committed.
9
+ *
10
+ * Producer output is untrusted input here: malformed shapes fail closed instead
11
+ * of degrading into an empty-but-valid checkpoint, which would look like
12
+ * "nothing was open" to every later reader.
13
+ */
14
+ export interface CompactionControlState {
15
+ readonly openTasks: readonly string[];
16
+ readonly blockerReasons: readonly string[];
17
+ readonly branch: string | null;
18
+ }
19
+ /** Validate producer output; malformed input fails closed, never degrades to an empty checkpoint. */
20
+ export declare function validateControlState(value: CompactionControlState | null): CompactionControlState | null;
21
+ /**
22
+ * Digest the snapshot deterministically. Null stays null so "no control
23
+ * authority attached" stays distinguishable from "authority reporting nothing
24
+ * open" — the transition between them is itself a change worth discarding on.
25
+ */
26
+ /**
27
+ * Make one control-state string safe for the envelope validators.
28
+ *
29
+ * Returns `[REDACTED]` rather than an empty string when sanitization consumes
30
+ * everything: the validators reject empty entries, and dropping the entry would
31
+ * quietly reduce the open-task count instead of preserving that work exists.
32
+ */
33
+ export declare function sanitizeProvenanceText(value: string): string;
34
+ /** Project a control snapshot onto the envelope's preserved-provenance fields. */
35
+ export declare function controlStateProvenance(state: CompactionControlState | null): {
36
+ readonly openTasks: readonly string[];
37
+ readonly blockerReasons: readonly string[];
38
+ readonly branch: string | null;
39
+ };
40
+ export declare function controlStateDigest(state: CompactionControlState | null): string | null;
41
+ //# sourceMappingURL=control-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-state.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/control-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAWD,qGAAqG;AACrG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,GAAG,sBAAsB,GAAG,IAAI,CAcxG;AAED;;;;GAIG;AACH;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO5D;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,GAAG;IAC7E,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAOA;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAYtF","sourcesContent":["/**\n * Host control snapshot bound into a compaction envelope's preserved provenance.\n *\n * A natural-language summary cannot restore the obligation set: if the only\n * record of \"what is still open\" is prose the summarizer wrote, a dropped line\n * silently closes real work. The host supplies this structured snapshot\n * instead, and the compaction commit compares its digest so a summary generated\n * under different control state is discarded rather than committed.\n *\n * Producer output is untrusted input here: malformed shapes fail closed instead\n * of degrading into an empty-but-valid checkpoint, which would look like\n * \"nothing was open\" to every later reader.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\nimport { redactSensitiveTextForced } from \"../redaction.ts\";\nimport { redactCredentialShapedContent } from \"./transaction.ts\";\n\n/** Envelope validators reject credential shapes and control characters outright. */\nconst MAX_PROVENANCE_TEXT = 4096;\n\nexport interface CompactionControlState {\n\treadonly openTasks: readonly string[];\n\treadonly blockerReasons: readonly string[];\n\treadonly branch: string | null;\n}\n\nconst MAX_CONTROL_STATE_ITEMS = 1024;\nconst MAX_CONTROL_STATE_TEXT = 16_384;\n\nfunction assertControlStateText(value: unknown, field: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.length > MAX_CONTROL_STATE_TEXT) {\n\t\tthrow new TypeError(`control state ${field} must be a bounded string`);\n\t}\n}\n\n/** Validate producer output; malformed input fails closed, never degrades to an empty checkpoint. */\nexport function validateControlState(value: CompactionControlState | null): CompactionControlState | null {\n\tif (value === null) return null;\n\tif (typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new TypeError(\"control state must be an object or null\");\n\t}\n\tfor (const field of [\"openTasks\", \"blockerReasons\"] as const) {\n\t\tconst list = value[field];\n\t\tif (!Array.isArray(list) || list.length > MAX_CONTROL_STATE_ITEMS) {\n\t\t\tthrow new TypeError(`control state ${field} must be a bounded array`);\n\t\t}\n\t\tfor (const item of list) assertControlStateText(item, `${field} item`);\n\t}\n\tif (value.branch !== null) assertControlStateText(value.branch, \"branch\");\n\treturn value;\n}\n\n/**\n * Digest the snapshot deterministically. Null stays null so \"no control\n * authority attached\" stays distinguishable from \"authority reporting nothing\n * open\" — the transition between them is itself a change worth discarding on.\n */\n/**\n * Make one control-state string safe for the envelope validators.\n *\n * Returns `[REDACTED]` rather than an empty string when sanitization consumes\n * everything: the validators reject empty entries, and dropping the entry would\n * quietly reduce the open-task count instead of preserving that work exists.\n */\nexport function sanitizeProvenanceText(value: string): string {\n\tconst sanitized = redactCredentialShapedContent(\n\t\tsanitizeBinaryOutput(redactSensitiveTextForced(value.trim()))\n\t\t\t.replace(/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f]/gu, \"\")\n\t\t\t.slice(0, MAX_PROVENANCE_TEXT),\n\t);\n\treturn sanitized.length > 0 ? sanitized : \"[REDACTED]\";\n}\n\n/** Project a control snapshot onto the envelope's preserved-provenance fields. */\nexport function controlStateProvenance(state: CompactionControlState | null): {\n\treadonly openTasks: readonly string[];\n\treadonly blockerReasons: readonly string[];\n\treadonly branch: string | null;\n} {\n\tif (state === null) return { openTasks: [], blockerReasons: [], branch: null };\n\treturn {\n\t\topenTasks: state.openTasks.map(sanitizeProvenanceText),\n\t\tblockerReasons: state.blockerReasons.map(sanitizeProvenanceText),\n\t\tbranch: state.branch == null ? null : sanitizeProvenanceText(state.branch),\n\t};\n}\n\nexport function controlStateDigest(state: CompactionControlState | null): string | null {\n\tif (state === null) return null;\n\treturn createHash(\"sha256\")\n\t\t.update(\n\t\t\tJSON.stringify({\n\t\t\t\topenTasks: [...state.openTasks],\n\t\t\t\tblockerReasons: [...state.blockerReasons],\n\t\t\t\tbranch: state.branch,\n\t\t\t}),\n\t\t\t\"utf8\",\n\t\t)\n\t\t.digest(\"hex\");\n}\n"]}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Host control snapshot bound into a compaction envelope's preserved provenance.
3
+ *
4
+ * A natural-language summary cannot restore the obligation set: if the only
5
+ * record of "what is still open" is prose the summarizer wrote, a dropped line
6
+ * silently closes real work. The host supplies this structured snapshot
7
+ * instead, and the compaction commit compares its digest so a summary generated
8
+ * under different control state is discarded rather than committed.
9
+ *
10
+ * Producer output is untrusted input here: malformed shapes fail closed instead
11
+ * of degrading into an empty-but-valid checkpoint, which would look like
12
+ * "nothing was open" to every later reader.
13
+ */
14
+ import { createHash } from "node:crypto";
15
+ import { sanitizeBinaryOutput } from "../../utils/shell.js";
16
+ import { redactSensitiveTextForced } from "../redaction.js";
17
+ import { redactCredentialShapedContent } from "./transaction.js";
18
+ /** Envelope validators reject credential shapes and control characters outright. */
19
+ const MAX_PROVENANCE_TEXT = 4096;
20
+ const MAX_CONTROL_STATE_ITEMS = 1024;
21
+ const MAX_CONTROL_STATE_TEXT = 16_384;
22
+ function assertControlStateText(value, field) {
23
+ if (typeof value !== "string" || value.length > MAX_CONTROL_STATE_TEXT) {
24
+ throw new TypeError(`control state ${field} must be a bounded string`);
25
+ }
26
+ }
27
+ /** Validate producer output; malformed input fails closed, never degrades to an empty checkpoint. */
28
+ export function validateControlState(value) {
29
+ if (value === null)
30
+ return null;
31
+ if (typeof value !== "object" || Array.isArray(value)) {
32
+ throw new TypeError("control state must be an object or null");
33
+ }
34
+ for (const field of ["openTasks", "blockerReasons"]) {
35
+ const list = value[field];
36
+ if (!Array.isArray(list) || list.length > MAX_CONTROL_STATE_ITEMS) {
37
+ throw new TypeError(`control state ${field} must be a bounded array`);
38
+ }
39
+ for (const item of list)
40
+ assertControlStateText(item, `${field} item`);
41
+ }
42
+ if (value.branch !== null)
43
+ assertControlStateText(value.branch, "branch");
44
+ return value;
45
+ }
46
+ /**
47
+ * Digest the snapshot deterministically. Null stays null so "no control
48
+ * authority attached" stays distinguishable from "authority reporting nothing
49
+ * open" — the transition between them is itself a change worth discarding on.
50
+ */
51
+ /**
52
+ * Make one control-state string safe for the envelope validators.
53
+ *
54
+ * Returns `[REDACTED]` rather than an empty string when sanitization consumes
55
+ * everything: the validators reject empty entries, and dropping the entry would
56
+ * quietly reduce the open-task count instead of preserving that work exists.
57
+ */
58
+ export function sanitizeProvenanceText(value) {
59
+ const sanitized = redactCredentialShapedContent(sanitizeBinaryOutput(redactSensitiveTextForced(value.trim()))
60
+ .replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/gu, "")
61
+ .slice(0, MAX_PROVENANCE_TEXT));
62
+ return sanitized.length > 0 ? sanitized : "[REDACTED]";
63
+ }
64
+ /** Project a control snapshot onto the envelope's preserved-provenance fields. */
65
+ export function controlStateProvenance(state) {
66
+ if (state === null)
67
+ return { openTasks: [], blockerReasons: [], branch: null };
68
+ return {
69
+ openTasks: state.openTasks.map(sanitizeProvenanceText),
70
+ blockerReasons: state.blockerReasons.map(sanitizeProvenanceText),
71
+ branch: state.branch == null ? null : sanitizeProvenanceText(state.branch),
72
+ };
73
+ }
74
+ export function controlStateDigest(state) {
75
+ if (state === null)
76
+ return null;
77
+ return createHash("sha256")
78
+ .update(JSON.stringify({
79
+ openTasks: [...state.openTasks],
80
+ blockerReasons: [...state.blockerReasons],
81
+ branch: state.branch,
82
+ }), "utf8")
83
+ .digest("hex");
84
+ }
85
+ //# sourceMappingURL=control-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-state.js","sourceRoot":"","sources":["../../../src/core/compaction/control-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host control snapshot bound into a compaction envelope's preserved provenance.\n *\n * A natural-language summary cannot restore the obligation set: if the only\n * record of \"what is still open\" is prose the summarizer wrote, a dropped line\n * silently closes real work. The host supplies this structured snapshot\n * instead, and the compaction commit compares its digest so a summary generated\n * under different control state is discarded rather than committed.\n *\n * Producer output is untrusted input here: malformed shapes fail closed instead\n * of degrading into an empty-but-valid checkpoint, which would look like\n * \"nothing was open\" to every later reader.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\nimport { redactSensitiveTextForced } from \"../redaction.ts\";\nimport { redactCredentialShapedContent } from \"./transaction.ts\";\n\n/** Envelope validators reject credential shapes and control characters outright. */\nconst MAX_PROVENANCE_TEXT = 4096;\n\nexport interface CompactionControlState {\n\treadonly openTasks: readonly string[];\n\treadonly blockerReasons: readonly string[];\n\treadonly branch: string | null;\n}\n\nconst MAX_CONTROL_STATE_ITEMS = 1024;\nconst MAX_CONTROL_STATE_TEXT = 16_384;\n\nfunction assertControlStateText(value: unknown, field: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.length > MAX_CONTROL_STATE_TEXT) {\n\t\tthrow new TypeError(`control state ${field} must be a bounded string`);\n\t}\n}\n\n/** Validate producer output; malformed input fails closed, never degrades to an empty checkpoint. */\nexport function validateControlState(value: CompactionControlState | null): CompactionControlState | null {\n\tif (value === null) return null;\n\tif (typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new TypeError(\"control state must be an object or null\");\n\t}\n\tfor (const field of [\"openTasks\", \"blockerReasons\"] as const) {\n\t\tconst list = value[field];\n\t\tif (!Array.isArray(list) || list.length > MAX_CONTROL_STATE_ITEMS) {\n\t\t\tthrow new TypeError(`control state ${field} must be a bounded array`);\n\t\t}\n\t\tfor (const item of list) assertControlStateText(item, `${field} item`);\n\t}\n\tif (value.branch !== null) assertControlStateText(value.branch, \"branch\");\n\treturn value;\n}\n\n/**\n * Digest the snapshot deterministically. Null stays null so \"no control\n * authority attached\" stays distinguishable from \"authority reporting nothing\n * open\" — the transition between them is itself a change worth discarding on.\n */\n/**\n * Make one control-state string safe for the envelope validators.\n *\n * Returns `[REDACTED]` rather than an empty string when sanitization consumes\n * everything: the validators reject empty entries, and dropping the entry would\n * quietly reduce the open-task count instead of preserving that work exists.\n */\nexport function sanitizeProvenanceText(value: string): string {\n\tconst sanitized = redactCredentialShapedContent(\n\t\tsanitizeBinaryOutput(redactSensitiveTextForced(value.trim()))\n\t\t\t.replace(/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f]/gu, \"\")\n\t\t\t.slice(0, MAX_PROVENANCE_TEXT),\n\t);\n\treturn sanitized.length > 0 ? sanitized : \"[REDACTED]\";\n}\n\n/** Project a control snapshot onto the envelope's preserved-provenance fields. */\nexport function controlStateProvenance(state: CompactionControlState | null): {\n\treadonly openTasks: readonly string[];\n\treadonly blockerReasons: readonly string[];\n\treadonly branch: string | null;\n} {\n\tif (state === null) return { openTasks: [], blockerReasons: [], branch: null };\n\treturn {\n\t\topenTasks: state.openTasks.map(sanitizeProvenanceText),\n\t\tblockerReasons: state.blockerReasons.map(sanitizeProvenanceText),\n\t\tbranch: state.branch == null ? null : sanitizeProvenanceText(state.branch),\n\t};\n}\n\nexport function controlStateDigest(state: CompactionControlState | null): string | null {\n\tif (state === null) return null;\n\treturn createHash(\"sha256\")\n\t\t.update(\n\t\t\tJSON.stringify({\n\t\t\t\topenTasks: [...state.openTasks],\n\t\t\t\tblockerReasons: [...state.blockerReasons],\n\t\t\t\tbranch: state.branch,\n\t\t\t}),\n\t\t\t\"utf8\",\n\t\t)\n\t\t.digest(\"hex\");\n}\n"]}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * What to do when compaction summarization cannot run.
3
+ *
4
+ * The resilience ladder, in order:
5
+ * 1. the resolved compaction model (caller's `summarize`),
6
+ * 2. the live session model — a pinned `compaction.model` can be quota-dead
7
+ * while the model the user is actively talking to still serves traffic,
8
+ * 3. a deterministic trim that needs no model at all.
9
+ *
10
+ * Step 3 exists because the alternative is stranding the run: once context is
11
+ * over the window, a failed compaction means no later turn can succeed until
12
+ * the billing cycle resets.
13
+ *
14
+ * Kept out of `compaction.ts` so the ladder is unit-testable without an
15
+ * AgentSession, and so neither module carries the other's growth.
16
+ */
17
+ import type { Model } from "omk-ai";
18
+ import type { CompactionDetails, CompactionPreparation, CompactionResult } from "./compaction.ts";
19
+ /**
20
+ * Detail shape unique to the no-model path. Kept here rather than on
21
+ * `CompactionDetails` so a reader of a normal entry never has to wonder why a
22
+ * `deterministicEmergency` flag exists on it.
23
+ */
24
+ export interface DeterministicCompactionDetails extends CompactionDetails {
25
+ readonly deterministicEmergency: true;
26
+ /** Sanitized, bounded reason the model path was unavailable. */
27
+ readonly deterministicReason: string;
28
+ }
29
+ /**
30
+ * Compact without a model.
31
+ *
32
+ * Keeps exactly what `prepareCompaction()` already derived deterministically —
33
+ * the prior summary, source-bound user rules, and file operations — plus the
34
+ * recent window the cut point preserved. It never claims to be a model summary:
35
+ * the heading and `details.deterministicEmergency` mark it as a trim, because
36
+ * the dropped turns were discarded without semantic summarization.
37
+ *
38
+ * Takes no model, key, or stream function: the signature itself proves no
39
+ * provider call can occur on this path.
40
+ */
41
+ export declare function compactDeterministic(preparation: CompactionPreparation, reason: string): CompactionResult;
42
+ export interface SummarizationFallbackInput {
43
+ readonly preparation: CompactionPreparation;
44
+ readonly primaryModel: Model<any>;
45
+ /** The model the session is actually running, when known. */
46
+ readonly sessionModel: Model<any> | undefined;
47
+ /**
48
+ * Summarize on one model, resolving that model's own credentials. The
49
+ * generic failover list reuses the failed model's key across candidates, so
50
+ * a cross-provider rescue must resolve auth per call instead.
51
+ */
52
+ readonly summarize: (model: Model<any>) => Promise<CompactionResult>;
53
+ readonly isAborted: () => boolean;
54
+ }
55
+ /**
56
+ * Run the summarization ladder. Aborts and non-quota failures propagate
57
+ * unchanged — a transient 503 must retry its model, not silently degrade.
58
+ */
59
+ export declare function summarizeWithFallback(input: SummarizationFallbackInput): Promise<CompactionResult>;
60
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAGpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAYlG;;;;GAIG;AACH,MAAM,WAAW,8BAA+B,SAAQ,iBAAiB;IACxE,QAAQ,CAAC,sBAAsB,EAAE,IAAI,CAAC;IACtC,gEAAgE;IAChE,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACrC;AASD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAwDzG;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,6DAA6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC;CAClC;AAMD;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmBxG","sourcesContent":["/**\n * What to do when compaction summarization cannot run.\n *\n * The resilience ladder, in order:\n * 1. the resolved compaction model (caller's `summarize`),\n * 2. the live session model — a pinned `compaction.model` can be quota-dead\n * while the model the user is actively talking to still serves traffic,\n * 3. a deterministic trim that needs no model at all.\n *\n * Step 3 exists because the alternative is stranding the run: once context is\n * over the window, a failed compaction means no later turn can succeed until\n * the billing cycle resets.\n *\n * Kept out of `compaction.ts` so the ladder is unit-testable without an\n * AgentSession, and so neither module carries the other's growth.\n */\n\nimport type { Model } from \"omk-ai\";\nimport { isQuotaExhaustionMessage } from \"../provider-resilience.ts\";\nimport { redactSensitiveTextForced } from \"../redaction.ts\";\nimport type { CompactionDetails, CompactionPreparation, CompactionResult } from \"./compaction.ts\";\nimport { applyCompactionKnowledgeTriage } from \"./knowledge-triage.ts\";\nimport { redactCredentialShapedContent } from \"./transaction.ts\";\nimport { computeFileLists, formatFileOperations } from \"./utils.ts\";\n\n/** Upper bound on the reason text persisted into the compaction entry. */\nconst DETERMINISTIC_REASON_MAX_CHARS = 512;\n/** Upper bound on the prior summary carried forward verbatim. */\nconst CARRIED_SUMMARY_MAX_CHARS = 16_384;\n\nconst DETERMINISTIC_EMERGENCY_HEADING = \"## Deterministic emergency compaction\";\n\n/**\n * Detail shape unique to the no-model path. Kept here rather than on\n * `CompactionDetails` so a reader of a normal entry never has to wonder why a\n * `deterministicEmergency` flag exists on it.\n */\nexport interface DeterministicCompactionDetails extends CompactionDetails {\n\treadonly deterministicEmergency: true;\n\t/** Sanitized, bounded reason the model path was unavailable. */\n\treadonly deterministicReason: string;\n}\n\nfunction boundedSanitizedText(value: string, maxChars: number): string {\n\tconst sanitized = redactCredentialShapedContent(redactSensitiveTextForced(value))\n\t\t.replace(/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f]/gu, \"\")\n\t\t.trim();\n\treturn sanitized.length <= maxChars ? sanitized : `${sanitized.slice(0, maxChars - 1)}\\u2026`;\n}\n\n/**\n * Compact without a model.\n *\n * Keeps exactly what `prepareCompaction()` already derived deterministically —\n * the prior summary, source-bound user rules, and file operations — plus the\n * recent window the cut point preserved. It never claims to be a model summary:\n * the heading and `details.deterministicEmergency` mark it as a trim, because\n * the dropped turns were discarded without semantic summarization.\n *\n * Takes no model, key, or stream function: the signature itself proves no\n * provider call can occur on this path.\n */\nexport function compactDeterministic(preparation: CompactionPreparation, reason: string): CompactionResult {\n\tconst {\n\t\tfirstKeptEntryId,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tpreviousRuleHistory,\n\t\tcurrentRuleEntries,\n\t\tfileOps,\n\t} = preparation;\n\n\tif (!firstKeptEntryId) {\n\t\tthrow new Error(\"First kept entry has no UUID - session may need migration\");\n\t}\n\n\tconst safeReason = boundedSanitizedText(reason, DETERMINISTIC_REASON_MAX_CHARS);\n\tconst carried =\n\t\tpreviousSummary === undefined ? \"\" : boundedSanitizedText(previousSummary, CARRIED_SUMMARY_MAX_CHARS);\n\n\tconst sections = [\n\t\tDETERMINISTIC_EMERGENCY_HEADING,\n\t\t\"Model summarization was unavailable, so the context was trimmed deterministically \" +\n\t\t\t\"rather than leaving the session unable to continue. This is not a model-generated \" +\n\t\t\t\"summary: older turns were dropped without semantic summarization, and only the \" +\n\t\t\t\"structured state below plus the retained recent window survive.\",\n\t\t`Cause: ${safeReason.length > 0 ? safeReason : \"unspecified summarization failure\"}`,\n\t];\n\tif (carried.length > 0) {\n\t\tsections.push(`### Carried forward from the previous compaction\\n\\n${carried}`);\n\t}\n\n\tconst triage = applyCompactionKnowledgeTriage({\n\t\tgeneratedSummary: sections.join(\"\\n\\n\"),\n\t\tcurrentMessages: [...messagesToSummarize, ...turnPrefixMessages],\n\t\tcurrentEntries: currentRuleEntries,\n\t\tpreviousRules: previousRuleHistory?.rules,\n\t\tpreviousSummary,\n\t\tpreviousEntries: previousRuleHistory?.entries,\n\t});\n\n\tconst { readFiles, modifiedFiles } = computeFileLists(fileOps);\n\tconst summary = triage.summary + formatFileOperations(readFiles, modifiedFiles);\n\n\treturn {\n\t\tsummary,\n\t\tfirstKeptEntryId,\n\t\ttokensBefore,\n\t\tdetails: {\n\t\t\treadFiles,\n\t\t\tmodifiedFiles,\n\t\t\tpreservedRules: [...triage.preservedRules],\n\t\t\tdeterministicEmergency: true,\n\t\t\tdeterministicReason: safeReason,\n\t\t} satisfies DeterministicCompactionDetails,\n\t};\n}\n\nexport interface SummarizationFallbackInput {\n\treadonly preparation: CompactionPreparation;\n\treadonly primaryModel: Model<any>;\n\t/** The model the session is actually running, when known. */\n\treadonly sessionModel: Model<any> | undefined;\n\t/**\n\t * Summarize on one model, resolving that model's own credentials. The\n\t * generic failover list reuses the failed model's key across candidates, so\n\t * a cross-provider rescue must resolve auth per call instead.\n\t */\n\treadonly summarize: (model: Model<any>) => Promise<CompactionResult>;\n\treadonly isAborted: () => boolean;\n}\n\nfunction sameModel(a: Model<any>, b: Model<any>): boolean {\n\treturn a.provider === b.provider && a.id === b.id;\n}\n\n/**\n * Run the summarization ladder. Aborts and non-quota failures propagate\n * unchanged — a transient 503 must retry its model, not silently degrade.\n */\nexport async function summarizeWithFallback(input: SummarizationFallbackInput): Promise<CompactionResult> {\n\ttry {\n\t\treturn await input.summarize(input.primaryModel);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tif (input.isAborted()) throw error;\n\t\tif (!isQuotaExhaustionMessage(message)) throw error;\n\n\t\tconst session = input.sessionModel;\n\t\tif (session !== undefined && !sameModel(session, input.primaryModel)) {\n\t\t\ttry {\n\t\t\t\treturn await input.summarize(session);\n\t\t\t} catch (rescueError) {\n\t\t\t\tif (input.isAborted()) throw rescueError;\n\t\t\t\t// Session model could not help either; fall through to the trim.\n\t\t\t}\n\t\t}\n\t\treturn compactDeterministic(input.preparation, message);\n\t}\n}\n"]}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * What to do when compaction summarization cannot run.
3
+ *
4
+ * The resilience ladder, in order:
5
+ * 1. the resolved compaction model (caller's `summarize`),
6
+ * 2. the live session model — a pinned `compaction.model` can be quota-dead
7
+ * while the model the user is actively talking to still serves traffic,
8
+ * 3. a deterministic trim that needs no model at all.
9
+ *
10
+ * Step 3 exists because the alternative is stranding the run: once context is
11
+ * over the window, a failed compaction means no later turn can succeed until
12
+ * the billing cycle resets.
13
+ *
14
+ * Kept out of `compaction.ts` so the ladder is unit-testable without an
15
+ * AgentSession, and so neither module carries the other's growth.
16
+ */
17
+ import { isQuotaExhaustionMessage } from "../provider-resilience.js";
18
+ import { redactSensitiveTextForced } from "../redaction.js";
19
+ import { applyCompactionKnowledgeTriage } from "./knowledge-triage.js";
20
+ import { redactCredentialShapedContent } from "./transaction.js";
21
+ import { computeFileLists, formatFileOperations } from "./utils.js";
22
+ /** Upper bound on the reason text persisted into the compaction entry. */
23
+ const DETERMINISTIC_REASON_MAX_CHARS = 512;
24
+ /** Upper bound on the prior summary carried forward verbatim. */
25
+ const CARRIED_SUMMARY_MAX_CHARS = 16_384;
26
+ const DETERMINISTIC_EMERGENCY_HEADING = "## Deterministic emergency compaction";
27
+ function boundedSanitizedText(value, maxChars) {
28
+ const sanitized = redactCredentialShapedContent(redactSensitiveTextForced(value))
29
+ .replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/gu, "")
30
+ .trim();
31
+ return sanitized.length <= maxChars ? sanitized : `${sanitized.slice(0, maxChars - 1)}\u2026`;
32
+ }
33
+ /**
34
+ * Compact without a model.
35
+ *
36
+ * Keeps exactly what `prepareCompaction()` already derived deterministically —
37
+ * the prior summary, source-bound user rules, and file operations — plus the
38
+ * recent window the cut point preserved. It never claims to be a model summary:
39
+ * the heading and `details.deterministicEmergency` mark it as a trim, because
40
+ * the dropped turns were discarded without semantic summarization.
41
+ *
42
+ * Takes no model, key, or stream function: the signature itself proves no
43
+ * provider call can occur on this path.
44
+ */
45
+ export function compactDeterministic(preparation, reason) {
46
+ const { firstKeptEntryId, messagesToSummarize, turnPrefixMessages, tokensBefore, previousSummary, previousRuleHistory, currentRuleEntries, fileOps, } = preparation;
47
+ if (!firstKeptEntryId) {
48
+ throw new Error("First kept entry has no UUID - session may need migration");
49
+ }
50
+ const safeReason = boundedSanitizedText(reason, DETERMINISTIC_REASON_MAX_CHARS);
51
+ const carried = previousSummary === undefined ? "" : boundedSanitizedText(previousSummary, CARRIED_SUMMARY_MAX_CHARS);
52
+ const sections = [
53
+ DETERMINISTIC_EMERGENCY_HEADING,
54
+ "Model summarization was unavailable, so the context was trimmed deterministically " +
55
+ "rather than leaving the session unable to continue. This is not a model-generated " +
56
+ "summary: older turns were dropped without semantic summarization, and only the " +
57
+ "structured state below plus the retained recent window survive.",
58
+ `Cause: ${safeReason.length > 0 ? safeReason : "unspecified summarization failure"}`,
59
+ ];
60
+ if (carried.length > 0) {
61
+ sections.push(`### Carried forward from the previous compaction\n\n${carried}`);
62
+ }
63
+ const triage = applyCompactionKnowledgeTriage({
64
+ generatedSummary: sections.join("\n\n"),
65
+ currentMessages: [...messagesToSummarize, ...turnPrefixMessages],
66
+ currentEntries: currentRuleEntries,
67
+ previousRules: previousRuleHistory?.rules,
68
+ previousSummary,
69
+ previousEntries: previousRuleHistory?.entries,
70
+ });
71
+ const { readFiles, modifiedFiles } = computeFileLists(fileOps);
72
+ const summary = triage.summary + formatFileOperations(readFiles, modifiedFiles);
73
+ return {
74
+ summary,
75
+ firstKeptEntryId,
76
+ tokensBefore,
77
+ details: {
78
+ readFiles,
79
+ modifiedFiles,
80
+ preservedRules: [...triage.preservedRules],
81
+ deterministicEmergency: true,
82
+ deterministicReason: safeReason,
83
+ },
84
+ };
85
+ }
86
+ function sameModel(a, b) {
87
+ return a.provider === b.provider && a.id === b.id;
88
+ }
89
+ /**
90
+ * Run the summarization ladder. Aborts and non-quota failures propagate
91
+ * unchanged — a transient 503 must retry its model, not silently degrade.
92
+ */
93
+ export async function summarizeWithFallback(input) {
94
+ try {
95
+ return await input.summarize(input.primaryModel);
96
+ }
97
+ catch (error) {
98
+ const message = error instanceof Error ? error.message : String(error);
99
+ if (input.isAborted())
100
+ throw error;
101
+ if (!isQuotaExhaustionMessage(message))
102
+ throw error;
103
+ const session = input.sessionModel;
104
+ if (session !== undefined && !sameModel(session, input.primaryModel)) {
105
+ try {
106
+ return await input.summarize(session);
107
+ }
108
+ catch (rescueError) {
109
+ if (input.isAborted())
110
+ throw rescueError;
111
+ // Session model could not help either; fall through to the trim.
112
+ }
113
+ }
114
+ return compactDeterministic(input.preparation, message);
115
+ }
116
+ }
117
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../../src/core/compaction/fallback.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What to do when compaction summarization cannot run.\n *\n * The resilience ladder, in order:\n * 1. the resolved compaction model (caller's `summarize`),\n * 2. the live session model — a pinned `compaction.model` can be quota-dead\n * while the model the user is actively talking to still serves traffic,\n * 3. a deterministic trim that needs no model at all.\n *\n * Step 3 exists because the alternative is stranding the run: once context is\n * over the window, a failed compaction means no later turn can succeed until\n * the billing cycle resets.\n *\n * Kept out of `compaction.ts` so the ladder is unit-testable without an\n * AgentSession, and so neither module carries the other's growth.\n */\n\nimport type { Model } from \"omk-ai\";\nimport { isQuotaExhaustionMessage } from \"../provider-resilience.ts\";\nimport { redactSensitiveTextForced } from \"../redaction.ts\";\nimport type { CompactionDetails, CompactionPreparation, CompactionResult } from \"./compaction.ts\";\nimport { applyCompactionKnowledgeTriage } from \"./knowledge-triage.ts\";\nimport { redactCredentialShapedContent } from \"./transaction.ts\";\nimport { computeFileLists, formatFileOperations } from \"./utils.ts\";\n\n/** Upper bound on the reason text persisted into the compaction entry. */\nconst DETERMINISTIC_REASON_MAX_CHARS = 512;\n/** Upper bound on the prior summary carried forward verbatim. */\nconst CARRIED_SUMMARY_MAX_CHARS = 16_384;\n\nconst DETERMINISTIC_EMERGENCY_HEADING = \"## Deterministic emergency compaction\";\n\n/**\n * Detail shape unique to the no-model path. Kept here rather than on\n * `CompactionDetails` so a reader of a normal entry never has to wonder why a\n * `deterministicEmergency` flag exists on it.\n */\nexport interface DeterministicCompactionDetails extends CompactionDetails {\n\treadonly deterministicEmergency: true;\n\t/** Sanitized, bounded reason the model path was unavailable. */\n\treadonly deterministicReason: string;\n}\n\nfunction boundedSanitizedText(value: string, maxChars: number): string {\n\tconst sanitized = redactCredentialShapedContent(redactSensitiveTextForced(value))\n\t\t.replace(/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f]/gu, \"\")\n\t\t.trim();\n\treturn sanitized.length <= maxChars ? sanitized : `${sanitized.slice(0, maxChars - 1)}\\u2026`;\n}\n\n/**\n * Compact without a model.\n *\n * Keeps exactly what `prepareCompaction()` already derived deterministically —\n * the prior summary, source-bound user rules, and file operations — plus the\n * recent window the cut point preserved. It never claims to be a model summary:\n * the heading and `details.deterministicEmergency` mark it as a trim, because\n * the dropped turns were discarded without semantic summarization.\n *\n * Takes no model, key, or stream function: the signature itself proves no\n * provider call can occur on this path.\n */\nexport function compactDeterministic(preparation: CompactionPreparation, reason: string): CompactionResult {\n\tconst {\n\t\tfirstKeptEntryId,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tpreviousRuleHistory,\n\t\tcurrentRuleEntries,\n\t\tfileOps,\n\t} = preparation;\n\n\tif (!firstKeptEntryId) {\n\t\tthrow new Error(\"First kept entry has no UUID - session may need migration\");\n\t}\n\n\tconst safeReason = boundedSanitizedText(reason, DETERMINISTIC_REASON_MAX_CHARS);\n\tconst carried =\n\t\tpreviousSummary === undefined ? \"\" : boundedSanitizedText(previousSummary, CARRIED_SUMMARY_MAX_CHARS);\n\n\tconst sections = [\n\t\tDETERMINISTIC_EMERGENCY_HEADING,\n\t\t\"Model summarization was unavailable, so the context was trimmed deterministically \" +\n\t\t\t\"rather than leaving the session unable to continue. This is not a model-generated \" +\n\t\t\t\"summary: older turns were dropped without semantic summarization, and only the \" +\n\t\t\t\"structured state below plus the retained recent window survive.\",\n\t\t`Cause: ${safeReason.length > 0 ? safeReason : \"unspecified summarization failure\"}`,\n\t];\n\tif (carried.length > 0) {\n\t\tsections.push(`### Carried forward from the previous compaction\\n\\n${carried}`);\n\t}\n\n\tconst triage = applyCompactionKnowledgeTriage({\n\t\tgeneratedSummary: sections.join(\"\\n\\n\"),\n\t\tcurrentMessages: [...messagesToSummarize, ...turnPrefixMessages],\n\t\tcurrentEntries: currentRuleEntries,\n\t\tpreviousRules: previousRuleHistory?.rules,\n\t\tpreviousSummary,\n\t\tpreviousEntries: previousRuleHistory?.entries,\n\t});\n\n\tconst { readFiles, modifiedFiles } = computeFileLists(fileOps);\n\tconst summary = triage.summary + formatFileOperations(readFiles, modifiedFiles);\n\n\treturn {\n\t\tsummary,\n\t\tfirstKeptEntryId,\n\t\ttokensBefore,\n\t\tdetails: {\n\t\t\treadFiles,\n\t\t\tmodifiedFiles,\n\t\t\tpreservedRules: [...triage.preservedRules],\n\t\t\tdeterministicEmergency: true,\n\t\t\tdeterministicReason: safeReason,\n\t\t} satisfies DeterministicCompactionDetails,\n\t};\n}\n\nexport interface SummarizationFallbackInput {\n\treadonly preparation: CompactionPreparation;\n\treadonly primaryModel: Model<any>;\n\t/** The model the session is actually running, when known. */\n\treadonly sessionModel: Model<any> | undefined;\n\t/**\n\t * Summarize on one model, resolving that model's own credentials. The\n\t * generic failover list reuses the failed model's key across candidates, so\n\t * a cross-provider rescue must resolve auth per call instead.\n\t */\n\treadonly summarize: (model: Model<any>) => Promise<CompactionResult>;\n\treadonly isAborted: () => boolean;\n}\n\nfunction sameModel(a: Model<any>, b: Model<any>): boolean {\n\treturn a.provider === b.provider && a.id === b.id;\n}\n\n/**\n * Run the summarization ladder. Aborts and non-quota failures propagate\n * unchanged — a transient 503 must retry its model, not silently degrade.\n */\nexport async function summarizeWithFallback(input: SummarizationFallbackInput): Promise<CompactionResult> {\n\ttry {\n\t\treturn await input.summarize(input.primaryModel);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tif (input.isAborted()) throw error;\n\t\tif (!isQuotaExhaustionMessage(message)) throw error;\n\n\t\tconst session = input.sessionModel;\n\t\tif (session !== undefined && !sameModel(session, input.primaryModel)) {\n\t\t\ttry {\n\t\t\t\treturn await input.summarize(session);\n\t\t\t} catch (rescueError) {\n\t\t\t\tif (input.isAborted()) throw rescueError;\n\t\t\t\t// Session model could not help either; fall through to the trim.\n\t\t\t}\n\t\t}\n\t\treturn compactDeterministic(input.preparation, message);\n\t}\n}\n"]}
@@ -3,6 +3,8 @@
3
3
  */
4
4
  export * from "./branch-summarization.ts";
5
5
  export * from "./compaction.ts";
6
+ export * from "./control-state.ts";
7
+ export * from "./fallback.ts";
6
8
  export * from "./hysteresis.ts";
7
9
  export * from "./knowledge-triage.ts";
8
10
  export * from "./model-policy.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC","sourcesContent":["/**\n * Compaction and summarization utilities.\n */\n\nexport * from \"./branch-summarization.ts\";\nexport * from \"./compaction.ts\";\nexport * from \"./hysteresis.ts\";\nexport * from \"./knowledge-triage.ts\";\nexport * from \"./model-policy.ts\";\nexport * from \"./resume-policy.ts\";\nexport * from \"./transaction.ts\";\nexport * from \"./utils.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC","sourcesContent":["/**\n * Compaction and summarization utilities.\n */\n\nexport * from \"./branch-summarization.ts\";\nexport * from \"./compaction.ts\";\nexport * from \"./control-state.ts\";\nexport * from \"./fallback.ts\";\nexport * from \"./hysteresis.ts\";\nexport * from \"./knowledge-triage.ts\";\nexport * from \"./model-policy.ts\";\nexport * from \"./resume-policy.ts\";\nexport * from \"./transaction.ts\";\nexport * from \"./utils.ts\";\n"]}
@@ -3,6 +3,8 @@
3
3
  */
4
4
  export * from "./branch-summarization.js";
5
5
  export * from "./compaction.js";
6
+ export * from "./control-state.js";
7
+ export * from "./fallback.js";
6
8
  export * from "./hysteresis.js";
7
9
  export * from "./knowledge-triage.js";
8
10
  export * from "./model-policy.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC","sourcesContent":["/**\n * Compaction and summarization utilities.\n */\n\nexport * from \"./branch-summarization.ts\";\nexport * from \"./compaction.ts\";\nexport * from \"./hysteresis.ts\";\nexport * from \"./knowledge-triage.ts\";\nexport * from \"./model-policy.ts\";\nexport * from \"./resume-policy.ts\";\nexport * from \"./transaction.ts\";\nexport * from \"./utils.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC","sourcesContent":["/**\n * Compaction and summarization utilities.\n */\n\nexport * from \"./branch-summarization.ts\";\nexport * from \"./compaction.ts\";\nexport * from \"./control-state.ts\";\nexport * from \"./fallback.ts\";\nexport * from \"./hysteresis.ts\";\nexport * from \"./knowledge-triage.ts\";\nexport * from \"./model-policy.ts\";\nexport * from \"./resume-policy.ts\";\nexport * from \"./transaction.ts\";\nexport * from \"./utils.ts\";\n"]}
@@ -1,3 +1,18 @@
1
1
  import { type ContextBudgetItemV2, type ContextRepresentationCandidateV2, type HeadroomQualityPolicyV2 } from "./context-budget-headroom-types.ts";
2
- export declare function deriveRepresentationCandidates(item: ContextBudgetItemV2, policy?: HeadroomQualityPolicyV2): readonly ContextRepresentationCandidateV2[];
2
+ /** Prices one materialized representation string; must be the counter that produced the item's full-text cost. */
3
+ export type RepresentationTokenCounter = (text: string) => number;
4
+ /**
5
+ * Derive the representations the selector may choose for one item.
6
+ *
7
+ * Every non-full candidate is priced by counting the string it actually
8
+ * materializes with `countTokens` — the same counter that priced the full
9
+ * text — so the cost the selector checks against the budget is the cost of
10
+ * the text that would be sent. A compression ratio is never a cost: a summary
11
+ * that returns its source unchanged saves nothing, and a representation whose
12
+ * materialized text is not cheaper than the full text is not offered at all.
13
+ * Pass the counter that produced `item.tokenEstimate`; mixing an exact
14
+ * tokenizer for the full text with the heuristic for its alternatives makes
15
+ * the candidates incomparable.
16
+ */
17
+ export declare function deriveRepresentationCandidates(item: ContextBudgetItemV2, policy?: HeadroomQualityPolicyV2, countTokens?: RepresentationTokenCounter): readonly ContextRepresentationCandidateV2[];
3
18
  //# sourceMappingURL=context-budget-headroom-candidates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-budget-headroom-candidates.d.ts","sourceRoot":"","sources":["../../src/core/context-budget-headroom-candidates.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,gCAAgC,EAKrC,KAAK,uBAAuB,EAE5B,MAAM,oCAAoC,CAAC;AAK5C,wBAAgB,8BAA8B,CAC7C,IAAI,EAAE,mBAAmB,EACzB,MAAM,GAAE,uBAAyD,GAC/D,SAAS,gCAAgC,EAAE,CA4D7C","sourcesContent":["import {\n\ttype ContextBudgetItemV2,\n\ttype ContextRepresentationCandidateV2,\n\ttype ContextSourceRefV2,\n\tDEFAULT_HEADROOM_QUALITY_POLICY,\n\tfnv1aHex,\n\tfullTextTokens,\n\ttype HeadroomQualityPolicyV2,\n\theuristicTokenCount,\n} from \"./context-budget-headroom-types.ts\";\n\nconst SUMMARY_HEAD_CHARS = 160;\nconst HEADROOM_HEAD_CHARS = 120;\n\nexport function deriveRepresentationCandidates(\n\titem: ContextBudgetItemV2,\n\tpolicy: HeadroomQualityPolicyV2 = DEFAULT_HEADROOM_QUALITY_POLICY,\n): readonly ContextRepresentationCandidateV2[] {\n\tconst full = fullTextTokens(item);\n\tconst sourceRef = item.sourceRef;\n\tconst retrievable = sourceRef?.retrievable === true;\n\tconst candidates: ContextRepresentationCandidateV2[] = [];\n\n\tcandidates.push({\n\t\tkind: \"full\",\n\t\ttext: item.text,\n\t\testimatedTokens: full,\n\t\tfidelity: item.tokenEstimate !== undefined ? \"exact\" : \"bounded\",\n\t\tsourceRef,\n\t});\n\n\tif (retrievable && sourceRef) {\n\t\tconst pointerText = formatPointer(sourceRef);\n\t\tcandidates.push({\n\t\t\tkind: \"pointer\",\n\t\t\ttext: pointerText,\n\t\t\testimatedTokens: heuristicTokenCount(pointerText),\n\t\t\tfidelity: \"bounded\",\n\t\t\tsourceRef,\n\t\t});\n\t}\n\n\tconst summaryTokens = Math.ceil(full * 0.15) + 8;\n\tif (isSummaryEligible(item, full, policy) && summaryTokens < full) {\n\t\tcandidates.push({\n\t\t\tkind: \"summary\",\n\t\t\ttext: summarizeText(item.text),\n\t\t\testimatedTokens: summaryTokens,\n\t\t\tfidelity: \"lossy\",\n\t\t\tsummaryHash: fnv1aHex(item.text),\n\t\t});\n\t}\n\n\tconst headroomText = formatHeadroom(item.text, sourceRef);\n\tconst headroomTokens = Math.max(Math.ceil(full * 0.35) + 16, heuristicTokenCount(headroomText));\n\tif (full > policy.headroomThresholdTokens && retrievable && headroomTokens < full) {\n\t\tcandidates.push({\n\t\t\tkind: \"headroom-compressed\",\n\t\t\ttext: headroomText,\n\t\t\testimatedTokens: headroomTokens,\n\t\t\tfidelity: \"reversible\",\n\t\t\tsourceRef,\n\t\t\tcompressorId: \"headroom-shadow\",\n\t\t});\n\t}\n\n\tif (policy.allowOmit) {\n\t\tcandidates.push({\n\t\t\tkind: \"omit\",\n\t\t\ttext: \"\",\n\t\t\testimatedTokens: 0,\n\t\t\tfidelity: \"lossy\",\n\t\t\tsourceRef,\n\t\t});\n\t}\n\n\treturn candidates;\n}\n\nfunction isSummaryEligible(item: ContextBudgetItemV2, fullTokens: number, policy: HeadroomQualityPolicyV2): boolean {\n\treturn (\n\t\titem.tier === \"history\" ||\n\t\titem.tier === \"evidence\" ||\n\t\titem.tier === \"scratch\" ||\n\t\t(item.ageTurns ?? 0) >= policy.summaryMaxAgeTurns ||\n\t\tfullTokens > policy.headroomThresholdTokens\n\t);\n}\n\nfunction formatPointer(ref: ContextSourceRefV2): string {\n\tconst parts: string[] = [`uri=\"${escapeMetadataValue(ref.uri)}\"`];\n\tif (ref.symbol) parts.push(`symbol=\"${escapeMetadataValue(ref.symbol)}\"`);\n\tif (ref.range) parts.push(`lines=\"${ref.range.startLine}-${ref.range.endLine}\"`);\n\tparts.push(`hash=\"${escapeMetadataValue(ref.contentHash)}\"`);\n\treturn `<pointer ${parts.join(\" \")} />`;\n}\n\nfunction summarizeText(text: string): string {\n\tif (text.length <= SUMMARY_HEAD_CHARS) {\n\t\treturn text;\n\t}\n\treturn `${text.slice(0, SUMMARY_HEAD_CHARS)} …[summary]`;\n}\n\nfunction formatHeadroom(text: string, ref?: ContextSourceRefV2): string {\n\tconst head = text.slice(0, HEADROOM_HEAD_CHARS);\n\tconst hash = fnv1aHex(text);\n\tconst where = ref ? ` uri=\"${escapeMetadataValue(ref.uri)}\"` : \"\";\n\treturn `${head} …[headroom-compressed${where} hash=\"${hash}\"]`;\n}\n\nfunction escapeMetadataValue(value: string): string {\n\treturn value\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&apos;\");\n}\n"]}
1
+ {"version":3,"file":"context-budget-headroom-candidates.d.ts","sourceRoot":"","sources":["../../src/core/context-budget-headroom-candidates.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,gCAAgC,EAKrC,KAAK,uBAAuB,EAE5B,MAAM,oCAAoC,CAAC;AAK5C,kHAAkH;AAClH,MAAM,MAAM,0BAA0B,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,wBAAgB,8BAA8B,CAC7C,IAAI,EAAE,mBAAmB,EACzB,MAAM,GAAE,uBAAyD,EACjE,WAAW,GAAE,0BAAgD,GAC3D,SAAS,gCAAgC,EAAE,CAgE7C","sourcesContent":["import {\n\ttype ContextBudgetItemV2,\n\ttype ContextRepresentationCandidateV2,\n\ttype ContextSourceRefV2,\n\tDEFAULT_HEADROOM_QUALITY_POLICY,\n\tfnv1aHex,\n\tfullTextTokens,\n\ttype HeadroomQualityPolicyV2,\n\theuristicTokenCount,\n} from \"./context-budget-headroom-types.ts\";\n\nconst SUMMARY_HEAD_CHARS = 160;\nconst HEADROOM_HEAD_CHARS = 120;\n\n/** Prices one materialized representation string; must be the counter that produced the item's full-text cost. */\nexport type RepresentationTokenCounter = (text: string) => number;\n\n/**\n * Derive the representations the selector may choose for one item.\n *\n * Every non-full candidate is priced by counting the string it actually\n * materializes with `countTokens` — the same counter that priced the full\n * text — so the cost the selector checks against the budget is the cost of\n * the text that would be sent. A compression ratio is never a cost: a summary\n * that returns its source unchanged saves nothing, and a representation whose\n * materialized text is not cheaper than the full text is not offered at all.\n * Pass the counter that produced `item.tokenEstimate`; mixing an exact\n * tokenizer for the full text with the heuristic for its alternatives makes\n * the candidates incomparable.\n */\nexport function deriveRepresentationCandidates(\n\titem: ContextBudgetItemV2,\n\tpolicy: HeadroomQualityPolicyV2 = DEFAULT_HEADROOM_QUALITY_POLICY,\n\tcountTokens: RepresentationTokenCounter = heuristicTokenCount,\n): readonly ContextRepresentationCandidateV2[] {\n\tconst full = fullTextTokens(item);\n\tconst sourceRef = item.sourceRef;\n\tconst retrievable = sourceRef?.retrievable === true;\n\tconst candidates: ContextRepresentationCandidateV2[] = [];\n\tconst offerIfCheaper = (candidate: ContextRepresentationCandidateV2): void => {\n\t\tif (candidate.text !== item.text && candidate.estimatedTokens < full) candidates.push(candidate);\n\t};\n\n\tcandidates.push({\n\t\tkind: \"full\",\n\t\ttext: item.text,\n\t\testimatedTokens: full,\n\t\tfidelity: item.tokenEstimate !== undefined ? \"exact\" : \"bounded\",\n\t\tsourceRef,\n\t});\n\n\tif (retrievable && sourceRef) {\n\t\tconst pointerText = formatPointer(sourceRef);\n\t\tofferIfCheaper({\n\t\t\tkind: \"pointer\",\n\t\t\ttext: pointerText,\n\t\t\testimatedTokens: countTokens(pointerText),\n\t\t\tfidelity: \"bounded\",\n\t\t\tsourceRef,\n\t\t});\n\t}\n\n\tif (isSummaryEligible(item, full, policy)) {\n\t\tconst summaryText = summarizeText(item.text);\n\t\tofferIfCheaper({\n\t\t\tkind: \"summary\",\n\t\t\ttext: summaryText,\n\t\t\testimatedTokens: countTokens(summaryText),\n\t\t\tfidelity: \"lossy\",\n\t\t\tsummaryHash: fnv1aHex(item.text),\n\t\t});\n\t}\n\n\tif (full > policy.headroomThresholdTokens && retrievable) {\n\t\tconst headroomText = formatHeadroom(item.text, sourceRef);\n\t\t// The shadow compressor's reversible payload is larger than the visible\n\t\t// head, so its price keeps a floor above the counted head text.\n\t\tofferIfCheaper({\n\t\t\tkind: \"headroom-compressed\",\n\t\t\ttext: headroomText,\n\t\t\testimatedTokens: Math.max(Math.ceil(full * 0.35) + 16, countTokens(headroomText)),\n\t\t\tfidelity: \"reversible\",\n\t\t\tsourceRef,\n\t\t\tcompressorId: \"headroom-shadow\",\n\t\t});\n\t}\n\n\tif (policy.allowOmit) {\n\t\tcandidates.push({\n\t\t\tkind: \"omit\",\n\t\t\ttext: \"\",\n\t\t\testimatedTokens: 0,\n\t\t\tfidelity: \"lossy\",\n\t\t\tsourceRef,\n\t\t});\n\t}\n\n\treturn candidates;\n}\n\nfunction isSummaryEligible(item: ContextBudgetItemV2, fullTokens: number, policy: HeadroomQualityPolicyV2): boolean {\n\treturn (\n\t\titem.tier === \"history\" ||\n\t\titem.tier === \"evidence\" ||\n\t\titem.tier === \"scratch\" ||\n\t\t(item.ageTurns ?? 0) >= policy.summaryMaxAgeTurns ||\n\t\tfullTokens > policy.headroomThresholdTokens\n\t);\n}\n\nfunction formatPointer(ref: ContextSourceRefV2): string {\n\tconst parts: string[] = [`uri=\"${escapeMetadataValue(ref.uri)}\"`];\n\tif (ref.symbol) parts.push(`symbol=\"${escapeMetadataValue(ref.symbol)}\"`);\n\tif (ref.range) parts.push(`lines=\"${ref.range.startLine}-${ref.range.endLine}\"`);\n\tparts.push(`hash=\"${escapeMetadataValue(ref.contentHash)}\"`);\n\treturn `<pointer ${parts.join(\" \")} />`;\n}\n\nfunction summarizeText(text: string): string {\n\tif (text.length <= SUMMARY_HEAD_CHARS) {\n\t\treturn text;\n\t}\n\treturn `${text.slice(0, SUMMARY_HEAD_CHARS)} …[summary]`;\n}\n\nfunction formatHeadroom(text: string, ref?: ContextSourceRefV2): string {\n\tconst head = text.slice(0, HEADROOM_HEAD_CHARS);\n\tconst hash = fnv1aHex(text);\n\tconst where = ref ? ` uri=\"${escapeMetadataValue(ref.uri)}\"` : \"\";\n\treturn `${head} …[headroom-compressed${where} hash=\"${hash}\"]`;\n}\n\nfunction escapeMetadataValue(value: string): string {\n\treturn value\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&apos;\");\n}\n"]}