@namzu/sdk 45.1.0 → 48.0.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 (767) hide show
  1. package/CHANGELOG.md +436 -8
  2. package/README.md +7 -8
  3. package/dist/advisory/history.d.ts.map +1 -1
  4. package/dist/advisory/history.js +21 -1
  5. package/dist/advisory/history.js.map +1 -1
  6. package/dist/advisory/index.d.ts +1 -1
  7. package/dist/advisory/index.d.ts.map +1 -1
  8. package/dist/advisory/index.js +1 -1
  9. package/dist/advisory/index.js.map +1 -1
  10. package/dist/advisory/registry.d.ts +17 -0
  11. package/dist/advisory/registry.d.ts.map +1 -1
  12. package/dist/advisory/registry.js +26 -0
  13. package/dist/advisory/registry.js.map +1 -1
  14. package/dist/agents/PipelineAgent.d.ts +2 -46
  15. package/dist/agents/PipelineAgent.d.ts.map +1 -1
  16. package/dist/agents/PipelineAgent.js +2 -242
  17. package/dist/agents/PipelineAgent.js.map +1 -1
  18. package/dist/agents/QueryAgent.d.ts +21 -0
  19. package/dist/agents/QueryAgent.d.ts.map +1 -0
  20. package/dist/agents/QueryAgent.js +214 -0
  21. package/dist/agents/QueryAgent.js.map +1 -0
  22. package/dist/agents/ReactiveAgent.d.ts +4 -16
  23. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  24. package/dist/agents/ReactiveAgent.js +4 -183
  25. package/dist/agents/ReactiveAgent.js.map +1 -1
  26. package/dist/agents/RouterAgent.d.ts +2 -20
  27. package/dist/agents/RouterAgent.d.ts.map +1 -1
  28. package/dist/agents/RouterAgent.js +2 -266
  29. package/dist/agents/RouterAgent.js.map +1 -1
  30. package/dist/agents/SupervisorAgent.d.ts +3 -43
  31. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  32. package/dist/agents/SupervisorAgent.js +3 -418
  33. package/dist/agents/SupervisorAgent.js.map +1 -1
  34. package/dist/agents/defineAgent.d.ts +2 -1
  35. package/dist/agents/defineAgent.d.ts.map +1 -1
  36. package/dist/agents/defineAgent.js +6 -1
  37. package/dist/agents/defineAgent.js.map +1 -1
  38. package/dist/agents/examples/PipelineAgent.d.ts +46 -0
  39. package/dist/agents/examples/PipelineAgent.d.ts.map +1 -0
  40. package/dist/agents/examples/PipelineAgent.js +242 -0
  41. package/dist/agents/examples/PipelineAgent.js.map +1 -0
  42. package/dist/agents/examples/RouterAgent.d.ts +22 -0
  43. package/dist/agents/examples/RouterAgent.d.ts.map +1 -0
  44. package/dist/agents/examples/RouterAgent.js +268 -0
  45. package/dist/agents/examples/RouterAgent.js.map +1 -0
  46. package/dist/agents/examples/SupervisorAgent.d.ts +45 -0
  47. package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -0
  48. package/dist/agents/examples/SupervisorAgent.js +406 -0
  49. package/dist/agents/examples/SupervisorAgent.js.map +1 -0
  50. package/dist/agents/explore.d.ts +6 -3
  51. package/dist/agents/explore.d.ts.map +1 -1
  52. package/dist/agents/explore.js +6 -3
  53. package/dist/agents/explore.js.map +1 -1
  54. package/dist/agents/forward-options.d.ts +11 -0
  55. package/dist/agents/forward-options.d.ts.map +1 -0
  56. package/dist/agents/forward-options.js +15 -0
  57. package/dist/agents/forward-options.js.map +1 -0
  58. package/dist/agents/index.d.ts +1 -0
  59. package/dist/agents/index.d.ts.map +1 -1
  60. package/dist/agents/index.js +2 -0
  61. package/dist/agents/index.js.map +1 -1
  62. package/dist/agents/runAgent.d.ts +19 -8
  63. package/dist/agents/runAgent.d.ts.map +1 -1
  64. package/dist/agents/runAgent.js +99 -29
  65. package/dist/agents/runAgent.js.map +1 -1
  66. package/dist/authorization/command-line.d.ts +2 -0
  67. package/dist/authorization/command-line.d.ts.map +1 -1
  68. package/dist/authorization/command-line.js +2 -2
  69. package/dist/authorization/command-line.js.map +1 -1
  70. package/dist/authorization/gate.d.ts +13 -2
  71. package/dist/authorization/gate.d.ts.map +1 -1
  72. package/dist/authorization/gate.js +37 -5
  73. package/dist/authorization/gate.js.map +1 -1
  74. package/dist/authorization/program.d.ts +151 -0
  75. package/dist/authorization/program.d.ts.map +1 -0
  76. package/dist/authorization/program.js +713 -0
  77. package/dist/authorization/program.js.map +1 -0
  78. package/dist/authorization/reexec-wrapper.d.ts +106 -0
  79. package/dist/authorization/reexec-wrapper.d.ts.map +1 -0
  80. package/dist/authorization/reexec-wrapper.js +532 -0
  81. package/dist/authorization/reexec-wrapper.js.map +1 -0
  82. package/dist/authorization/rules.d.ts +9 -0
  83. package/dist/authorization/rules.d.ts.map +1 -1
  84. package/dist/authorization/rules.js +27 -1
  85. package/dist/authorization/rules.js.map +1 -1
  86. package/dist/authorization/shell-lexer.d.ts +39 -0
  87. package/dist/authorization/shell-lexer.d.ts.map +1 -1
  88. package/dist/authorization/shell-lexer.js +113 -69
  89. package/dist/authorization/shell-lexer.js.map +1 -1
  90. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  91. package/dist/bridge/sse/mapper.js +6 -0
  92. package/dist/bridge/sse/mapper.js.map +1 -1
  93. package/dist/capabilities/index.d.ts +54 -0
  94. package/dist/capabilities/index.d.ts.map +1 -0
  95. package/dist/capabilities/index.js +92 -0
  96. package/dist/capabilities/index.js.map +1 -0
  97. package/dist/config/registry.d.ts +2 -1
  98. package/dist/config/registry.d.ts.map +1 -1
  99. package/dist/config/registry.js +3 -2
  100. package/dist/config/registry.js.map +1 -1
  101. package/dist/connector/index.d.ts +4 -4
  102. package/dist/connector/index.d.ts.map +1 -1
  103. package/dist/connector/index.js +3 -3
  104. package/dist/connector/index.js.map +1 -1
  105. package/dist/connector/mcp/adapter.d.ts +16 -1
  106. package/dist/connector/mcp/adapter.d.ts.map +1 -1
  107. package/dist/connector/mcp/adapter.js +60 -4
  108. package/dist/connector/mcp/adapter.js.map +1 -1
  109. package/dist/connector/mcp/client.d.ts +13 -4
  110. package/dist/connector/mcp/client.d.ts.map +1 -1
  111. package/dist/connector/mcp/client.js +20 -3
  112. package/dist/connector/mcp/client.js.map +1 -1
  113. package/dist/connector/mcp/discovery.d.ts +24 -1
  114. package/dist/connector/mcp/discovery.d.ts.map +1 -1
  115. package/dist/connector/mcp/discovery.js +44 -0
  116. package/dist/connector/mcp/discovery.js.map +1 -1
  117. package/dist/connector/mcp/index.d.ts +2 -0
  118. package/dist/connector/mcp/index.d.ts.map +1 -1
  119. package/dist/connector/mcp/index.js +11 -0
  120. package/dist/connector/mcp/index.js.map +1 -1
  121. package/dist/connector/mcp/mcp-toolset.d.ts +133 -0
  122. package/dist/connector/mcp/mcp-toolset.d.ts.map +1 -0
  123. package/dist/connector/mcp/mcp-toolset.js +399 -0
  124. package/dist/connector/mcp/mcp-toolset.js.map +1 -0
  125. package/dist/connector/tools/index.d.ts +2 -2
  126. package/dist/connector/tools/index.d.ts.map +1 -1
  127. package/dist/connector/tools/index.js +1 -1
  128. package/dist/connector/tools/index.js.map +1 -1
  129. package/dist/connector/tools/router.d.ts +15 -13
  130. package/dist/connector/tools/router.d.ts.map +1 -1
  131. package/dist/connector/tools/router.js +30 -51
  132. package/dist/connector/tools/router.js.map +1 -1
  133. package/dist/contracts/a2a.d.ts +2 -2
  134. package/dist/directory/derive-supervisor.d.ts +2 -2
  135. package/dist/directory/derive-supervisor.d.ts.map +1 -1
  136. package/dist/directory/derive-supervisor.js +6 -7
  137. package/dist/directory/derive-supervisor.js.map +1 -1
  138. package/dist/directory/derive.d.ts.map +1 -1
  139. package/dist/directory/derive.js +5 -5
  140. package/dist/directory/derive.js.map +1 -1
  141. package/dist/execution/code-runtime/types.d.ts +2 -2
  142. package/dist/execution/code-runtime/types.js +1 -1
  143. package/dist/invariants/index.d.ts +2 -1
  144. package/dist/invariants/index.d.ts.map +1 -1
  145. package/dist/invariants/index.js +3 -2
  146. package/dist/invariants/index.js.map +1 -1
  147. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  148. package/dist/manager/agent/lifecycle.js +9 -0
  149. package/dist/manager/agent/lifecycle.js.map +1 -1
  150. package/dist/manager/connector/environment.d.ts +6 -0
  151. package/dist/manager/connector/environment.d.ts.map +1 -1
  152. package/dist/manager/connector/environment.js +11 -4
  153. package/dist/manager/connector/environment.js.map +1 -1
  154. package/dist/manager/connector/index.d.ts +2 -2
  155. package/dist/manager/connector/index.d.ts.map +1 -1
  156. package/dist/manager/connector/index.js +2 -2
  157. package/dist/manager/connector/index.js.map +1 -1
  158. package/dist/manager/connector/tenant.d.ts +6 -0
  159. package/dist/manager/connector/tenant.d.ts.map +1 -1
  160. package/dist/manager/connector/tenant.js +11 -4
  161. package/dist/manager/connector/tenant.js.map +1 -1
  162. package/dist/manager/index.d.ts +2 -2
  163. package/dist/manager/index.d.ts.map +1 -1
  164. package/dist/manager/index.js +2 -2
  165. package/dist/manager/index.js.map +1 -1
  166. package/dist/manager/resident/learning-observation.d.ts +4 -4
  167. package/dist/manager/resident/learning.d.ts +36 -36
  168. package/dist/manager/session/attribution.d.ts +22 -0
  169. package/dist/manager/session/attribution.d.ts.map +1 -0
  170. package/dist/manager/session/attribution.js +64 -0
  171. package/dist/manager/session/attribution.js.map +1 -0
  172. package/dist/manager/session/turn-recorder.d.ts +14 -0
  173. package/dist/manager/session/turn-recorder.d.ts.map +1 -1
  174. package/dist/manager/session/turn-recorder.js +208 -55
  175. package/dist/manager/session/turn-recorder.js.map +1 -1
  176. package/dist/peers/address.d.ts +36 -0
  177. package/dist/peers/address.d.ts.map +1 -0
  178. package/dist/peers/address.js +52 -0
  179. package/dist/peers/address.js.map +1 -0
  180. package/dist/peers/client.d.ts +47 -0
  181. package/dist/peers/client.d.ts.map +1 -0
  182. package/dist/peers/client.js +132 -0
  183. package/dist/peers/client.js.map +1 -0
  184. package/dist/peers/dir.d.ts +88 -0
  185. package/dist/peers/dir.d.ts.map +1 -0
  186. package/dist/peers/dir.js +139 -0
  187. package/dist/peers/dir.js.map +1 -0
  188. package/dist/peers/endpoint.d.ts +144 -0
  189. package/dist/peers/endpoint.d.ts.map +1 -0
  190. package/dist/peers/endpoint.js +420 -0
  191. package/dist/peers/endpoint.js.map +1 -0
  192. package/dist/peers/envelope.d.ts +42 -0
  193. package/dist/peers/envelope.d.ts.map +1 -0
  194. package/dist/peers/envelope.js +110 -0
  195. package/dist/peers/envelope.js.map +1 -0
  196. package/dist/peers/index.d.ts +30 -0
  197. package/dist/peers/index.d.ts.map +1 -0
  198. package/dist/peers/index.js +22 -0
  199. package/dist/peers/index.js.map +1 -0
  200. package/dist/peers/protocol.d.ts +645 -0
  201. package/dist/peers/protocol.d.ts.map +1 -0
  202. package/dist/peers/protocol.js +151 -0
  203. package/dist/peers/protocol.js.map +1 -0
  204. package/dist/peers/record.d.ts +71 -0
  205. package/dist/peers/record.d.ts.map +1 -0
  206. package/dist/peers/record.js +45 -0
  207. package/dist/peers/record.js.map +1 -0
  208. package/dist/peers/registry.d.ts +54 -0
  209. package/dist/peers/registry.d.ts.map +1 -0
  210. package/dist/peers/registry.js +213 -0
  211. package/dist/peers/registry.js.map +1 -0
  212. package/dist/plugin/define.d.ts +24 -0
  213. package/dist/plugin/define.d.ts.map +1 -0
  214. package/dist/plugin/define.js +42 -0
  215. package/dist/plugin/define.js.map +1 -0
  216. package/dist/plugin/index.d.ts +2 -0
  217. package/dist/plugin/index.d.ts.map +1 -1
  218. package/dist/plugin/index.js +1 -0
  219. package/dist/plugin/index.js.map +1 -1
  220. package/dist/plugin/lifecycle.d.ts +27 -3
  221. package/dist/plugin/lifecycle.d.ts.map +1 -1
  222. package/dist/plugin/lifecycle.js +242 -92
  223. package/dist/plugin/lifecycle.js.map +1 -1
  224. package/dist/plugin/resolver.d.ts +2 -2
  225. package/dist/plugin/resolver.d.ts.map +1 -1
  226. package/dist/plugin/resolver.js.map +1 -1
  227. package/dist/plugin/shell-hook.d.ts.map +1 -1
  228. package/dist/plugin/shell-hook.js +17 -3
  229. package/dist/plugin/shell-hook.js.map +1 -1
  230. package/dist/pricing/catalogue.generated.d.ts.map +1 -1
  231. package/dist/pricing/catalogue.generated.js +28 -4
  232. package/dist/pricing/catalogue.generated.js.map +1 -1
  233. package/dist/probe/errors.d.ts +2 -1
  234. package/dist/probe/errors.d.ts.map +1 -1
  235. package/dist/probe/errors.js +3 -2
  236. package/dist/probe/errors.js.map +1 -1
  237. package/dist/prompt/coding-agent-doctrine.d.ts +18 -7
  238. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  239. package/dist/prompt/coding-agent-doctrine.js +11 -6
  240. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  241. package/dist/prompt/contributions.d.ts +4 -1
  242. package/dist/prompt/contributions.d.ts.map +1 -1
  243. package/dist/prompt/contributions.js +7 -2
  244. package/dist/prompt/contributions.js.map +1 -1
  245. package/dist/prompt/index.d.ts +1 -1
  246. package/dist/prompt/index.d.ts.map +1 -1
  247. package/dist/prompt/index.js +1 -1
  248. package/dist/prompt/index.js.map +1 -1
  249. package/dist/provider/collect-chat-completion.d.ts +6 -1
  250. package/dist/provider/collect-chat-completion.d.ts.map +1 -1
  251. package/dist/provider/collect-chat-completion.js +88 -10
  252. package/dist/provider/collect-chat-completion.js.map +1 -1
  253. package/dist/provider/mock.d.ts.map +1 -1
  254. package/dist/provider/mock.js +23 -6
  255. package/dist/provider/mock.js.map +1 -1
  256. package/dist/provider/registry.d.ts +2 -1
  257. package/dist/provider/registry.d.ts.map +1 -1
  258. package/dist/provider/registry.js +3 -2
  259. package/dist/provider/registry.js.map +1 -1
  260. package/dist/provider/tool-call-framing.d.ts +164 -0
  261. package/dist/provider/tool-call-framing.d.ts.map +1 -0
  262. package/dist/provider/tool-call-framing.js +163 -0
  263. package/dist/provider/tool-call-framing.js.map +1 -0
  264. package/dist/public-runtime.d.ts +27 -14
  265. package/dist/public-runtime.d.ts.map +1 -1
  266. package/dist/public-runtime.js +49 -11
  267. package/dist/public-runtime.js.map +1 -1
  268. package/dist/public-tools.d.ts +9 -6
  269. package/dist/public-tools.d.ts.map +1 -1
  270. package/dist/public-tools.js +13 -5
  271. package/dist/public-tools.js.map +1 -1
  272. package/dist/public-types.d.ts +16 -5
  273. package/dist/public-types.d.ts.map +1 -1
  274. package/dist/read-model/registry.d.ts +2 -1
  275. package/dist/read-model/registry.d.ts.map +1 -1
  276. package/dist/read-model/registry.js +3 -2
  277. package/dist/read-model/registry.js.map +1 -1
  278. package/dist/registry/ManagedRegistry.d.ts +30 -0
  279. package/dist/registry/ManagedRegistry.d.ts.map +1 -1
  280. package/dist/registry/ManagedRegistry.js +45 -6
  281. package/dist/registry/ManagedRegistry.js.map +1 -1
  282. package/dist/registry/collision.d.ts +57 -0
  283. package/dist/registry/collision.d.ts.map +1 -0
  284. package/dist/registry/collision.js +41 -0
  285. package/dist/registry/collision.js.map +1 -0
  286. package/dist/registry/command/index.d.ts +5 -3
  287. package/dist/registry/command/index.d.ts.map +1 -1
  288. package/dist/registry/command/index.js +6 -4
  289. package/dist/registry/command/index.js.map +1 -1
  290. package/dist/registry/index.d.ts +3 -4
  291. package/dist/registry/index.d.ts.map +1 -1
  292. package/dist/registry/index.js +2 -2
  293. package/dist/registry/index.js.map +1 -1
  294. package/dist/registry/plugin/index.d.ts.map +1 -1
  295. package/dist/registry/plugin/index.js +14 -1
  296. package/dist/registry/plugin/index.js.map +1 -1
  297. package/dist/registry/tool/callable.d.ts +22 -0
  298. package/dist/registry/tool/callable.d.ts.map +1 -0
  299. package/dist/registry/tool/callable.js +28 -0
  300. package/dist/registry/tool/callable.js.map +1 -0
  301. package/dist/registry/tool/execute.d.ts +14 -77
  302. package/dist/registry/tool/execute.d.ts.map +1 -1
  303. package/dist/registry/tool/execute.js +15 -720
  304. package/dist/registry/tool/execute.js.map +1 -1
  305. package/dist/registry/tool/portable.d.ts +25 -0
  306. package/dist/registry/tool/portable.d.ts.map +1 -1
  307. package/dist/registry/tool/portable.js +50 -0
  308. package/dist/registry/tool/portable.js.map +1 -1
  309. package/dist/registry/tool/presentation.d.ts +6 -5
  310. package/dist/registry/tool/presentation.d.ts.map +1 -1
  311. package/dist/registry/tool/presentation.js +3 -3
  312. package/dist/registry/tool/presentation.js.map +1 -1
  313. package/dist/runtime/bidi/session.d.ts +5 -4
  314. package/dist/runtime/bidi/session.d.ts.map +1 -1
  315. package/dist/runtime/bidi/session.js +18 -1
  316. package/dist/runtime/bidi/session.js.map +1 -1
  317. package/dist/runtime/query/executor/tool-call-admission.d.ts +82 -13
  318. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  319. package/dist/runtime/query/executor/tool-call-admission.js +227 -17
  320. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  321. package/dist/runtime/query/executor.d.ts +37 -5
  322. package/dist/runtime/query/executor.d.ts.map +1 -1
  323. package/dist/runtime/query/executor.js +103 -14
  324. package/dist/runtime/query/executor.js.map +1 -1
  325. package/dist/runtime/query/file-evidence-replay.d.ts +1 -1
  326. package/dist/runtime/query/file-evidence-replay.d.ts.map +1 -1
  327. package/dist/runtime/query/file-evidence-replay.js +8 -7
  328. package/dist/runtime/query/file-evidence-replay.js.map +1 -1
  329. package/dist/runtime/query/fork/prepare.d.ts +4 -1
  330. package/dist/runtime/query/fork/prepare.d.ts.map +1 -1
  331. package/dist/runtime/query/fork/prepare.js +4 -0
  332. package/dist/runtime/query/fork/prepare.js.map +1 -1
  333. package/dist/runtime/query/guardrail-presets.d.ts +4 -3
  334. package/dist/runtime/query/guardrail-presets.d.ts.map +1 -1
  335. package/dist/runtime/query/guardrail-presets.js +4 -3
  336. package/dist/runtime/query/guardrail-presets.js.map +1 -1
  337. package/dist/runtime/query/index.d.ts +23 -10
  338. package/dist/runtime/query/index.d.ts.map +1 -1
  339. package/dist/runtime/query/index.js +149 -70
  340. package/dist/runtime/query/index.js.map +1 -1
  341. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  342. package/dist/runtime/query/iteration/index.js +8 -1
  343. package/dist/runtime/query/iteration/index.js.map +1 -1
  344. package/dist/runtime/query/iteration/phases/compaction.js +1 -1
  345. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  346. package/dist/runtime/query/iteration/phases/context.d.ts +2 -2
  347. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  348. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  349. package/dist/runtime/query/iteration/phases/tool-review.js +55 -2
  350. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  351. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  352. package/dist/runtime/query/iteration/stream-turn.js +342 -116
  353. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  354. package/dist/runtime/query/iteration/tool-input.d.ts +79 -0
  355. package/dist/runtime/query/iteration/tool-input.d.ts.map +1 -0
  356. package/dist/runtime/query/iteration/tool-input.js +291 -0
  357. package/dist/runtime/query/iteration/tool-input.js.map +1 -0
  358. package/dist/runtime/query/observation-context.d.ts +2 -2
  359. package/dist/runtime/query/observation-context.d.ts.map +1 -1
  360. package/dist/runtime/query/observation-context.js.map +1 -1
  361. package/dist/runtime/query/prelude-lease.d.ts +18 -0
  362. package/dist/runtime/query/prelude-lease.d.ts.map +1 -0
  363. package/dist/runtime/query/prelude-lease.js +121 -0
  364. package/dist/runtime/query/prelude-lease.js.map +1 -0
  365. package/dist/runtime/query/prepare-turn.d.ts.map +1 -1
  366. package/dist/runtime/query/prepare-turn.js +386 -187
  367. package/dist/runtime/query/prepare-turn.js.map +1 -1
  368. package/dist/runtime/query/prompt-cache.d.ts +2 -2
  369. package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
  370. package/dist/runtime/query/prompt.d.ts +2 -2
  371. package/dist/runtime/query/prompt.d.ts.map +1 -1
  372. package/dist/runtime/query/prompt.js +1 -1
  373. package/dist/runtime/query/prompt.js.map +1 -1
  374. package/dist/runtime/query/resume-session.d.ts.map +1 -1
  375. package/dist/runtime/query/resume-session.js +37 -2
  376. package/dist/runtime/query/resume-session.js.map +1 -1
  377. package/dist/runtime/query/review-policy.d.ts +65 -3
  378. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  379. package/dist/runtime/query/review-policy.js +143 -22
  380. package/dist/runtime/query/review-policy.js.map +1 -1
  381. package/dist/runtime/query/tooling.d.ts +3 -2
  382. package/dist/runtime/query/tooling.d.ts.map +1 -1
  383. package/dist/runtime/query/tooling.js.map +1 -1
  384. package/dist/runtime/query/turn-state.d.ts.map +1 -1
  385. package/dist/runtime/query/turn-state.js +5 -0
  386. package/dist/runtime/query/turn-state.js.map +1 -1
  387. package/dist/runtime/system-events.d.ts +112 -0
  388. package/dist/runtime/system-events.d.ts.map +1 -0
  389. package/dist/runtime/system-events.js +183 -0
  390. package/dist/runtime/system-events.js.map +1 -0
  391. package/dist/scheduler/delegating.d.ts +2 -1
  392. package/dist/scheduler/delegating.d.ts.map +1 -1
  393. package/dist/scheduler/delegating.js +3 -2
  394. package/dist/scheduler/delegating.js.map +1 -1
  395. package/dist/skills/index.d.ts +1 -1
  396. package/dist/skills/index.d.ts.map +1 -1
  397. package/dist/skills/index.js +1 -1
  398. package/dist/skills/index.js.map +1 -1
  399. package/dist/skills/registry.d.ts +18 -0
  400. package/dist/skills/registry.d.ts.map +1 -1
  401. package/dist/skills/registry.js +20 -0
  402. package/dist/skills/registry.js.map +1 -1
  403. package/dist/store/evidence/index-page.d.ts +2 -2
  404. package/dist/store/session-log/conformance.d.ts +1 -1
  405. package/dist/store/session-log/conformance.d.ts.map +1 -1
  406. package/dist/store/session-log/conformance.js +49 -8
  407. package/dist/store/session-log/conformance.js.map +1 -1
  408. package/dist/store/session-log/core.d.ts +8 -3
  409. package/dist/store/session-log/core.d.ts.map +1 -1
  410. package/dist/store/session-log/core.js +2 -1
  411. package/dist/store/session-log/core.js.map +1 -1
  412. package/dist/store/session-log/fold.d.ts +12 -0
  413. package/dist/store/session-log/fold.d.ts.map +1 -1
  414. package/dist/store/session-log/fold.js +57 -7
  415. package/dist/store/session-log/fold.js.map +1 -1
  416. package/dist/store/session-log/index.d.ts +2 -2
  417. package/dist/store/session-log/index.d.ts.map +1 -1
  418. package/dist/store/session-log/index.js +1 -1
  419. package/dist/store/session-log/index.js.map +1 -1
  420. package/dist/test-support/toolset.d.ts +19 -0
  421. package/dist/test-support/toolset.d.ts.map +1 -0
  422. package/dist/test-support/toolset.js +20 -0
  423. package/dist/test-support/toolset.js.map +1 -0
  424. package/dist/tools/builtins/bash.d.ts +29 -0
  425. package/dist/tools/builtins/bash.d.ts.map +1 -1
  426. package/dist/tools/builtins/bash.js +19 -9
  427. package/dist/tools/builtins/bash.js.map +1 -1
  428. package/dist/tools/builtins/browser-url.d.ts +1 -1
  429. package/dist/tools/builtins/browser-url.js +1 -1
  430. package/dist/tools/builtins/browser.d.ts +6 -6
  431. package/dist/tools/builtins/computer-use-coordinates.d.ts +65 -0
  432. package/dist/tools/builtins/computer-use-coordinates.d.ts.map +1 -0
  433. package/dist/tools/builtins/computer-use-coordinates.js +123 -0
  434. package/dist/tools/builtins/computer-use-coordinates.js.map +1 -0
  435. package/dist/tools/builtins/computer-use-image.d.ts +77 -0
  436. package/dist/tools/builtins/computer-use-image.d.ts.map +1 -0
  437. package/dist/tools/builtins/computer-use-image.js +223 -0
  438. package/dist/tools/builtins/computer-use-image.js.map +1 -0
  439. package/dist/tools/builtins/computer-use.d.ts +519 -14
  440. package/dist/tools/builtins/computer-use.d.ts.map +1 -1
  441. package/dist/tools/builtins/computer-use.js +1196 -183
  442. package/dist/tools/builtins/computer-use.js.map +1 -1
  443. package/dist/tools/builtins/edit.d.ts.map +1 -1
  444. package/dist/tools/builtins/edit.js +9 -1
  445. package/dist/tools/builtins/edit.js.map +1 -1
  446. package/dist/tools/builtins/index.d.ts +2 -1
  447. package/dist/tools/builtins/index.d.ts.map +1 -1
  448. package/dist/tools/builtins/index.js +1 -1
  449. package/dist/tools/builtins/index.js.map +1 -1
  450. package/dist/tools/builtins/json-string-hint.d.ts +15 -0
  451. package/dist/tools/builtins/json-string-hint.d.ts.map +1 -0
  452. package/dist/tools/builtins/json-string-hint.js +17 -0
  453. package/dist/tools/builtins/json-string-hint.js.map +1 -0
  454. package/dist/tools/builtins/search-tools.d.ts.map +1 -1
  455. package/dist/tools/builtins/search-tools.js +7 -15
  456. package/dist/tools/builtins/search-tools.js.map +1 -1
  457. package/dist/tools/builtins/skill.d.ts +74 -0
  458. package/dist/tools/builtins/skill.d.ts.map +1 -1
  459. package/dist/tools/builtins/skill.js +214 -174
  460. package/dist/tools/builtins/skill.js.map +1 -1
  461. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  462. package/dist/tools/builtins/write-file.js +11 -0
  463. package/dist/tools/builtins/write-file.js.map +1 -1
  464. package/dist/tools/command-shell.d.ts +10 -0
  465. package/dist/tools/command-shell.d.ts.map +1 -1
  466. package/dist/tools/command-shell.js +45 -1
  467. package/dist/tools/command-shell.js.map +1 -1
  468. package/dist/tools/coordinator/agent.d.ts.map +1 -1
  469. package/dist/tools/coordinator/agent.js +5 -0
  470. package/dist/tools/coordinator/agent.js.map +1 -1
  471. package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
  472. package/dist/tools/coordinator/ask-user-question.js +26 -13
  473. package/dist/tools/coordinator/ask-user-question.js.map +1 -1
  474. package/dist/tools/coordinator/index.d.ts.map +1 -1
  475. package/dist/tools/coordinator/index.js +5 -0
  476. package/dist/tools/coordinator/index.js.map +1 -1
  477. package/dist/tools/coordinator/question-options.d.ts +78 -0
  478. package/dist/tools/coordinator/question-options.d.ts.map +1 -0
  479. package/dist/tools/coordinator/question-options.js +153 -0
  480. package/dist/tools/coordinator/question-options.js.map +1 -0
  481. package/dist/tools/defineTool.d.ts +12 -0
  482. package/dist/tools/defineTool.d.ts.map +1 -1
  483. package/dist/tools/defineTool.js +24 -0
  484. package/dist/tools/defineTool.js.map +1 -1
  485. package/dist/tools/memory/search.d.ts.map +1 -1
  486. package/dist/tools/memory/search.js +4 -1
  487. package/dist/tools/memory/search.js.map +1 -1
  488. package/dist/tools/memory/update.d.ts.map +1 -1
  489. package/dist/tools/memory/update.js +8 -5
  490. package/dist/tools/memory/update.js.map +1 -1
  491. package/dist/tools/render-nonce.d.ts +47 -0
  492. package/dist/tools/render-nonce.d.ts.map +1 -0
  493. package/dist/tools/render-nonce.js +63 -0
  494. package/dist/tools/render-nonce.js.map +1 -0
  495. package/dist/tools/roster.d.ts +46 -19
  496. package/dist/tools/roster.d.ts.map +1 -1
  497. package/dist/tools/roster.js +63 -33
  498. package/dist/tools/roster.js.map +1 -1
  499. package/dist/tools/schedules/present.d.ts.map +1 -1
  500. package/dist/tools/schedules/present.js +2 -0
  501. package/dist/tools/schedules/present.js.map +1 -1
  502. package/dist/tools/schedules/schedule-tool.d.ts +6 -5
  503. package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
  504. package/dist/tools/schedules/schedule-tool.js +208 -37
  505. package/dist/tools/schedules/schedule-tool.js.map +1 -1
  506. package/dist/tools/schedules/types.d.ts +120 -6
  507. package/dist/tools/schedules/types.d.ts.map +1 -1
  508. package/dist/tools/trusted-read-only.d.ts +9 -5
  509. package/dist/tools/trusted-read-only.d.ts.map +1 -1
  510. package/dist/tools/trusted-read-only.js +14 -10
  511. package/dist/tools/trusted-read-only.js.map +1 -1
  512. package/dist/tools/untrusted-envelope.d.ts +67 -28
  513. package/dist/tools/untrusted-envelope.d.ts.map +1 -1
  514. package/dist/tools/untrusted-envelope.js +108 -59
  515. package/dist/tools/untrusted-envelope.js.map +1 -1
  516. package/dist/toolsets/combine.d.ts +44 -0
  517. package/dist/toolsets/combine.d.ts.map +1 -0
  518. package/dist/toolsets/combine.js +153 -0
  519. package/dist/toolsets/combine.js.map +1 -0
  520. package/dist/toolsets/manager.d.ts +201 -0
  521. package/dist/toolsets/manager.d.ts.map +1 -0
  522. package/dist/toolsets/manager.js +837 -0
  523. package/dist/toolsets/manager.js.map +1 -0
  524. package/dist/toolsets/source-glob.d.ts +15 -0
  525. package/dist/toolsets/source-glob.d.ts.map +1 -0
  526. package/dist/toolsets/source-glob.js +23 -0
  527. package/dist/toolsets/source-glob.js.map +1 -0
  528. package/dist/toolsets/toolset.d.ts +20 -0
  529. package/dist/toolsets/toolset.d.ts.map +1 -0
  530. package/dist/toolsets/toolset.js +28 -0
  531. package/dist/toolsets/toolset.js.map +1 -0
  532. package/dist/toolsets/types.d.ts +128 -0
  533. package/dist/toolsets/types.d.ts.map +1 -0
  534. package/dist/toolsets/types.js +33 -0
  535. package/dist/toolsets/types.js.map +1 -0
  536. package/dist/toolsets/wrappers.d.ts +59 -0
  537. package/dist/toolsets/wrappers.d.ts.map +1 -0
  538. package/dist/toolsets/wrappers.js +165 -0
  539. package/dist/toolsets/wrappers.js.map +1 -0
  540. package/dist/types/agent/base.d.ts +27 -16
  541. package/dist/types/agent/base.d.ts.map +1 -1
  542. package/dist/types/agent/index.d.ts +1 -0
  543. package/dist/types/agent/index.d.ts.map +1 -1
  544. package/dist/types/agent/index.js +1 -0
  545. package/dist/types/agent/index.js.map +1 -1
  546. package/dist/types/agent/pipeline.d.ts +2 -0
  547. package/dist/types/agent/pipeline.d.ts.map +1 -1
  548. package/dist/types/agent/query.d.ts +117 -0
  549. package/dist/types/agent/query.d.ts.map +1 -0
  550. package/dist/types/agent/query.js +2 -0
  551. package/dist/types/agent/query.js.map +1 -0
  552. package/dist/types/agent/reactive.d.ts +2 -129
  553. package/dist/types/agent/reactive.d.ts.map +1 -1
  554. package/dist/types/agent/router.d.ts +2 -0
  555. package/dist/types/agent/router.d.ts.map +1 -1
  556. package/dist/types/agent/supervisor.d.ts +5 -2
  557. package/dist/types/agent/supervisor.d.ts.map +1 -1
  558. package/dist/types/authorization/index.d.ts +70 -12
  559. package/dist/types/authorization/index.d.ts.map +1 -1
  560. package/dist/types/authorization/index.js +11 -0
  561. package/dist/types/authorization/index.js.map +1 -1
  562. package/dist/types/computer-use/index.d.ts +176 -0
  563. package/dist/types/computer-use/index.d.ts.map +1 -1
  564. package/dist/types/computer-use/index.js.map +1 -1
  565. package/dist/types/connector/mcp.d.ts +32 -0
  566. package/dist/types/connector/mcp.d.ts.map +1 -1
  567. package/dist/types/errors/index.d.ts +15 -0
  568. package/dist/types/errors/index.d.ts.map +1 -1
  569. package/dist/types/errors/index.js.map +1 -1
  570. package/dist/types/hitl/index.d.ts +57 -0
  571. package/dist/types/hitl/index.d.ts.map +1 -1
  572. package/dist/types/hitl/index.js.map +1 -1
  573. package/dist/types/message/index.d.ts +130 -9
  574. package/dist/types/message/index.d.ts.map +1 -1
  575. package/dist/types/message/index.js +4 -1
  576. package/dist/types/message/index.js.map +1 -1
  577. package/dist/types/plugin/index.d.ts +22 -4
  578. package/dist/types/plugin/index.d.ts.map +1 -1
  579. package/dist/types/plugin/index.js +1 -0
  580. package/dist/types/plugin/index.js.map +1 -1
  581. package/dist/types/provider/chat.d.ts +5 -0
  582. package/dist/types/provider/chat.d.ts.map +1 -1
  583. package/dist/types/provider/config.d.ts +8 -3
  584. package/dist/types/provider/config.d.ts.map +1 -1
  585. package/dist/types/provider/stream.d.ts +39 -0
  586. package/dist/types/provider/stream.d.ts.map +1 -1
  587. package/dist/types/sandbox/index.d.ts +1 -1
  588. package/dist/types/session/events.d.ts +14 -3
  589. package/dist/types/session/events.d.ts.map +1 -1
  590. package/dist/types/session/events.js.map +1 -1
  591. package/dist/types/tool/index.d.ts +171 -91
  592. package/dist/types/tool/index.d.ts.map +1 -1
  593. package/dist/types/tool/index.js.map +1 -1
  594. package/dist/types/toolset/index.d.ts +10 -40
  595. package/dist/types/toolset/index.d.ts.map +1 -1
  596. package/package.json +3 -1
  597. package/src/advisory/history.ts +27 -2
  598. package/src/advisory/index.ts +1 -1
  599. package/src/advisory/registry.ts +33 -0
  600. package/src/agents/AGENTS.md +14 -7
  601. package/src/agents/PipelineAgent.ts +2 -303
  602. package/src/agents/QueryAgent.ts +269 -0
  603. package/src/agents/ReactiveAgent.ts +6 -216
  604. package/src/agents/RouterAgent.ts +2 -337
  605. package/src/agents/SupervisorAgent.ts +3 -476
  606. package/src/agents/defineAgent.ts +13 -2
  607. package/src/agents/examples/PipelineAgent.ts +302 -0
  608. package/src/agents/examples/RouterAgent.ts +338 -0
  609. package/src/agents/examples/SupervisorAgent.ts +472 -0
  610. package/src/agents/explore.ts +6 -3
  611. package/src/agents/forward-options.ts +37 -0
  612. package/src/agents/index.ts +2 -0
  613. package/src/agents/runAgent.ts +144 -37
  614. package/src/authorization/command-line.ts +2 -2
  615. package/src/authorization/gate.ts +46 -5
  616. package/src/authorization/program.ts +773 -0
  617. package/src/authorization/reexec-wrapper.ts +589 -0
  618. package/src/authorization/rules.ts +36 -1
  619. package/src/authorization/shell-lexer.ts +136 -63
  620. package/src/bridge/sse/mapper.ts +6 -0
  621. package/src/capabilities/index.ts +157 -0
  622. package/src/config/registry.ts +4 -1
  623. package/src/connector/index.ts +9 -2
  624. package/src/connector/mcp/adapter.ts +58 -3
  625. package/src/connector/mcp/client.ts +20 -4
  626. package/src/connector/mcp/discovery.ts +60 -0
  627. package/src/connector/mcp/index.ts +13 -0
  628. package/src/connector/mcp/mcp-toolset.ts +515 -0
  629. package/src/connector/tools/index.ts +2 -2
  630. package/src/connector/tools/router.ts +35 -58
  631. package/src/directory/derive-supervisor.ts +12 -8
  632. package/src/directory/derive.ts +8 -5
  633. package/src/execution/code-runtime/types.ts +2 -2
  634. package/src/invariants/index.ts +4 -1
  635. package/src/manager/agent/lifecycle.ts +9 -0
  636. package/src/manager/connector/environment.ts +17 -4
  637. package/src/manager/connector/index.ts +2 -2
  638. package/src/manager/connector/tenant.ts +17 -4
  639. package/src/manager/index.ts +2 -2
  640. package/src/manager/session/attribution.ts +79 -0
  641. package/src/manager/session/turn-recorder.ts +211 -55
  642. package/src/peers/address.ts +58 -0
  643. package/src/peers/client.ts +202 -0
  644. package/src/peers/dir.ts +176 -0
  645. package/src/peers/endpoint.ts +564 -0
  646. package/src/peers/envelope.ts +121 -0
  647. package/src/peers/index.ts +96 -0
  648. package/src/peers/protocol.ts +196 -0
  649. package/src/peers/record.ts +56 -0
  650. package/src/peers/registry.ts +241 -0
  651. package/src/plugin/define.ts +68 -0
  652. package/src/plugin/index.ts +2 -0
  653. package/src/plugin/lifecycle.ts +286 -106
  654. package/src/plugin/resolver.ts +6 -3
  655. package/src/plugin/shell-hook.ts +21 -5
  656. package/src/pricing/catalogue.generated.ts +28 -4
  657. package/src/pricing/rates.source.json +27 -6
  658. package/src/probe/errors.ts +4 -1
  659. package/src/prompt/coding-agent-doctrine.ts +22 -10
  660. package/src/prompt/contributions.ts +12 -2
  661. package/src/prompt/index.ts +1 -0
  662. package/src/provider/collect-chat-completion.ts +96 -11
  663. package/src/provider/mock.ts +24 -6
  664. package/src/provider/registry.ts +4 -1
  665. package/src/provider/tool-call-framing.ts +226 -0
  666. package/src/public-runtime.ts +152 -9
  667. package/src/public-tools.ts +43 -5
  668. package/src/public-types.ts +65 -6
  669. package/src/read-model/registry.ts +7 -2
  670. package/src/registry/ManagedRegistry.ts +57 -6
  671. package/src/registry/collision.ts +64 -0
  672. package/src/registry/command/index.ts +7 -3
  673. package/src/registry/index.ts +3 -9
  674. package/src/registry/plugin/index.ts +14 -1
  675. package/src/registry/tool/callable.ts +36 -0
  676. package/src/registry/tool/execute.ts +16 -839
  677. package/src/registry/tool/portable.ts +59 -0
  678. package/src/registry/tool/presentation.ts +6 -5
  679. package/src/runtime/bidi/session.ts +24 -5
  680. package/src/runtime/query/executor/tool-call-admission.ts +288 -22
  681. package/src/runtime/query/executor.ts +129 -16
  682. package/src/runtime/query/file-evidence-replay.ts +8 -7
  683. package/src/runtime/query/fork/prepare.ts +6 -1
  684. package/src/runtime/query/guardrail-presets.ts +4 -3
  685. package/src/runtime/query/index.ts +199 -101
  686. package/src/runtime/query/iteration/index.ts +13 -3
  687. package/src/runtime/query/iteration/phases/compaction.ts +1 -1
  688. package/src/runtime/query/iteration/phases/context.ts +2 -2
  689. package/src/runtime/query/iteration/phases/tool-review.ts +59 -2
  690. package/src/runtime/query/iteration/stream-turn.ts +390 -136
  691. package/src/runtime/query/iteration/tool-input.ts +284 -0
  692. package/src/runtime/query/observation-context.ts +2 -2
  693. package/src/runtime/query/prelude-lease.ts +132 -0
  694. package/src/runtime/query/prepare-turn.ts +477 -198
  695. package/src/runtime/query/prompt-cache.ts +2 -2
  696. package/src/runtime/query/prompt.ts +4 -4
  697. package/src/runtime/query/resume-session.ts +42 -3
  698. package/src/runtime/query/review-policy.ts +190 -24
  699. package/src/runtime/query/tooling.ts +3 -6
  700. package/src/runtime/query/turn-state.ts +4 -0
  701. package/src/runtime/system-events.ts +246 -0
  702. package/src/scheduler/delegating.ts +7 -2
  703. package/src/skills/index.ts +1 -1
  704. package/src/skills/registry.ts +33 -0
  705. package/src/store/session-log/conformance.ts +51 -8
  706. package/src/store/session-log/core.ts +10 -4
  707. package/src/store/session-log/fold.ts +33 -7
  708. package/src/store/session-log/index.ts +2 -0
  709. package/src/test-support/toolset.ts +23 -0
  710. package/src/tools/builtins/bash.ts +27 -10
  711. package/src/tools/builtins/browser-url.ts +1 -1
  712. package/src/tools/builtins/computer-use-coordinates.ts +144 -0
  713. package/src/tools/builtins/computer-use-image.ts +278 -0
  714. package/src/tools/builtins/computer-use.ts +1495 -191
  715. package/src/tools/builtins/edit.ts +12 -2
  716. package/src/tools/builtins/index.ts +7 -1
  717. package/src/tools/builtins/json-string-hint.ts +16 -0
  718. package/src/tools/builtins/search-tools.ts +7 -20
  719. package/src/tools/builtins/skill.ts +304 -174
  720. package/src/tools/builtins/write-file.ts +12 -0
  721. package/src/tools/command-shell.ts +46 -1
  722. package/src/tools/coordinator/agent.ts +6 -0
  723. package/src/tools/coordinator/ask-user-question.ts +29 -15
  724. package/src/tools/coordinator/index.ts +6 -0
  725. package/src/tools/coordinator/question-options.ts +195 -0
  726. package/src/tools/defineTool.ts +38 -0
  727. package/src/tools/memory/search.ts +4 -1
  728. package/src/tools/memory/update.ts +8 -5
  729. package/src/tools/render-nonce.ts +69 -0
  730. package/src/tools/roster.ts +84 -33
  731. package/src/tools/schedules/present.ts +2 -0
  732. package/src/tools/schedules/schedule-tool.ts +238 -39
  733. package/src/tools/schedules/types.ts +120 -6
  734. package/src/tools/trusted-read-only.ts +19 -10
  735. package/src/tools/untrusted-envelope.ts +121 -57
  736. package/src/toolsets/combine.ts +181 -0
  737. package/src/toolsets/manager.ts +996 -0
  738. package/src/toolsets/source-glob.ts +22 -0
  739. package/src/toolsets/toolset.ts +31 -0
  740. package/src/toolsets/types.ts +154 -0
  741. package/src/toolsets/wrappers.ts +191 -0
  742. package/src/types/agent/base.ts +29 -16
  743. package/src/types/agent/index.ts +1 -0
  744. package/src/types/agent/pipeline.ts +2 -0
  745. package/src/types/agent/query.ts +129 -0
  746. package/src/types/agent/reactive.ts +5 -142
  747. package/src/types/agent/router.ts +2 -0
  748. package/src/types/agent/supervisor.ts +5 -2
  749. package/src/types/authorization/index.ts +33 -0
  750. package/src/types/computer-use/index.ts +202 -0
  751. package/src/types/connector/mcp.ts +32 -0
  752. package/src/types/errors/index.ts +15 -0
  753. package/src/types/hitl/index.ts +57 -0
  754. package/src/types/message/index.ts +135 -7
  755. package/src/types/plugin/index.ts +44 -21
  756. package/src/types/provider/chat.ts +5 -0
  757. package/src/types/provider/config.ts +8 -3
  758. package/src/types/provider/stream.ts +39 -0
  759. package/src/types/sandbox/index.ts +1 -1
  760. package/src/types/session/events.ts +14 -3
  761. package/src/types/tool/index.ts +173 -105
  762. package/src/types/toolset/index.ts +10 -47
  763. package/dist/registry/toolset/catalog.d.ts +0 -42
  764. package/dist/registry/toolset/catalog.d.ts.map +0 -1
  765. package/dist/registry/toolset/catalog.js +0 -234
  766. package/dist/registry/toolset/catalog.js.map +0 -1
  767. package/src/registry/toolset/catalog.ts +0 -308
@@ -1,10 +1,16 @@
1
+ import { isDeepStrictEqual } from 'node:util'
1
2
  import { drainQueuedMessages } from '../../agents/handle.js'
2
3
  import {
3
4
  type ToolHistoryRepairReport,
4
5
  repairToolMessageHistory,
5
6
  toolHistoryRepairChanged,
6
7
  } from '../../compaction/dangling.js'
7
- import { type RecordedMessage, readFoldedHistory } from '../../manager/session/turn-recorder.js'
8
+ import { assertSessionLogAttribution } from '../../manager/session/attribution.js'
9
+ import {
10
+ type RecordedMessage,
11
+ readEverRecordedMessages,
12
+ readFoldedHistory,
13
+ } from '../../manager/session/turn-recorder.js'
8
14
  import { resolveModelPricing } from '../../pricing/index.js'
9
15
  import { isCallerAbortError } from '../../provider/errors.js'
10
16
  import {
@@ -17,6 +23,7 @@ import { withProviderRetry } from '../../provider/retry.js'
17
23
  import { withTokenBudget } from '../../provider/token-budget.js'
18
24
  import { resolveAttachments } from '../../store/attachment/index.js'
19
25
  import type { SessionTokenBudget } from '../../store/budget/index.js'
26
+ import type { SessionLog } from '../../store/session-log/index.js'
20
27
  import { NAMZU } from '../../telemetry/attributes.js'
21
28
  import type { SerializedSpanContext } from '../../telemetry/attributes.js'
22
29
  import type { TaskScheduler } from '../../types/agent/scheduler.js'
@@ -41,9 +48,11 @@ import { EventTranslator } from './events.js'
41
48
  import type { QueryParams } from './index.js'
42
49
  import { isCompactionMessage } from './iteration/phases/compaction.js'
43
50
  import { isWorkingMemoryMessage } from './iteration/phases/working-memory.js'
51
+ import { PreludeSessionLease } from './prelude-lease.js'
44
52
  import {
45
53
  awaitProjectInstructionCallback,
46
54
  collapseProjectInstructionSnapshots,
55
+ isProjectInstructionMessage,
47
56
  replaceProjectInstructionSnapshot,
48
57
  } from './project-instructions.js'
49
58
  import type { PromptCache } from './prompt-cache.js'
@@ -359,187 +368,207 @@ export async function prepareTurn(params: QueryParams): Promise<PreparedTurn> {
359
368
  ...(params.tokenBudgetStore ? { tokenBudgetStore: params.tokenBudgetStore } : {}),
360
369
  ...(params.workingDirectory ? { workingDirectory: params.workingDirectory } : {}),
361
370
  })
362
- const savedBudget = await savedBudgetReference(params, turnId, storage, selectedResumeState)
363
- const budget = await resolveQueryBudget(params, turnId, storage.tokenBudget, savedBudget)
364
- const log = TurnContextFactory.buildLogger({
365
- agentName: params.agentName,
366
- turnConfig,
371
+ // The preflight refuses an already foreign log before opening a budget or
372
+ // draining queued topic messages. Repeat after claiming the writer lease:
373
+ // another process may have opened a log that was empty at preflight time.
374
+ await assertSessionLogAttribution(storage.log, params)
375
+ const preludeLease = await PreludeSessionLease.acquire(
376
+ storage.log,
377
+ params.sessionId,
367
378
  turnId,
368
- ...(params.parentSessionId ? { parentSessionId: params.parentSessionId } : {}),
369
- sessionId: params.sessionId,
370
- topicId: params.topicId,
371
- projectId: params.projectId,
372
- tenantId: params.tenantId,
373
- })
374
-
375
- // Every model call in the turn — the loop's turns, the forced-final
376
- // summary, advisory and compaction side calls — goes through this one
377
- // wrapped provider, so the retry policy cannot be bypassed by a code
378
- // path that happens to hold the raw driver.
379
- // The logger is passed on purpose: `withProviderRetry` guards every one
380
- // of its warns behind `options.log`, and this is its only production
381
- // call site — so without it the "failed, retrying" and "failed, giving
382
- // up" lines were dead code and a backoff left no trace anywhere.
383
- //
384
- // With a chain declared, the same sentence holds two levels out. The idle
385
- // watchdog is applied to each raw member, retry wraps that, and fallback
386
- // wraps the members: `fallback(retry(idle(m0)), retry(idle(m1)), …)`. The
387
- // idle layer cannot sit outside retry, because its timer would then count a
388
- // legitimate backoff as provider silence. This order is not a
389
- // preference. Assembled the other way round — which is what a host gets if
390
- // it wraps its own chain and hands the result in, because this function
391
- // would then wrap THAT in retry — an exhausted chain gets restarted from
392
- // the head by the outer loop and a throttle on the last member is counted
393
- // by two budgets. Building it here is what makes the order unspellable
394
- // wrong.
395
- const chain: readonly ProviderChainMember[] = [
396
- { provider: params.provider },
397
- ...(params.fallbackProviders ?? []),
398
- ]
399
- assertCostIsAttributable(chain, params.pricing)
400
- assertBudgetIsMeasurable(params)
401
- const withRecovery = (provider: LLMProvider): LLMProvider => {
402
- const withIdleBound = withStreamIdleTimeout(provider, {
403
- idleTimeoutMs: streamIdleTimeoutMs,
404
- log,
405
- })
406
- const metered = withTokenBudget(withIdleBound, budget)
407
- return params.retry === false
408
- ? metered
409
- : withProviderRetry(metered, {
410
- config: params.retry,
411
- log,
412
- canRetry: () => budget.remaining > 0,
413
- })
414
- }
415
- // Who is serving right now, for the turn RECORD rather than for the request.
416
- //
417
- // It starts at the head and moves only when the chain does, which is the
418
- // whole of the truth because the cursor never rewinds. The turn cannot read
419
- // this off `resilientProvider`: that wrapper reports the head's `id` on
420
- // purpose, so asking it produces the declaration back — the defect this
421
- // record exists to fix.
422
- const serving: { current: ServingMember } = {
423
- current: { index: 0, providerId: params.provider.id },
424
- }
425
- const resilientProvider = withProviderFallback(
426
- chain.map((member) => ({
427
- ...member,
428
- provider: withRecovery(member.provider),
429
- })),
430
- {
431
- log,
432
- canFallback: () => budget.remaining > 0,
433
- onSwap: (to) => {
434
- serving.current = to
435
- // `ctx` is declared below and is initialized before anything can
436
- // call the provider: this fires from inside a `chatStream`, and
437
- // the first one is issued by the loop that `ctx` is built for.
438
- ctx.recorder.setServingProvider(to.providerId)
439
- },
440
- },
379
+ params.lease,
441
380
  )
381
+ let releaseOwnedLease = () => preludeLease.release()
382
+ try {
383
+ await preludeLease.assertCurrent()
384
+ await assertSessionLogAttribution(storage.log, params)
385
+ const savedBudget = await savedBudgetReference(params, turnId, storage, selectedResumeState)
386
+ const budget = await resolveQueryBudget(params, turnId, storage.tokenBudget, savedBudget)
387
+ const log = TurnContextFactory.buildLogger({
388
+ agentName: params.agentName,
389
+ turnConfig,
390
+ turnId,
391
+ ...(params.parentSessionId ? { parentSessionId: params.parentSessionId } : {}),
392
+ sessionId: params.sessionId,
393
+ topicId: params.topicId,
394
+ projectId: params.projectId,
395
+ tenantId: params.tenantId,
396
+ })
442
397
 
443
- // Asked ONCE, here, before the loop exists. Both readers are synchronous
444
- // and hot, so this can never move inside the iteration — and a driver
445
- // that rejects, or one that hangs until the turn is cancelled, must not
446
- // take down a run the table could have served perfectly well. That is
447
- // why the failure path is a swallow with a log rather than a throw: the
448
- // window is an optimisation over a working default, not a prerequisite.
449
- const providerContextWindow = await resolveProviderContextWindow(
450
- resilientProvider,
451
- turnConfig.model,
452
- params.signal,
453
- turnConfig.timeoutMs,
454
- log,
455
- )
456
- const modelContextWindows = new Map<string, number | undefined>()
457
- if (turnConfig.model) modelContextWindows.set(turnConfig.model, providerContextWindow)
458
-
459
- // The mode this conversation was left in, when the turn config names none.
460
- // Read once, before the loop exists, for the same reason the context
461
- // window is: the executor's resolver is synchronous and hot.
462
- //
463
- // A store that throws is not a turn failure — the turn falls back to the
464
- // config's answer, which is exactly what it did before this existed.
465
- const topicState = params.topicStateStore
466
- ? await params.topicStateStore
467
- .getState(params.topicId, params.tenantId)
468
- .catch((err: unknown) => {
469
- log.debug('Could not read the topic state; using the turn config', {
470
- 'namzu.topic.id': params.topicId,
471
- 'namzu.error.message': toErrorMessage(err),
472
- })
473
- return null
474
- })
475
- : null
476
-
477
- // Whatever a host left for "the next turn", taken and cleared in one
478
- // compare-and-set write. Prepended to the messages this turn starts from,
479
- // so it is in the FIRST request rather than arriving a turn late.
480
- //
481
- // Cleared as it is read: a queue read and cleared separately re-delivers
482
- // on a crash between the two, and "start with this" arriving twice is a
483
- // different instruction from the one that was left.
484
- const queuedForThisRun: readonly Message[] = params.topicStateStore
485
- ? await drainQueuedMessages(params.topicStateStore, params.topicId, params.tenantId).catch(
486
- (err: unknown) => {
487
- log.debug('Could not drain the topic queue; starting without it', {
488
- 'namzu.topic.id': params.topicId,
489
- 'namzu.error.message': toErrorMessage(err),
398
+ // Every model call in the turn — the loop's turns, the forced-final
399
+ // summary, advisory and compaction side calls — goes through this one
400
+ // wrapped provider, so the retry policy cannot be bypassed by a code
401
+ // path that happens to hold the raw driver.
402
+ // The logger is passed on purpose: `withProviderRetry` guards every one
403
+ // of its warns behind `options.log`, and this is its only production
404
+ // call site — so without it the "failed, retrying" and "failed, giving
405
+ // up" lines were dead code and a backoff left no trace anywhere.
406
+ //
407
+ // With a chain declared, the same sentence holds two levels out. The idle
408
+ // watchdog is applied to each raw member, retry wraps that, and fallback
409
+ // wraps the members: `fallback(retry(idle(m0)), retry(idle(m1)), …)`. The
410
+ // idle layer cannot sit outside retry, because its timer would then count a
411
+ // legitimate backoff as provider silence. This order is not a
412
+ // preference. Assembled the other way round — which is what a host gets if
413
+ // it wraps its own chain and hands the result in, because this function
414
+ // would then wrap THAT in retry — an exhausted chain gets restarted from
415
+ // the head by the outer loop and a throttle on the last member is counted
416
+ // by two budgets. Building it here is what makes the order unspellable
417
+ // wrong.
418
+ const chain: readonly ProviderChainMember[] = [
419
+ { provider: params.provider },
420
+ ...(params.fallbackProviders ?? []),
421
+ ]
422
+ assertCostIsAttributable(chain, params.pricing)
423
+ assertBudgetIsMeasurable(params)
424
+ const withRecovery = (provider: LLMProvider): LLMProvider => {
425
+ const withIdleBound = withStreamIdleTimeout(provider, {
426
+ idleTimeoutMs: streamIdleTimeoutMs,
427
+ log,
428
+ })
429
+ const metered = withTokenBudget(withIdleBound, budget)
430
+ return params.retry === false
431
+ ? metered
432
+ : withProviderRetry(metered, {
433
+ config: params.retry,
434
+ log,
435
+ canRetry: () => budget.remaining > 0,
490
436
  })
491
- return []
437
+ }
438
+ // Who is serving right now, for the turn RECORD rather than for the request.
439
+ //
440
+ // It starts at the head and moves only when the chain does, which is the
441
+ // whole of the truth because the cursor never rewinds. The turn cannot read
442
+ // this off `resilientProvider`: that wrapper reports the head's `id` on
443
+ // purpose, so asking it produces the declaration back — the defect this
444
+ // record exists to fix.
445
+ const serving: { current: ServingMember } = {
446
+ current: { index: 0, providerId: params.provider.id },
447
+ }
448
+ const resilientProvider = withProviderFallback(
449
+ chain.map((member) => ({
450
+ ...member,
451
+ provider: withRecovery(member.provider),
452
+ })),
453
+ {
454
+ log,
455
+ canFallback: () => budget.remaining > 0,
456
+ onSwap: (to) => {
457
+ serving.current = to
458
+ // `ctx` is declared below and is initialized before anything can
459
+ // call the provider: this fires from inside a `chatStream`, and
460
+ // the first one is issued by the loop that `ctx` is built for.
461
+ ctx.recorder.setServingProvider(to.providerId)
492
462
  },
493
- )
494
- : []
495
-
496
- // One effective list, used everywhere the turn is seeded from. Three
497
- // branches below push from it, and computing it at each would be three
498
- // places to forget the queue.
499
- //
500
- // Stored attachments are resolved HERE, once, before the messages reach
501
- // the turn record. Resolving later — at the provider boundary — would put
502
- // refs in the durable transcript and in every checkpoint, and a turn
503
- // resumed against a store that had since forgotten a ref would fail
504
- // replaying its own history rather than at the moment somebody asked for
505
- // the bytes. Every failure refuses: a message that silently lost its
506
- // image is a model answering about a picture it never saw.
507
- const ctx = TurnContextFactory.build({
508
- budget,
509
- ...(topicState ? { topicPermissionMode: topicState.permissionMode } : {}),
510
- ...(params.permissionModeRef ? { permissionModeRef: params.permissionModeRef } : {}),
511
- agentId: params.agentId,
512
- agentName: params.agentName,
513
- turnConfig,
514
- provider: resilientProvider,
515
- workingDirectory: params.workingDirectory,
516
- pricing: params.pricing,
517
- enableActivityTracking: params.enableActivityTracking,
518
- signal: params.signal,
519
- sessionId: params.sessionId,
520
- topicId: params.topicId,
521
- projectId: params.projectId,
522
- tenantId: params.tenantId,
523
- storage,
524
- turnId,
525
- ...(params.parentSessionId ? { parentSessionId: params.parentSessionId } : {}),
526
- ...(params.parentTurnId ? { parentTurnId: params.parentTurnId } : {}),
527
- ...(params.depth !== undefined ? { depth: params.depth } : {}),
528
- log,
529
- })
463
+ },
464
+ )
530
465
 
531
- // The writer lease, and `session_started` on an empty log. Everything
532
- // from here to the end of the turn holds the lease, so a failure before
533
- // the turn body owns it releases it.
534
- await ctx.recorder.open({
535
- ...(params.lease ? { lease: params.lease } : {}),
536
- session: {
537
- cwd: ctx.cwd,
538
- ...(params.origin ? { origin: params.origin } : {}),
539
- ...(params.forkedFrom ? { forkedFrom: params.forkedFrom } : {}),
540
- },
541
- })
542
- try {
466
+ // Asked ONCE, here, before the loop exists. Both readers are synchronous
467
+ // and hot, so this can never move inside the iteration — and a driver
468
+ // that rejects, or one that hangs until the turn is cancelled, must not
469
+ // take down a run the table could have served perfectly well. That is
470
+ // why the failure path is a swallow with a log rather than a throw: the
471
+ // window is an optimisation over a working default, not a prerequisite.
472
+ const providerContextWindow = await resolveProviderContextWindow(
473
+ resilientProvider,
474
+ turnConfig.model,
475
+ params.signal,
476
+ turnConfig.timeoutMs,
477
+ log,
478
+ )
479
+ const modelContextWindows = new Map<string, number | undefined>()
480
+ if (turnConfig.model) modelContextWindows.set(turnConfig.model, providerContextWindow)
481
+
482
+ // The mode this conversation was left in, when the turn config names none.
483
+ // Read once, before the loop exists, for the same reason the context
484
+ // window is: the executor's resolver is synchronous and hot.
485
+ //
486
+ // A store that throws is not a turn failure — the turn falls back to the
487
+ // config's answer, which is exactly what it did before this existed.
488
+ const topicState = params.topicStateStore
489
+ ? await params.topicStateStore
490
+ .getState(params.topicId, params.tenantId)
491
+ .catch((err: unknown) => {
492
+ log.debug('Could not read the topic state; using the turn config', {
493
+ 'namzu.topic.id': params.topicId,
494
+ 'namzu.error.message': toErrorMessage(err),
495
+ })
496
+ return null
497
+ })
498
+ : null
499
+
500
+ // Whatever a host left for "the next turn", taken and cleared in one
501
+ // compare-and-set write. Prepended to the messages this turn starts from,
502
+ // so it is in the FIRST request rather than arriving a turn late.
503
+ //
504
+ // Cleared as it is read: a queue read and cleared separately re-delivers
505
+ // on a crash between the two, and "start with this" arriving twice is a
506
+ // different instruction from the one that was left.
507
+ await preludeLease.assertCurrent()
508
+ const queuedForThisRun: readonly Message[] = params.topicStateStore
509
+ ? await drainQueuedMessages(params.topicStateStore, params.topicId, params.tenantId).catch(
510
+ (err: unknown) => {
511
+ log.debug('Could not drain the topic queue; starting without it', {
512
+ 'namzu.topic.id': params.topicId,
513
+ 'namzu.error.message': toErrorMessage(err),
514
+ })
515
+ return []
516
+ },
517
+ )
518
+ : []
519
+
520
+ // One effective list, used everywhere the turn is seeded from. Three
521
+ // branches below push from it, and computing it at each would be three
522
+ // places to forget the queue.
523
+ //
524
+ // Stored attachments are resolved HERE, once, before the messages reach
525
+ // the turn record. Resolving later — at the provider boundary — would put
526
+ // refs in the durable transcript and in every checkpoint, and a turn
527
+ // resumed against a store that had since forgotten a ref would fail
528
+ // replaying its own history rather than at the moment somebody asked for
529
+ // the bytes. Every failure refuses: a message that silently lost its
530
+ // image is a model answering about a picture it never saw.
531
+ const ctx = TurnContextFactory.build({
532
+ budget,
533
+ ...(topicState ? { topicPermissionMode: topicState.permissionMode } : {}),
534
+ ...(params.permissionModeRef ? { permissionModeRef: params.permissionModeRef } : {}),
535
+ agentId: params.agentId,
536
+ agentName: params.agentName,
537
+ turnConfig,
538
+ provider: resilientProvider,
539
+ workingDirectory: params.workingDirectory,
540
+ pricing: params.pricing,
541
+ enableActivityTracking: params.enableActivityTracking,
542
+ signal: params.signal,
543
+ sessionId: params.sessionId,
544
+ topicId: params.topicId,
545
+ projectId: params.projectId,
546
+ tenantId: params.tenantId,
547
+ storage,
548
+ turnId,
549
+ ...(params.parentSessionId ? { parentSessionId: params.parentSessionId } : {}),
550
+ ...(params.parentTurnId ? { parentTurnId: params.parentTurnId } : {}),
551
+ ...(params.depth !== undefined ? { depth: params.depth } : {}),
552
+ log,
553
+ })
554
+
555
+ // The writer lease, and `session_started` on an empty log. Everything
556
+ // from here to the end of the turn holds the lease, so a failure before
557
+ // the turn body owns it releases it.
558
+ await ctx.recorder.open({
559
+ lease: await preludeLease.transfer(),
560
+ ownLease: preludeLease.ownsLease,
561
+ session: {
562
+ cwd: ctx.cwd,
563
+ ...(params.origin ? { origin: params.origin } : {}),
564
+ ...(params.forkedFrom ? { forkedFrom: params.forkedFrom } : {}),
565
+ },
566
+ })
567
+ releaseOwnedLease = async () => {
568
+ await preludeLease.stop()
569
+ await ctx.recorder.release()
570
+ }
571
+ await preludeLease.stop()
543
572
  await assertTurnMayStart(params, turnId, storage, ctx)
544
573
  // The session log is the conversation's source of truth. A new turn starts
545
574
  // from its folded history, and `params.messages` is what this turn adds.
@@ -548,7 +577,14 @@ export async function prepareTurn(params: QueryParams): Promise<PreparedTurn> {
548
577
  const history: RecordedMessage[] = params.resumeFromCheckpoint
549
578
  ? []
550
579
  : await readFoldedHistory(storage.log)
551
- const input = withoutRecordedPrefix(params.messages, history)
580
+ const input = params.resumeFromCheckpoint
581
+ ? []
582
+ : await reconcileCallerMessages(
583
+ params.messages,
584
+ history,
585
+ storage.log,
586
+ params.continuationMode === true,
587
+ )
552
588
  const seeded: Message[] = queuedForThisRun.length > 0 ? [...queuedForThisRun, ...input] : input
553
589
  let resolvedInitialMessages: Message[]
554
590
  let attachmentResolutionCancelled = false
@@ -577,9 +613,17 @@ export async function prepareTurn(params: QueryParams): Promise<PreparedTurn> {
577
613
  const preparationSignal = params.signal ?? new AbortController().signal
578
614
  let snapshot: UserMessage | null | undefined
579
615
  try {
616
+ // `ProjectInstructionCallbackContext.messages` promises "the
617
+ // messages accepted before this callback starts" — the durable
618
+ // history this turn folds from the log, not only what THIS turn
619
+ // itself is contributing. Without the fold's own project-instruction
620
+ // snapshot (from an earlier turn of the SAME session) in view, a
621
+ // host that discovers a nested scope from a tool call could never
622
+ // re-derive which files to re-read on the next turn, once the
623
+ // message that named them was reconciled away as already durable.
580
624
  const prepared = await awaitProjectInstructionCallback(preparationSignal, () =>
581
625
  params.projectInstructionContext?.prepareInitialSnapshot?.({
582
- messages: [...resolvedInitialMessages],
626
+ messages: [...history.map((entry) => entry.message), ...resolvedInitialMessages],
583
627
  signal: preparationSignal,
584
628
  }),
585
629
  )
@@ -778,7 +822,10 @@ export async function prepareTurn(params: QueryParams): Promise<PreparedTurn> {
778
822
  taskScheduler,
779
823
  }
780
824
  } catch (error) {
781
- await ctx.recorder.release()
825
+ // Once open succeeds, the recorder normally releases this lease at the
826
+ // end of the turn. Preparation failures, including an open refusal,
827
+ // still belong to this prelude. A caller-supplied lease stays theirs.
828
+ if (preludeLease.ownsLease) await releaseOwnedLease().catch(() => undefined)
782
829
  throw error
783
830
  }
784
831
  }
@@ -794,7 +841,10 @@ async function savedBudgetReference(
794
841
  selected: SelectedResumeState | undefined,
795
842
  ): Promise<SavedBudgetReference | undefined> {
796
843
  if (selected?.budgetBinding) {
797
- return { binding: selected.budgetBinding, accountId: selected.budgetBinding.accountId }
844
+ return {
845
+ binding: selected.budgetBinding,
846
+ accountId: selected.budgetBinding.accountId,
847
+ }
798
848
  }
799
849
  // A selected state carries only a durable binding. An account held in
800
850
  // memory is named by the checkpoint document alone, and a resume must
@@ -844,29 +894,258 @@ function projectRecordedHistory(
844
894
  }
845
895
 
846
896
  /**
847
- * `messages` without the leading run of messages the session log already
848
- * holds, compared by value. A host that passes only the new input is
849
- * unaffected; one that passes the whole conversation adds only its tail.
897
+ * Deep-equal ignoring `id` and `timestamp`: two copies of one message may
898
+ * disagree only on which record named it, and `timestamp` is bookkeeping
899
+ * about when it was authored, not part of what it says — `createUserMessage`
900
+ * and its siblings always stamp `Date.now()`, but the field is optional on
901
+ * `BaseMessage`, and a host that reconstructs history itself (the
902
+ * documented stateless `exec --json` stdin contract never requires it) has
903
+ * no way to recover the original value and must not be read as having
904
+ * edited a message merely for omitting one. Each side is round-tripped
905
+ * through JSON first — "canonical" — so an `undefined`-valued own property
906
+ * (a field a driver or the recorder set explicitly, as opposed to one never
907
+ * mentioned) does not read as a difference: `isDeepStrictEqual` alone treats
908
+ * `{ x: undefined }` and `{}` as unequal, and the durable record went
909
+ * through the same round trip when it was written.
910
+ */
911
+ function sameMessageContent(a: Message, b: Message): boolean {
912
+ const { id: _a, timestamp: _ta, ...restA } = a
913
+ const { id: _b, timestamp: _tb, ...restB } = b
914
+ return isDeepStrictEqual(
915
+ JSON.parse(JSON.stringify(restA)) as unknown,
916
+ JSON.parse(JSON.stringify(restB)) as unknown,
917
+ )
918
+ }
919
+
920
+ /** A `stale_cached_history` refusal: which way "the log disagrees" this is. */
921
+ function staleCachedHistoryError(
922
+ kind: 'edited' | 'foreign' | 'unaligned',
923
+ message: Message,
924
+ ): NamzuError {
925
+ const id = message.id
926
+ const guidance =
927
+ 'pass only new messages (with no id), or re-read history from the session instead of reusing a cached copy.'
928
+ const text =
929
+ kind === 'edited'
930
+ ? `A cached message carries id ${id}, but its content no longer matches what this session's log recorded under that id. A message read from history must not be edited before it is sent back: ${guidance}`
931
+ : kind === 'foreign'
932
+ ? `A cached message carries id ${id}, which this session's log never recorded. A host must not mint its own id for a message: pass only messages this session's log gave an id (unedited), or new messages with no id.`
933
+ : `A cached message with no id starts the same as this session's log, but the two diverge further in — this looks like an attempted full resend of the conversation, of a fold this log does not actually hold (edited, reordered, or from elsewhere). Nothing here can tell which of the cache's later messages, if any, are genuinely new: ${guidance}`
934
+ return new NamzuError({
935
+ code: 'stale_cached_history',
936
+ message: text,
937
+ details: {
938
+ kind,
939
+ role: message.role,
940
+ ...(id === undefined ? {} : { messageId: id }),
941
+ },
942
+ })
943
+ }
944
+
945
+ /**
946
+ * A kind `query()` reconstructs itself every turn rather than trusting a
947
+ * caller's cached copy of it: the per-turn static/dynamic system prompt
948
+ * (`pushSystemMessages`, pushed `transient: true` and so never durably
949
+ * recorded at all — see `manager/session/turn-recorder.ts`), and a
950
+ * project-instruction snapshot (durably recorded, but `Turn.messages` keeps
951
+ * only the LATEST one per `collapseProjectInstructionSnapshots`, while the
952
+ * log keeps every turn's own). A compaction summary and a working-memory
953
+ * note are deliberately NOT here: those two are conversation STATE the
954
+ * kernel cannot re-derive, not prompt scaffolding it rebuilds.
955
+ *
956
+ * Comparing either kind positionally is meaningless — the caller's copy and
957
+ * the log's own history disagree on how many of them exist by construction,
958
+ * never because anything is stale — so both are dropped before the no-id
959
+ * alignment below ever sees them, on both the caller's side and the fold's.
960
+ */
961
+ function isKernelDerivedMessage(message: Message): boolean {
962
+ if (isProjectInstructionMessage(message)) return true
963
+ if (message.role !== 'system') return false
964
+ const content = typeof message.content === 'string' ? message.content : null
965
+ return !isCompactionMessage(content) && !isWorkingMemoryMessage(content)
966
+ }
967
+
968
+ /**
969
+ * How a caller's no-id messages (`caller`, in order) relate to what remains
970
+ * of the log's own fold (`pool`, in order), once ids already claimed and the
971
+ * kernel-rebuilt kinds are set aside from both — never by searching for SOME
972
+ * aligned position, which cannot tell "the caller is echoing an old value"
973
+ * from "the caller wrote something new that happens to match" without a
974
+ * false positive or a false negative somewhere (an interrupted turn's own
975
+ * trailing no-id prompt, resent verbatim as the host's only next message,
976
+ * looks identical to a coincidental repeat of it as genuinely new content;
977
+ * a `k`-suffix search that tried to tell them apart swallowed the latter).
978
+ *
979
+ * There is exactly one shape this recognizes as "my cache, trimmed to a
980
+ * prefix of the fold": `caller`'s OWN first `pool.length` messages equal
981
+ * `pool` exactly, in order — the caller resent everything the fold
982
+ * currently holds. Then, and only then, that matched prefix is durable and
983
+ * dropped; what follows (if anything) is new. `caller` must be LONGER than
984
+ * `pool` for this UNLESS the call also has an id-carrying message
985
+ * elsewhere (`hasId`): only then can a length exactly matching the pool —
986
+ * "everything, nothing new yet" — be trusted, because something else in
987
+ * the same call already anchors it as part of a larger, structured resend.
988
+ * A caller with no id anywhere gets the strict inequality: its no-id
989
+ * segment IS its whole request, so an exact length match cannot be told
990
+ * apart from one message that happens to repeat the fold's own last value.
991
+ *
992
+ * Anything else is never matched by value, on purpose — a caller with no
993
+ * more messages than the fold has left, or one whose cache diverges from
994
+ * the fold's very first message, is `'new'`: every message it sent is kept,
995
+ * none dropped. This gives up detecting "a trimmed cache" without an id
996
+ * (session-log.md documents why: a host must send either everything or only
997
+ * new messages to reconcile by value at all) in exchange for never again
998
+ * confusing an echo with new content in either direction.
999
+ *
1000
+ * The one case still refused rather than guessed at: `caller` is longer
1001
+ * than `pool` and its first message matches `pool`'s first, but the two
1002
+ * diverge somewhere after that — a cache that looks like an attempted full
1003
+ * resend of a KNOWN fold, just not the fold this session's log actually
1004
+ * holds. `'unaligned'` names that, rather than the alternative — duplicating
1005
+ * or dropping content nobody can prove is redundant.
850
1006
  */
851
- function withoutRecordedPrefix(
1007
+ type NoIdReconciliation =
1008
+ /** `caller`'s first `pool.length` messages ARE `pool`: drop that prefix. */
1009
+ | 'trimmed'
1010
+ /** Fails the turn: an attempted full resend of a fold this log does not hold. */
1011
+ | 'unaligned'
1012
+ /** No value matching at all: every one of `caller`'s messages is kept. */
1013
+ | 'new'
1014
+
1015
+ function reconcileNoIdAgainstFold(
1016
+ caller: readonly Message[],
1017
+ pool: readonly Message[],
1018
+ // A wholly no-id caller (this call's `messages` carries no id anywhere)
1019
+ // gets the strict `>`: its no-id segment IS its entire request, so a
1020
+ // length exactly matching the pool is indistinguishable from "one
1021
+ // message that happens to repeat the fold's own last value" (an
1022
+ // interrupted turn's own trailing prompt, resent as a caller's ONLY
1023
+ // next message — round-3's own probe1/probe3) — favoring "new" there
1024
+ // is the whole point of this rule. A caller that ALSO sent at least one
1025
+ // id-carrying message this same call is not that: its no-id segment is
1026
+ // part of a larger, structured resend the id path already anchors, so
1027
+ // an EXACT length match is trusted as "everything, nothing new" (`>=`)
1028
+ // — the shape a wholesale history replacement (a compaction, or the
1029
+ // provider-rejected-image repair, which records this way for the same
1030
+ // reason: `TurnRecorder.replaceMessages`) produces on its very next
1031
+ // turn, before any new message has been added at all.
1032
+ hasId: boolean,
1033
+ ): NoIdReconciliation {
1034
+ if (hasId ? caller.length >= pool.length : caller.length > pool.length) {
1035
+ let fullPrefix = true
1036
+ for (let i = 0; i < pool.length; i++) {
1037
+ if (!sameMessageContent(caller[i] as Message, pool[i] as Message)) {
1038
+ fullPrefix = false
1039
+ break
1040
+ }
1041
+ }
1042
+ if (fullPrefix) return 'trimmed'
1043
+ if (pool.length > 0 && sameMessageContent(caller[0] as Message, pool[0] as Message)) {
1044
+ return 'unaligned'
1045
+ }
1046
+ }
1047
+ return 'new'
1048
+ }
1049
+
1050
+ /**
1051
+ * `messages` reconciled against this session's log, by id where a message
1052
+ * carries one, and otherwise by the anchored, whole-cache rule
1053
+ * {@link reconcileNoIdAgainstFold} implements — never by walking the two
1054
+ * positionally message by message, and never by searching for some aligned
1055
+ * position, either of which reads a genuine echo of old content and a
1056
+ * coincidentally-identical new message as the same shape.
1057
+ *
1058
+ * A message carrying an id already durable under it (matching content) is
1059
+ * dropped — the fold supplies it, from wherever compaction has since put
1060
+ * it, even from before a compaction summarized it away, since the log
1061
+ * remembers every id it ever gave out. One whose id the log never recorded,
1062
+ * or whose content no longer matches what the log recorded under it, is
1063
+ * refused outright (`stale_cached_history`, `'foreign'` / `'edited'`).
1064
+ *
1065
+ * A message with no id, once the kernel-derived kinds above are set aside
1066
+ * from both sides, joins its OWN sequence of no-id messages (in their
1067
+ * original relative order), reconciled against the fold's own remaining
1068
+ * pool: every fold entry EXCEPT one whose id an id-carrying caller message
1069
+ * already claimed above (so nothing is offered to both mechanisms) and a
1070
+ * no-id one (a compaction summary, or a record predating per-message ids).
1071
+ * A caller using no ids at all thus reconciles exactly as
1072
+ * {@link reconcileNoIdAgainstFold} describes, against the whole fold,
1073
+ * nothing claimed. A caller that CAN only ever id some roles — a protocol
1074
+ * adapter (AG-UI) that mints an id for an assistant/tool message it
1075
+ * produced but never for one its own client authored — still reconciles
1076
+ * its no-id messages correctly, against whatever the id path left
1077
+ * unclaimed, rather than an empty pool that would read every one of them
1078
+ * as new (which is harmless here — "new" is always a safe answer — but
1079
+ * would duplicate needlessly).
1080
+ *
1081
+ * See {@link reconcileNoIdAgainstFold} for exactly which shape is recognized
1082
+ * as "my cache, trimmed to a prefix of the fold" (dropped), which is
1083
+ * refused as `stale_cached_history` (`'unaligned'`) as an attempted resend
1084
+ * of a fold this log does not hold, and — deliberately, the rest — which is
1085
+ * never matched by value at all and so always kept as new.
1086
+ */
1087
+ async function reconcileCallerMessages(
852
1088
  messages: readonly Message[],
853
1089
  history: readonly RecordedMessage[],
854
- ): Message[] {
855
- const recorded = history.filter((entry) => entry.message.role !== 'system')
856
- let matched = 0
857
- let r = 0
858
- for (const message of messages) {
859
- if (message.role === 'system') {
860
- matched++
861
- continue
1090
+ log: SessionLog,
1091
+ continuationMode: boolean,
1092
+ ): Promise<Message[]> {
1093
+ const hasId = messages.some((message) => message.id !== undefined)
1094
+ const recordedById = hasId ? await readEverRecordedMessages(log) : undefined
1095
+ // Ids a caller message already claimed by direct lookup above: a fold
1096
+ // entry that gave one of THESE out must not also be offered to the no-id
1097
+ // alignment below, or a message that already reconciled by id could be
1098
+ // matched a second time by value. A caller need not be all-or-nothing
1099
+ // about ids for this to matter — a protocol adapter (AG-UI) that can
1100
+ // only ever attach an id to an assistant/tool message it itself minted,
1101
+ // never to a message its OWN client authored, sends exactly this mix.
1102
+ const claimedIds = new Set<MessageId>()
1103
+
1104
+ const noIdIndices: number[] = []
1105
+ const noIdMessages: Message[] = []
1106
+ for (let index = 0; index < messages.length; index++) {
1107
+ const message = messages[index] as Message
1108
+ const id = message.id
1109
+ if (id !== undefined) {
1110
+ const recorded = recordedById?.get(id)
1111
+ if (recorded === undefined) throw staleCachedHistoryError('foreign', message)
1112
+ if (!sameMessageContent(recorded, message)) throw staleCachedHistoryError('edited', message)
1113
+ claimedIds.add(id)
1114
+ continue // already durable: the fold supplies it
862
1115
  }
863
- const next = recorded[r]
864
- if (!next || JSON.stringify(next.message) !== JSON.stringify(message)) break
865
- r++
866
- matched++
1116
+ // Outside `continuationMode`, the kernel rebuilds the system floor and
1117
+ // collapses every project-instruction snapshot but the latest
1118
+ // (`pushSystemMessages`, `collapseProjectInstructionSnapshots`
1119
+ // downstream of this function) regardless of what a caller sent, so a
1120
+ // no-id message of either kind is dropped here rather than offered to
1121
+ // the alignment below, where the fold's OWN asymmetric copies of them
1122
+ // (one durable record per turn that had one, never collapsed) would
1123
+ // corrupt it. `continuationMode` turns that rebuilding OFF — the
1124
+ // caller's array IS the request, verbatim — so there is no "the
1125
+ // kernel discards this anyway" to lean on; a message of either kind
1126
+ // is ordinary content there; unforced-through, it would just report
1127
+ // a passthrough-only conversation as no-id forever - a genuinely new
1128
+ // no-id system message (a `continuationMode` caller's own) has to
1129
+ // reconcile like anything else, not vanish.
1130
+ if (!continuationMode && isKernelDerivedMessage(message)) continue
1131
+ noIdIndices.push(index)
1132
+ noIdMessages.push(message)
1133
+ }
1134
+
1135
+ const pool = history
1136
+ .filter((entry) => entry.messageId === undefined || !claimedIds.has(entry.messageId))
1137
+ .map((entry) => entry.message)
1138
+ .filter((message) => continuationMode || !isKernelDerivedMessage(message))
1139
+
1140
+ const reconciliation = reconcileNoIdAgainstFold(noIdMessages, pool, hasId)
1141
+ if (reconciliation === 'unaligned') {
1142
+ throw staleCachedHistoryError('unaligned', noIdMessages[0] as Message)
867
1143
  }
868
- if (r === 0) return [...messages]
869
- return messages.slice(matched)
1144
+ const keptNoIdIndices =
1145
+ reconciliation === 'trimmed' ? noIdIndices.slice(pool.length) : noIdIndices
1146
+
1147
+ const newIndices = new Set(keptNoIdIndices)
1148
+ return messages.filter((_message, index) => newIndices.has(index))
870
1149
  }
871
1150
 
872
1151
  /**