@namzu/sdk 30.2.0 → 31.1.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 (718) hide show
  1. package/CHANGELOG.md +562 -0
  2. package/README.md +43 -2
  3. package/dist/advisory/executor.d.ts +2 -1
  4. package/dist/advisory/executor.d.ts.map +1 -1
  5. package/dist/advisory/executor.js +4 -1
  6. package/dist/advisory/executor.js.map +1 -1
  7. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  8. package/dist/agents/ReactiveAgent.js +12 -0
  9. package/dist/agents/ReactiveAgent.js.map +1 -1
  10. package/dist/agents/RouterAgent.d.ts.map +1 -1
  11. package/dist/agents/RouterAgent.js +21 -3
  12. package/dist/agents/RouterAgent.js.map +1 -1
  13. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  14. package/dist/agents/SupervisorAgent.js +34 -11
  15. package/dist/agents/SupervisorAgent.js.map +1 -1
  16. package/dist/agents/runAgent.d.ts +12 -0
  17. package/dist/agents/runAgent.d.ts.map +1 -1
  18. package/dist/agents/runAgent.js +26 -2
  19. package/dist/agents/runAgent.js.map +1 -1
  20. package/dist/authorization/command-line.d.ts +81 -0
  21. package/dist/authorization/command-line.d.ts.map +1 -0
  22. package/dist/authorization/command-line.js +347 -0
  23. package/dist/authorization/command-line.js.map +1 -0
  24. package/dist/authorization/rules.d.ts.map +1 -1
  25. package/dist/authorization/rules.js +22 -1
  26. package/dist/authorization/rules.js.map +1 -1
  27. package/dist/bridge/a2a/client.d.ts +23 -5
  28. package/dist/bridge/a2a/client.d.ts.map +1 -1
  29. package/dist/bridge/a2a/client.js +320 -73
  30. package/dist/bridge/a2a/client.js.map +1 -1
  31. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  32. package/dist/bridge/a2a/mapper.js +4 -0
  33. package/dist/bridge/a2a/mapper.js.map +1 -1
  34. package/dist/bridge/acp/server.d.ts +13 -1
  35. package/dist/bridge/acp/server.d.ts.map +1 -1
  36. package/dist/bridge/acp/server.js +150 -44
  37. package/dist/bridge/acp/server.js.map +1 -1
  38. package/dist/bridge/mcp/connector/adapter.d.ts +3 -2
  39. package/dist/bridge/mcp/connector/adapter.d.ts.map +1 -1
  40. package/dist/bridge/mcp/connector/adapter.js +17 -21
  41. package/dist/bridge/mcp/connector/adapter.js.map +1 -1
  42. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  43. package/dist/bridge/sse/mapper.js +3 -0
  44. package/dist/bridge/sse/mapper.js.map +1 -1
  45. package/dist/compaction/dangling.d.ts +29 -2
  46. package/dist/compaction/dangling.d.ts.map +1 -1
  47. package/dist/compaction/dangling.js +172 -35
  48. package/dist/compaction/dangling.js.map +1 -1
  49. package/dist/compaction/index.d.ts +3 -2
  50. package/dist/compaction/index.d.ts.map +1 -1
  51. package/dist/compaction/index.js +1 -1
  52. package/dist/compaction/index.js.map +1 -1
  53. package/dist/compaction/manual.d.ts +11 -1
  54. package/dist/compaction/manual.d.ts.map +1 -1
  55. package/dist/compaction/manual.js +89 -14
  56. package/dist/compaction/manual.js.map +1 -1
  57. package/dist/compaction/plan.d.ts +19 -6
  58. package/dist/compaction/plan.d.ts.map +1 -1
  59. package/dist/compaction/plan.js +18 -4
  60. package/dist/compaction/plan.js.map +1 -1
  61. package/dist/compaction/retention.d.ts +10 -7
  62. package/dist/compaction/retention.d.ts.map +1 -1
  63. package/dist/compaction/retention.js +26 -8
  64. package/dist/compaction/retention.js.map +1 -1
  65. package/dist/compaction/summary.d.ts +4 -4
  66. package/dist/compaction/summary.js +4 -4
  67. package/dist/compaction/verifier.d.ts +19 -1
  68. package/dist/compaction/verifier.d.ts.map +1 -1
  69. package/dist/compaction/verifier.js +20 -1
  70. package/dist/compaction/verifier.js.map +1 -1
  71. package/dist/config/runtime.d.ts +6 -6
  72. package/dist/connector/BaseConnector.d.ts +6 -4
  73. package/dist/connector/BaseConnector.d.ts.map +1 -1
  74. package/dist/connector/BaseConnector.js +8 -2
  75. package/dist/connector/BaseConnector.js.map +1 -1
  76. package/dist/connector/builtins/http.d.ts +16 -4
  77. package/dist/connector/builtins/http.d.ts.map +1 -1
  78. package/dist/connector/builtins/http.js +177 -44
  79. package/dist/connector/builtins/http.js.map +1 -1
  80. package/dist/connector/builtins/webhook.d.ts +15 -4
  81. package/dist/connector/builtins/webhook.d.ts.map +1 -1
  82. package/dist/connector/builtins/webhook.js +165 -45
  83. package/dist/connector/builtins/webhook.js.map +1 -1
  84. package/dist/connector/execution-contract.d.ts +11 -0
  85. package/dist/connector/execution-contract.d.ts.map +1 -0
  86. package/dist/connector/execution-contract.js +14 -0
  87. package/dist/connector/execution-contract.js.map +1 -0
  88. package/dist/connector/http-operation.d.ts +48 -0
  89. package/dist/connector/http-operation.d.ts.map +1 -0
  90. package/dist/connector/http-operation.js +205 -0
  91. package/dist/connector/http-operation.js.map +1 -0
  92. package/dist/connector/mcp/adapter.d.ts.map +1 -1
  93. package/dist/connector/mcp/adapter.js +8 -3
  94. package/dist/connector/mcp/adapter.js.map +1 -1
  95. package/dist/connector/mcp/client.d.ts +14 -8
  96. package/dist/connector/mcp/client.d.ts.map +1 -1
  97. package/dist/connector/mcp/client.js +160 -44
  98. package/dist/connector/mcp/client.js.map +1 -1
  99. package/dist/connector/mcp/http-sse.d.ts +8 -2
  100. package/dist/connector/mcp/http-sse.d.ts.map +1 -1
  101. package/dist/connector/mcp/http-sse.js +70 -17
  102. package/dist/connector/mcp/http-sse.js.map +1 -1
  103. package/dist/connector/mcp/prompt-adapter.d.ts.map +1 -1
  104. package/dist/connector/mcp/prompt-adapter.js +9 -2
  105. package/dist/connector/mcp/prompt-adapter.js.map +1 -1
  106. package/dist/connector/mcp/stdio.d.ts +2 -2
  107. package/dist/connector/mcp/stdio.d.ts.map +1 -1
  108. package/dist/connector/mcp/stdio.js +14 -50
  109. package/dist/connector/mcp/stdio.js.map +1 -1
  110. package/dist/connector/mcp/streamable-http.d.ts +7 -2
  111. package/dist/connector/mcp/streamable-http.d.ts.map +1 -1
  112. package/dist/connector/mcp/streamable-http.js +66 -18
  113. package/dist/connector/mcp/streamable-http.js.map +1 -1
  114. package/dist/connector/tools/adapter.d.ts +2 -2
  115. package/dist/connector/tools/adapter.d.ts.map +1 -1
  116. package/dist/connector/tools/adapter.js +23 -14
  117. package/dist/connector/tools/adapter.js.map +1 -1
  118. package/dist/connector/tools/definitions.d.ts.map +1 -1
  119. package/dist/connector/tools/definitions.js +5 -2
  120. package/dist/connector/tools/definitions.js.map +1 -1
  121. package/dist/connector/tools/result.d.ts +4 -0
  122. package/dist/connector/tools/result.d.ts.map +1 -0
  123. package/dist/connector/tools/result.js +20 -0
  124. package/dist/connector/tools/result.js.map +1 -0
  125. package/dist/connector/web/guarded-fetch.d.ts +4 -2
  126. package/dist/connector/web/guarded-fetch.d.ts.map +1 -1
  127. package/dist/connector/web/guarded-fetch.js +157 -43
  128. package/dist/connector/web/guarded-fetch.js.map +1 -1
  129. package/dist/constants/sandbox/index.d.ts +3 -2
  130. package/dist/constants/sandbox/index.d.ts.map +1 -1
  131. package/dist/constants/sandbox/index.js +3 -2
  132. package/dist/constants/sandbox/index.js.map +1 -1
  133. package/dist/contracts/api.d.ts +2 -0
  134. package/dist/contracts/api.d.ts.map +1 -1
  135. package/dist/contracts/schemas.d.ts +38 -12
  136. package/dist/contracts/schemas.d.ts.map +1 -1
  137. package/dist/contracts/schemas.js +7 -0
  138. package/dist/contracts/schemas.js.map +1 -1
  139. package/dist/directory/derive-supervisor.d.ts.map +1 -1
  140. package/dist/directory/derive-supervisor.js +8 -0
  141. package/dist/directory/derive-supervisor.js.map +1 -1
  142. package/dist/directory/derive.d.ts.map +1 -1
  143. package/dist/directory/derive.js +8 -0
  144. package/dist/directory/derive.js.map +1 -1
  145. package/dist/directory/load.d.ts.map +1 -1
  146. package/dist/directory/load.js +2 -0
  147. package/dist/directory/load.js.map +1 -1
  148. package/dist/directory/types.d.ts +4 -0
  149. package/dist/directory/types.d.ts.map +1 -1
  150. package/dist/eval/experiment.d.ts +10 -10
  151. package/dist/eval/experiment.d.ts.map +1 -1
  152. package/dist/eval/experiment.js +121 -91
  153. package/dist/eval/experiment.js.map +1 -1
  154. package/dist/eval/judge.d.ts +6 -0
  155. package/dist/eval/judge.d.ts.map +1 -1
  156. package/dist/eval/judge.js +7 -2
  157. package/dist/eval/judge.js.map +1 -1
  158. package/dist/eval/types.d.ts +7 -1
  159. package/dist/eval/types.d.ts.map +1 -1
  160. package/dist/manager/agent/lifecycle.d.ts +12 -10
  161. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  162. package/dist/manager/agent/lifecycle.js +16 -3
  163. package/dist/manager/agent/lifecycle.js.map +1 -1
  164. package/dist/manager/connector/environment.d.ts +2 -2
  165. package/dist/manager/connector/environment.d.ts.map +1 -1
  166. package/dist/manager/connector/environment.js +2 -2
  167. package/dist/manager/connector/environment.js.map +1 -1
  168. package/dist/manager/connector/lifecycle.d.ts +10 -2
  169. package/dist/manager/connector/lifecycle.d.ts.map +1 -1
  170. package/dist/manager/connector/lifecycle.js +273 -24
  171. package/dist/manager/connector/lifecycle.js.map +1 -1
  172. package/dist/manager/connector/tenant.d.ts +5 -4
  173. package/dist/manager/connector/tenant.d.ts.map +1 -1
  174. package/dist/manager/connector/tenant.js +47 -22
  175. package/dist/manager/connector/tenant.js.map +1 -1
  176. package/dist/manager/goal/activation.d.ts +23 -0
  177. package/dist/manager/goal/activation.d.ts.map +1 -0
  178. package/dist/manager/goal/activation.js +41 -0
  179. package/dist/manager/goal/activation.js.map +1 -0
  180. package/dist/manager/index.d.ts +3 -2
  181. package/dist/manager/index.d.ts.map +1 -1
  182. package/dist/manager/index.js.map +1 -1
  183. package/dist/manager/run/persistence.d.ts +2 -0
  184. package/dist/manager/run/persistence.d.ts.map +1 -1
  185. package/dist/manager/run/persistence.js +5 -1
  186. package/dist/manager/run/persistence.js.map +1 -1
  187. package/dist/manager/topic/dependency.d.ts +24 -0
  188. package/dist/manager/topic/dependency.d.ts.map +1 -0
  189. package/dist/manager/topic/dependency.js +13 -0
  190. package/dist/manager/topic/dependency.js.map +1 -0
  191. package/dist/manager/topic/lifecycle.d.ts +9 -21
  192. package/dist/manager/topic/lifecycle.d.ts.map +1 -1
  193. package/dist/manager/topic/lifecycle.js +17 -29
  194. package/dist/manager/topic/lifecycle.js.map +1 -1
  195. package/dist/plugin/index.d.ts +1 -0
  196. package/dist/plugin/index.d.ts.map +1 -1
  197. package/dist/plugin/index.js.map +1 -1
  198. package/dist/plugin/lifecycle.d.ts +15 -0
  199. package/dist/plugin/lifecycle.d.ts.map +1 -1
  200. package/dist/plugin/lifecycle.js +144 -38
  201. package/dist/plugin/lifecycle.js.map +1 -1
  202. package/dist/plugin/loader.d.ts +3 -3
  203. package/dist/plugin/loader.d.ts.map +1 -1
  204. package/dist/plugin/loader.js +58 -12
  205. package/dist/plugin/loader.js.map +1 -1
  206. package/dist/provider/collect-chat-completion.d.ts.map +1 -1
  207. package/dist/provider/collect-chat-completion.js +4 -0
  208. package/dist/provider/collect-chat-completion.js.map +1 -1
  209. package/dist/provider/fallback.d.ts +3 -1
  210. package/dist/provider/fallback.d.ts.map +1 -1
  211. package/dist/provider/fallback.js +62 -10
  212. package/dist/provider/fallback.js.map +1 -1
  213. package/dist/provider/idle-timeout.d.ts +4 -0
  214. package/dist/provider/idle-timeout.d.ts.map +1 -1
  215. package/dist/provider/idle-timeout.js +131 -15
  216. package/dist/provider/idle-timeout.js.map +1 -1
  217. package/dist/provider/index.d.ts +2 -0
  218. package/dist/provider/index.d.ts.map +1 -1
  219. package/dist/provider/index.js +1 -0
  220. package/dist/provider/index.js.map +1 -1
  221. package/dist/provider/instrumentation.d.ts.map +1 -1
  222. package/dist/provider/instrumentation.js +1 -0
  223. package/dist/provider/instrumentation.js.map +1 -1
  224. package/dist/provider/retry.d.ts.map +1 -1
  225. package/dist/provider/retry.js +13 -1
  226. package/dist/provider/retry.js.map +1 -1
  227. package/dist/public-runtime.d.ts +57 -24
  228. package/dist/public-runtime.d.ts.map +1 -1
  229. package/dist/public-runtime.js +42 -35
  230. package/dist/public-runtime.js.map +1 -1
  231. package/dist/public-tools.d.ts +1 -0
  232. package/dist/public-tools.d.ts.map +1 -1
  233. package/dist/public-tools.js +5 -0
  234. package/dist/public-tools.js.map +1 -1
  235. package/dist/public-types.d.ts +33 -12
  236. package/dist/public-types.d.ts.map +1 -1
  237. package/dist/rag/embedding.d.ts +8 -3
  238. package/dist/rag/embedding.d.ts.map +1 -1
  239. package/dist/rag/embedding.js +120 -9
  240. package/dist/rag/embedding.js.map +1 -1
  241. package/dist/rag/index.d.ts +1 -1
  242. package/dist/rag/index.d.ts.map +1 -1
  243. package/dist/rag/index.js +1 -1
  244. package/dist/rag/index.js.map +1 -1
  245. package/dist/rag/ingestion.d.ts +2 -2
  246. package/dist/rag/ingestion.d.ts.map +1 -1
  247. package/dist/rag/ingestion.js +15 -3
  248. package/dist/rag/ingestion.js.map +1 -1
  249. package/dist/rag/knowledge-base.d.ts +3 -3
  250. package/dist/rag/knowledge-base.d.ts.map +1 -1
  251. package/dist/rag/knowledge-base.js +8 -4
  252. package/dist/rag/knowledge-base.js.map +1 -1
  253. package/dist/rag/operation.d.ts +10 -0
  254. package/dist/rag/operation.d.ts.map +1 -0
  255. package/dist/rag/operation.js +26 -0
  256. package/dist/rag/operation.js.map +1 -0
  257. package/dist/rag/rag-tool.d.ts.map +1 -1
  258. package/dist/rag/rag-tool.js +6 -3
  259. package/dist/rag/rag-tool.js.map +1 -1
  260. package/dist/rag/retriever.d.ts +2 -2
  261. package/dist/rag/retriever.d.ts.map +1 -1
  262. package/dist/rag/retriever.js +31 -15
  263. package/dist/rag/retriever.js.map +1 -1
  264. package/dist/rag/vector-store.d.ts +3 -3
  265. package/dist/rag/vector-store.d.ts.map +1 -1
  266. package/dist/rag/vector-store.js +4 -2
  267. package/dist/rag/vector-store.js.map +1 -1
  268. package/dist/registry/command/kernel-commands.d.ts +16 -4
  269. package/dist/registry/command/kernel-commands.d.ts.map +1 -1
  270. package/dist/registry/command/kernel-commands.js +171 -0
  271. package/dist/registry/command/kernel-commands.js.map +1 -1
  272. package/dist/run/reporter.d.ts.map +1 -1
  273. package/dist/run/reporter.js +9 -0
  274. package/dist/run/reporter.js.map +1 -1
  275. package/dist/run-query/index.d.ts +15 -1
  276. package/dist/run-query/index.d.ts.map +1 -1
  277. package/dist/run-query/index.js +69 -15
  278. package/dist/run-query/index.js.map +1 -1
  279. package/dist/runtime/query/context.d.ts.map +1 -1
  280. package/dist/runtime/query/context.js +10 -3
  281. package/dist/runtime/query/context.js.map +1 -1
  282. package/dist/runtime/query/executor.d.ts +3 -0
  283. package/dist/runtime/query/executor.d.ts.map +1 -1
  284. package/dist/runtime/query/executor.js +80 -18
  285. package/dist/runtime/query/executor.js.map +1 -1
  286. package/dist/runtime/query/guard.d.ts +9 -0
  287. package/dist/runtime/query/guard.d.ts.map +1 -1
  288. package/dist/runtime/query/guard.js +11 -0
  289. package/dist/runtime/query/guard.js.map +1 -1
  290. package/dist/runtime/query/index.d.ts +30 -1
  291. package/dist/runtime/query/index.d.ts.map +1 -1
  292. package/dist/runtime/query/index.js +548 -95
  293. package/dist/runtime/query/index.js.map +1 -1
  294. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  295. package/dist/runtime/query/iteration/index.js +74 -14
  296. package/dist/runtime/query/iteration/index.js.map +1 -1
  297. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  298. package/dist/runtime/query/iteration/phases/compaction.js +94 -53
  299. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  300. package/dist/runtime/query/iteration/phases/context.d.ts +3 -0
  301. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  302. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  303. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  304. package/dist/runtime/query/iteration/phases/tool-review.js +21 -0
  305. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  306. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  307. package/dist/runtime/query/iteration/stream-turn.js +4 -0
  308. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  309. package/dist/runtime/query/project-instructions.d.ts +69 -0
  310. package/dist/runtime/query/project-instructions.d.ts.map +1 -0
  311. package/dist/runtime/query/project-instructions.js +137 -0
  312. package/dist/runtime/query/project-instructions.js.map +1 -0
  313. package/dist/runtime/query/request-rich-content.d.ts +22 -0
  314. package/dist/runtime/query/request-rich-content.d.ts.map +1 -0
  315. package/dist/runtime/query/request-rich-content.js +122 -0
  316. package/dist/runtime/query/request-rich-content.js.map +1 -0
  317. package/dist/runtime/query/result.d.ts.map +1 -1
  318. package/dist/runtime/query/result.js +12 -1
  319. package/dist/runtime/query/result.js.map +1 -1
  320. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  321. package/dist/runtime/query/resume-pending.js +19 -20
  322. package/dist/runtime/query/resume-pending.js.map +1 -1
  323. package/dist/runtime/query/resume-run.d.ts.map +1 -1
  324. package/dist/runtime/query/resume-run.js +54 -8
  325. package/dist/runtime/query/resume-run.js.map +1 -1
  326. package/dist/runtime/query/run-state.d.ts +5 -0
  327. package/dist/runtime/query/run-state.d.ts.map +1 -1
  328. package/dist/runtime/query/run-state.js +6 -1
  329. package/dist/runtime/query/run-state.js.map +1 -1
  330. package/dist/runtime/query/sandbox-lifecycle.d.ts +54 -0
  331. package/dist/runtime/query/sandbox-lifecycle.d.ts.map +1 -0
  332. package/dist/runtime/query/sandbox-lifecycle.js +167 -0
  333. package/dist/runtime/query/sandbox-lifecycle.js.map +1 -0
  334. package/dist/sandbox/isolation.d.ts.map +1 -1
  335. package/dist/sandbox/isolation.js +9 -0
  336. package/dist/sandbox/isolation.js.map +1 -1
  337. package/dist/sandbox/provider/local.d.ts +56 -6
  338. package/dist/sandbox/provider/local.d.ts.map +1 -1
  339. package/dist/sandbox/provider/local.js +181 -76
  340. package/dist/sandbox/provider/local.js.map +1 -1
  341. package/dist/sandbox/terminal.d.ts +13 -5
  342. package/dist/sandbox/terminal.d.ts.map +1 -1
  343. package/dist/sandbox/terminal.js +11 -3
  344. package/dist/sandbox/terminal.js.map +1 -1
  345. package/dist/session/errors.d.ts +28 -29
  346. package/dist/session/errors.d.ts.map +1 -1
  347. package/dist/session/errors.js +28 -29
  348. package/dist/session/errors.js.map +1 -1
  349. package/dist/session/handoff/broadcast.d.ts +5 -8
  350. package/dist/session/handoff/broadcast.d.ts.map +1 -1
  351. package/dist/session/handoff/broadcast.js +16 -6
  352. package/dist/session/handoff/broadcast.js.map +1 -1
  353. package/dist/session/handoff/single.d.ts +5 -8
  354. package/dist/session/handoff/single.d.ts.map +1 -1
  355. package/dist/session/handoff/single.js +7 -4
  356. package/dist/session/handoff/single.js.map +1 -1
  357. package/dist/store/attachment/index.d.ts +11 -3
  358. package/dist/store/attachment/index.d.ts.map +1 -1
  359. package/dist/store/attachment/index.js +49 -4
  360. package/dist/store/attachment/index.js.map +1 -1
  361. package/dist/store/feedback/conformance.d.ts.map +1 -1
  362. package/dist/store/feedback/conformance.js +32 -0
  363. package/dist/store/feedback/conformance.js.map +1 -1
  364. package/dist/store/feedback/disk.d.ts +8 -6
  365. package/dist/store/feedback/disk.d.ts.map +1 -1
  366. package/dist/store/feedback/disk.js +111 -76
  367. package/dist/store/feedback/disk.js.map +1 -1
  368. package/dist/store/goal/index.d.ts +111 -0
  369. package/dist/store/goal/index.d.ts.map +1 -0
  370. package/dist/store/goal/index.js +436 -0
  371. package/dist/store/goal/index.js.map +1 -0
  372. package/dist/store/index.d.ts +1 -1
  373. package/dist/store/index.d.ts.map +1 -1
  374. package/dist/store/index.js +1 -1
  375. package/dist/store/index.js.map +1 -1
  376. package/dist/store/kv/revision-record-store.d.ts +70 -0
  377. package/dist/store/kv/revision-record-store.d.ts.map +1 -0
  378. package/dist/store/kv/revision-record-store.js +290 -0
  379. package/dist/store/kv/revision-record-store.js.map +1 -0
  380. package/dist/store/memory/disk.d.ts +9 -7
  381. package/dist/store/memory/disk.d.ts.map +1 -1
  382. package/dist/store/memory/disk.js +256 -98
  383. package/dist/store/memory/disk.js.map +1 -1
  384. package/dist/store/run/disk.d.ts +10 -2
  385. package/dist/store/run/disk.d.ts.map +1 -1
  386. package/dist/store/run/disk.js +70 -4
  387. package/dist/store/run/disk.js.map +1 -1
  388. package/dist/store/run/memory.d.ts +4 -2
  389. package/dist/store/run/memory.d.ts.map +1 -1
  390. package/dist/store/run/memory.js +15 -1
  391. package/dist/store/run/memory.js.map +1 -1
  392. package/dist/store/session/disk.d.ts +9 -0
  393. package/dist/store/session/disk.d.ts.map +1 -1
  394. package/dist/store/session/disk.js +57 -5
  395. package/dist/store/session/disk.js.map +1 -1
  396. package/dist/store/session/memory.d.ts +1 -0
  397. package/dist/store/session/memory.d.ts.map +1 -1
  398. package/dist/store/session/memory.js +14 -0
  399. package/dist/store/session/memory.js.map +1 -1
  400. package/dist/store/topic/memory.d.ts +1 -2
  401. package/dist/store/topic/memory.d.ts.map +1 -1
  402. package/dist/store/topic/memory.js +4 -5
  403. package/dist/store/topic/memory.js.map +1 -1
  404. package/dist/store/topic/objective.d.ts +8 -4
  405. package/dist/store/topic/objective.d.ts.map +1 -1
  406. package/dist/store/topic/objective.js +185 -100
  407. package/dist/store/topic/objective.js.map +1 -1
  408. package/dist/store/topic/state.d.ts +1 -2
  409. package/dist/store/topic/state.d.ts.map +1 -1
  410. package/dist/store/topic/state.js +50 -62
  411. package/dist/store/topic/state.js.map +1 -1
  412. package/dist/tools/builtins/bash.d.ts.map +1 -1
  413. package/dist/tools/builtins/bash.js +20 -0
  414. package/dist/tools/builtins/bash.js.map +1 -1
  415. package/dist/tools/builtins/computer-use.d.ts +9 -1
  416. package/dist/tools/builtins/computer-use.d.ts.map +1 -1
  417. package/dist/tools/builtins/computer-use.js.map +1 -1
  418. package/dist/tools/builtins/content-fingerprint.d.ts +8 -7
  419. package/dist/tools/builtins/content-fingerprint.d.ts.map +1 -1
  420. package/dist/tools/builtins/content-fingerprint.js +9 -10
  421. package/dist/tools/builtins/content-fingerprint.js.map +1 -1
  422. package/dist/tools/builtins/edit.d.ts +6 -1
  423. package/dist/tools/builtins/edit.d.ts.map +1 -1
  424. package/dist/tools/builtins/edit.js +166 -27
  425. package/dist/tools/builtins/edit.js.map +1 -1
  426. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  427. package/dist/tools/builtins/write-file.js +45 -19
  428. package/dist/tools/builtins/write-file.js.map +1 -1
  429. package/dist/tools/command-arguments.d.ts +43 -0
  430. package/dist/tools/command-arguments.d.ts.map +1 -0
  431. package/dist/tools/command-arguments.js +52 -0
  432. package/dist/tools/command-arguments.js.map +1 -0
  433. package/dist/tools/coordinator/index.d.ts +2 -0
  434. package/dist/tools/coordinator/index.d.ts.map +1 -1
  435. package/dist/tools/coordinator/index.js +3 -1
  436. package/dist/tools/coordinator/index.js.map +1 -1
  437. package/dist/tools/defineTool.d.ts +10 -0
  438. package/dist/tools/defineTool.d.ts.map +1 -1
  439. package/dist/tools/defineTool.js +1 -0
  440. package/dist/tools/defineTool.js.map +1 -1
  441. package/dist/tools/env-scrub.d.ts +7 -5
  442. package/dist/tools/env-scrub.d.ts.map +1 -1
  443. package/dist/tools/env-scrub.js +7 -5
  444. package/dist/tools/env-scrub.js.map +1 -1
  445. package/dist/tools/goal/index.d.ts +20 -0
  446. package/dist/tools/goal/index.d.ts.map +1 -0
  447. package/dist/tools/goal/index.js +104 -0
  448. package/dist/tools/goal/index.js.map +1 -0
  449. package/dist/tools/memory/index.d.ts +16 -0
  450. package/dist/tools/memory/index.d.ts.map +1 -1
  451. package/dist/tools/memory/index.js +6 -2
  452. package/dist/tools/memory/index.js.map +1 -1
  453. package/dist/tools/memory/search.d.ts +4 -1
  454. package/dist/tools/memory/search.d.ts.map +1 -1
  455. package/dist/tools/memory/search.js +10 -2
  456. package/dist/tools/memory/search.js.map +1 -1
  457. package/dist/types/agent/base.d.ts +11 -3
  458. package/dist/types/agent/base.d.ts.map +1 -1
  459. package/dist/types/agent/factory.d.ts +2 -0
  460. package/dist/types/agent/factory.d.ts.map +1 -1
  461. package/dist/types/agent/reactive.d.ts +2 -0
  462. package/dist/types/agent/reactive.d.ts.map +1 -1
  463. package/dist/types/agent/supervisor.d.ts +6 -0
  464. package/dist/types/agent/supervisor.d.ts.map +1 -1
  465. package/dist/types/agent/task.d.ts +6 -2
  466. package/dist/types/agent/task.d.ts.map +1 -1
  467. package/dist/types/connector/core.d.ts +13 -8
  468. package/dist/types/connector/core.d.ts.map +1 -1
  469. package/dist/types/connector/definition.d.ts +37 -18
  470. package/dist/types/connector/definition.d.ts.map +1 -1
  471. package/dist/types/connector/http.d.ts +6 -0
  472. package/dist/types/connector/http.d.ts.map +1 -1
  473. package/dist/types/connector/mcp.d.ts +24 -6
  474. package/dist/types/connector/mcp.d.ts.map +1 -1
  475. package/dist/types/connector/tenant.d.ts +17 -7
  476. package/dist/types/connector/tenant.d.ts.map +1 -1
  477. package/dist/types/connector/webhook.d.ts +6 -0
  478. package/dist/types/connector/webhook.d.ts.map +1 -1
  479. package/dist/types/goal/index.d.ts +46 -0
  480. package/dist/types/goal/index.d.ts.map +1 -0
  481. package/dist/types/goal/index.js +2 -0
  482. package/dist/types/goal/index.js.map +1 -0
  483. package/dist/types/ids/index.d.ts +2 -0
  484. package/dist/types/ids/index.d.ts.map +1 -1
  485. package/dist/types/ids/index.js.map +1 -1
  486. package/dist/types/message/index.d.ts +79 -13
  487. package/dist/types/message/index.d.ts.map +1 -1
  488. package/dist/types/message/index.js +49 -3
  489. package/dist/types/message/index.js.map +1 -1
  490. package/dist/types/plugin/index.d.ts +7 -5
  491. package/dist/types/plugin/index.d.ts.map +1 -1
  492. package/dist/types/plugin/index.js.map +1 -1
  493. package/dist/types/provider/chat.d.ts +27 -4
  494. package/dist/types/provider/chat.d.ts.map +1 -1
  495. package/dist/types/provider/index.d.ts +1 -1
  496. package/dist/types/provider/index.d.ts.map +1 -1
  497. package/dist/types/provider/interface.d.ts +18 -7
  498. package/dist/types/provider/interface.d.ts.map +1 -1
  499. package/dist/types/provider/model.d.ts +12 -0
  500. package/dist/types/provider/model.d.ts.map +1 -1
  501. package/dist/types/provider/stream.d.ts +6 -0
  502. package/dist/types/provider/stream.d.ts.map +1 -1
  503. package/dist/types/rag/embedding.d.ts +15 -2
  504. package/dist/types/rag/embedding.d.ts.map +1 -1
  505. package/dist/types/rag/ingestion.d.ts +2 -2
  506. package/dist/types/rag/ingestion.d.ts.map +1 -1
  507. package/dist/types/rag/knowledge-base.d.ts +3 -3
  508. package/dist/types/rag/knowledge-base.d.ts.map +1 -1
  509. package/dist/types/rag/retrieval.d.ts +2 -2
  510. package/dist/types/rag/retrieval.d.ts.map +1 -1
  511. package/dist/types/rag/scope.d.ts +4 -0
  512. package/dist/types/rag/scope.d.ts.map +1 -1
  513. package/dist/types/rag/vector.d.ts +5 -2
  514. package/dist/types/rag/vector.d.ts.map +1 -1
  515. package/dist/types/run/config.d.ts +20 -0
  516. package/dist/types/run/config.d.ts.map +1 -1
  517. package/dist/types/run/events.d.ts +25 -1
  518. package/dist/types/run/events.d.ts.map +1 -1
  519. package/dist/types/run/events.js.map +1 -1
  520. package/dist/types/run/metadata.d.ts +2 -0
  521. package/dist/types/run/metadata.d.ts.map +1 -1
  522. package/dist/types/run/step.d.ts +2 -6
  523. package/dist/types/run/step.d.ts.map +1 -1
  524. package/dist/types/run/step.js.map +1 -1
  525. package/dist/types/run/store.d.ts +55 -2
  526. package/dist/types/run/store.d.ts.map +1 -1
  527. package/dist/types/sandbox/index.d.ts +47 -6
  528. package/dist/types/sandbox/index.d.ts.map +1 -1
  529. package/dist/types/sandbox/index.js +23 -10
  530. package/dist/types/sandbox/index.js.map +1 -1
  531. package/dist/types/session/store.d.ts +13 -0
  532. package/dist/types/session/store.d.ts.map +1 -1
  533. package/dist/types/tool/index.d.ts +33 -11
  534. package/dist/types/tool/index.d.ts.map +1 -1
  535. package/dist/types/tool/index.js.map +1 -1
  536. package/dist/types/topic/entity.d.ts +3 -4
  537. package/dist/types/topic/entity.d.ts.map +1 -1
  538. package/dist/types/topic/store.d.ts +3 -3
  539. package/dist/utils/id.d.ts +3 -1
  540. package/dist/utils/id.d.ts.map +1 -1
  541. package/dist/utils/id.js +4 -0
  542. package/dist/utils/id.js.map +1 -1
  543. package/dist/utils/process-environment.d.ts +26 -0
  544. package/dist/utils/process-environment.d.ts.map +1 -0
  545. package/dist/utils/process-environment.js +78 -0
  546. package/dist/utils/process-environment.js.map +1 -0
  547. package/dist/vault/InMemoryCredentialVault.d.ts +2 -0
  548. package/dist/vault/InMemoryCredentialVault.d.ts.map +1 -1
  549. package/dist/vault/InMemoryCredentialVault.js +24 -4
  550. package/dist/vault/InMemoryCredentialVault.js.map +1 -1
  551. package/dist/vault/instrumentation.d.ts.map +1 -1
  552. package/dist/vault/instrumentation.js +15 -0
  553. package/dist/vault/instrumentation.js.map +1 -1
  554. package/package.json +1 -1
  555. package/src/advisory/executor.ts +4 -1
  556. package/src/agents/ReactiveAgent.ts +12 -0
  557. package/src/agents/RouterAgent.ts +25 -3
  558. package/src/agents/SupervisorAgent.ts +33 -11
  559. package/src/agents/runAgent.ts +38 -2
  560. package/src/authorization/command-line.ts +390 -0
  561. package/src/authorization/rules.ts +22 -1
  562. package/src/bridge/a2a/client.ts +384 -97
  563. package/src/bridge/a2a/mapper.ts +5 -0
  564. package/src/bridge/acp/server.ts +184 -42
  565. package/src/bridge/mcp/connector/adapter.ts +28 -20
  566. package/src/bridge/sse/mapper.ts +3 -0
  567. package/src/compaction/dangling.ts +203 -38
  568. package/src/compaction/index.ts +9 -2
  569. package/src/compaction/manual.ts +125 -18
  570. package/src/compaction/plan.ts +42 -11
  571. package/src/compaction/retention.ts +23 -8
  572. package/src/compaction/summary.ts +4 -4
  573. package/src/compaction/verifier.ts +66 -0
  574. package/src/connector/BaseConnector.ts +19 -4
  575. package/src/connector/builtins/http.ts +236 -46
  576. package/src/connector/builtins/webhook.ts +207 -47
  577. package/src/connector/execution-contract.ts +27 -0
  578. package/src/connector/http-operation.ts +238 -0
  579. package/src/connector/mcp/adapter.ts +8 -3
  580. package/src/connector/mcp/client.ts +207 -58
  581. package/src/connector/mcp/http-sse.ts +91 -23
  582. package/src/connector/mcp/prompt-adapter.ts +8 -2
  583. package/src/connector/mcp/stdio.ts +21 -46
  584. package/src/connector/mcp/streamable-http.ts +86 -22
  585. package/src/connector/tools/adapter.ts +23 -14
  586. package/src/connector/tools/definitions.ts +5 -2
  587. package/src/connector/tools/result.ts +21 -0
  588. package/src/connector/web/guarded-fetch.ts +188 -48
  589. package/src/constants/sandbox/index.ts +3 -2
  590. package/src/contracts/api.ts +2 -0
  591. package/src/contracts/schemas.ts +7 -0
  592. package/src/directory/derive-supervisor.ts +8 -0
  593. package/src/directory/derive.ts +8 -0
  594. package/src/directory/load.ts +2 -0
  595. package/src/directory/types.ts +4 -0
  596. package/src/eval/experiment.ts +160 -111
  597. package/src/eval/judge.ts +13 -2
  598. package/src/eval/types.ts +7 -1
  599. package/src/manager/agent/lifecycle.ts +28 -12
  600. package/src/manager/connector/environment.ts +3 -1
  601. package/src/manager/connector/lifecycle.ts +364 -24
  602. package/src/manager/connector/tenant.ts +56 -23
  603. package/src/manager/goal/activation.ts +52 -0
  604. package/src/manager/index.ts +10 -2
  605. package/src/manager/run/persistence.ts +6 -1
  606. package/src/manager/topic/dependency.ts +39 -0
  607. package/src/manager/topic/lifecycle.ts +19 -31
  608. package/src/plugin/index.ts +1 -0
  609. package/src/plugin/lifecycle.ts +180 -39
  610. package/src/plugin/loader.ts +70 -13
  611. package/src/provider/collect-chat-completion.ts +3 -0
  612. package/src/provider/fallback.ts +79 -11
  613. package/src/provider/idle-timeout.ts +143 -17
  614. package/src/provider/index.ts +2 -0
  615. package/src/provider/instrumentation.ts +1 -0
  616. package/src/provider/retry.ts +16 -1
  617. package/src/public-runtime.ts +190 -32
  618. package/src/public-tools.ts +5 -0
  619. package/src/public-types.ts +85 -11
  620. package/src/rag/embedding.ts +147 -19
  621. package/src/rag/index.ts +1 -1
  622. package/src/rag/ingestion.ts +16 -2
  623. package/src/rag/knowledge-base.ts +13 -4
  624. package/src/rag/operation.ts +28 -0
  625. package/src/rag/rag-tool.ts +6 -3
  626. package/src/rag/retriever.ts +62 -11
  627. package/src/rag/vector-store.ts +8 -2
  628. package/src/registry/command/kernel-commands.ts +223 -4
  629. package/src/run/reporter.ts +10 -0
  630. package/src/run-query/index.ts +84 -15
  631. package/src/runtime/query/context.ts +13 -3
  632. package/src/runtime/query/executor.ts +90 -17
  633. package/src/runtime/query/guard.ts +12 -0
  634. package/src/runtime/query/index.ts +652 -103
  635. package/src/runtime/query/iteration/index.ts +89 -13
  636. package/src/runtime/query/iteration/phases/compaction.ts +120 -55
  637. package/src/runtime/query/iteration/phases/context.ts +4 -0
  638. package/src/runtime/query/iteration/phases/tool-review.ts +28 -0
  639. package/src/runtime/query/iteration/stream-turn.ts +3 -0
  640. package/src/runtime/query/project-instructions.ts +212 -0
  641. package/src/runtime/query/request-rich-content.ts +153 -0
  642. package/src/runtime/query/result.ts +12 -1
  643. package/src/runtime/query/resume-pending.ts +20 -18
  644. package/src/runtime/query/resume-run.ts +52 -8
  645. package/src/runtime/query/run-state.ts +11 -1
  646. package/src/runtime/query/sandbox-lifecycle.ts +210 -0
  647. package/src/sandbox/isolation.ts +9 -0
  648. package/src/sandbox/provider/local.ts +255 -90
  649. package/src/sandbox/terminal.ts +13 -5
  650. package/src/session/errors.ts +68 -42
  651. package/src/session/handoff/broadcast.ts +20 -14
  652. package/src/session/handoff/single.ts +14 -13
  653. package/src/store/attachment/index.ts +65 -3
  654. package/src/store/feedback/conformance.ts +39 -0
  655. package/src/store/feedback/disk.ts +128 -82
  656. package/src/store/goal/index.ts +594 -0
  657. package/src/store/index.ts +1 -1
  658. package/src/store/kv/revision-record-store.ts +346 -0
  659. package/src/store/memory/disk.ts +288 -113
  660. package/src/store/run/disk.ts +96 -5
  661. package/src/store/run/memory.ts +22 -2
  662. package/src/store/session/disk.ts +93 -6
  663. package/src/store/session/memory.ts +22 -0
  664. package/src/store/topic/memory.ts +4 -5
  665. package/src/store/topic/objective.ts +215 -100
  666. package/src/store/topic/state.ts +100 -63
  667. package/src/tools/builtins/bash.ts +21 -0
  668. package/src/tools/builtins/computer-use.ts +9 -1
  669. package/src/tools/builtins/content-fingerprint.ts +9 -12
  670. package/src/tools/builtins/edit.ts +190 -27
  671. package/src/tools/builtins/write-file.ts +55 -19
  672. package/src/tools/command-arguments.ts +54 -0
  673. package/src/tools/coordinator/index.ts +4 -1
  674. package/src/tools/defineTool.ts +11 -0
  675. package/src/tools/env-scrub.ts +7 -5
  676. package/src/tools/goal/index.ts +129 -0
  677. package/src/tools/memory/index.ts +26 -3
  678. package/src/tools/memory/search.ts +20 -3
  679. package/src/types/agent/base.ts +12 -3
  680. package/src/types/agent/factory.ts +2 -0
  681. package/src/types/agent/reactive.ts +2 -0
  682. package/src/types/agent/supervisor.ts +6 -0
  683. package/src/types/agent/task.ts +6 -2
  684. package/src/types/connector/core.ts +13 -8
  685. package/src/types/connector/definition.ts +54 -20
  686. package/src/types/connector/http.ts +7 -0
  687. package/src/types/connector/mcp.ts +27 -6
  688. package/src/types/connector/tenant.ts +21 -7
  689. package/src/types/connector/webhook.ts +7 -0
  690. package/src/types/goal/index.ts +50 -0
  691. package/src/types/ids/index.ts +2 -0
  692. package/src/types/message/index.ts +147 -12
  693. package/src/types/plugin/index.ts +7 -5
  694. package/src/types/provider/chat.ts +35 -4
  695. package/src/types/provider/index.ts +1 -1
  696. package/src/types/provider/interface.ts +22 -7
  697. package/src/types/provider/model.ts +13 -0
  698. package/src/types/provider/stream.ts +6 -0
  699. package/src/types/rag/embedding.ts +16 -2
  700. package/src/types/rag/ingestion.ts +2 -1
  701. package/src/types/rag/knowledge-base.ts +7 -3
  702. package/src/types/rag/retrieval.ts +2 -1
  703. package/src/types/rag/scope.ts +5 -0
  704. package/src/types/rag/vector.ts +5 -2
  705. package/src/types/run/config.ts +20 -0
  706. package/src/types/run/events.ts +28 -3
  707. package/src/types/run/metadata.ts +2 -0
  708. package/src/types/run/step.ts +2 -7
  709. package/src/types/run/store.ts +60 -2
  710. package/src/types/sandbox/index.ts +57 -14
  711. package/src/types/session/store.ts +18 -0
  712. package/src/types/tool/index.ts +33 -11
  713. package/src/types/topic/entity.ts +3 -4
  714. package/src/types/topic/store.ts +3 -3
  715. package/src/utils/id.ts +6 -0
  716. package/src/utils/process-environment.ts +101 -0
  717. package/src/vault/InMemoryCredentialVault.ts +29 -4
  718. package/src/vault/instrumentation.ts +24 -0
@@ -0,0 +1,52 @@
1
+ import type { GoalRef, SessionGoal } from '../../types/goal/index.js'
2
+ import type { SessionId } from '../../types/ids/index.js'
3
+
4
+ export interface ActiveSessionGoal extends GoalRef {
5
+ readonly sessionId: SessionId
6
+ }
7
+
8
+ function sameGoal(left: GoalRef, right: GoalRef): boolean {
9
+ return left.id === right.id && left.revision === right.revision
10
+ }
11
+
12
+ /**
13
+ * Process-local permission for automatic goal continuation.
14
+ *
15
+ * Durable `phase: active` describes goal state; it does not grant a restarted
16
+ * process permission to spend another model turn. Hosts arm explicitly after
17
+ * direct create/resume and use exact disarm to keep an old turn from revoking
18
+ * a newer activation.
19
+ */
20
+ export class SessionGoalActivation {
21
+ private readonly active = new Map<SessionId, ActiveSessionGoal>()
22
+
23
+ arm(goal: Pick<SessionGoal, 'sessionId' | 'id' | 'revision'>): ActiveSessionGoal {
24
+ const armed = Object.freeze({
25
+ sessionId: goal.sessionId,
26
+ id: goal.id,
27
+ revision: goal.revision,
28
+ })
29
+ this.active.set(goal.sessionId, armed)
30
+ return armed
31
+ }
32
+
33
+ get(sessionId: SessionId): ActiveSessionGoal | null {
34
+ return this.active.get(sessionId) ?? null
35
+ }
36
+
37
+ isArmed(sessionId: SessionId, ref: GoalRef): boolean {
38
+ const active = this.active.get(sessionId)
39
+ return Boolean(active && sameGoal(active, ref))
40
+ }
41
+
42
+ /** Disarm unconditionally, or only if the caller still owns the exact ref. */
43
+ disarm(sessionId: SessionId, expected?: GoalRef): boolean {
44
+ const active = this.active.get(sessionId)
45
+ if (!active || (expected && !sameGoal(active, expected))) return false
46
+ return this.active.delete(sessionId)
47
+ }
48
+
49
+ clear(): void {
50
+ this.active.clear()
51
+ }
52
+ }
@@ -14,7 +14,11 @@ export type {
14
14
  } from './connector/environment.js'
15
15
 
16
16
  export { PlanManager } from './plan/lifecycle.js'
17
- export type { PlanEvent, PlanEventListener, PlanApprovalHandler } from './plan/lifecycle.js'
17
+ export type {
18
+ PlanEvent,
19
+ PlanEventListener,
20
+ PlanApprovalHandler,
21
+ } from './plan/lifecycle.js'
18
22
 
19
23
  export {
20
24
  TopicManager,
@@ -23,6 +27,7 @@ export {
23
27
  export type { TopicManagerDeps } from './topic/lifecycle.js'
24
28
 
25
29
  export { AgentManager } from './agent/lifecycle.js'
30
+ export type { AgentManagerDeps } from './agent/lifecycle.js'
26
31
 
27
32
  export { ProjectManager, requireOpenProject } from './project/lifecycle.js'
28
33
  export type { ProjectManagerDeps } from './project/lifecycle.js'
@@ -35,4 +40,7 @@ export {
35
40
  advanceObjective,
36
41
  driveObjective,
37
42
  } from './topic/objective.js'
38
- export type { AdvanceObjectiveParams, DriveObjectiveParams } from './topic/objective.js'
43
+ export type {
44
+ AdvanceObjectiveParams,
45
+ DriveObjectiveParams,
46
+ } from './topic/objective.js'
@@ -312,6 +312,11 @@ export class RunPersistence {
312
312
  this.run.messages.push(message)
313
313
  }
314
314
 
315
+ /** Replace the durable conversation projection without replacing the Run. */
316
+ replaceMessages(messages: readonly Message[]): void {
317
+ this.run.messages.splice(0, this.run.messages.length, ...messages)
318
+ }
319
+
315
320
  /**
316
321
  * Who served the tokens being accumulated, so a rate can be found for them.
317
322
  *
@@ -669,7 +674,7 @@ export class RunPersistence {
669
674
 
670
675
  async persist(): Promise<void> {
671
676
  await this.runStore.writeRunMeta(this.run)
672
- await this.runStore.writeMessages(this.run)
677
+ await this.runStore.writeMessages(this.run, this._lastEventSeq)
673
678
  // Optional on the contract: a backend whose runs are already queryable
674
679
  // has no browsable directory to add a row to.
675
680
  await this.runStore.addToIndex?.(this.run)
@@ -0,0 +1,39 @@
1
+ import type { TopicManager } from './lifecycle.js'
2
+
3
+ /**
4
+ * A dependency on the Topic lifecycle gate during the `threadManager` rename
5
+ * window.
6
+ *
7
+ * At least one spelling is required. Supplying both is accepted only when
8
+ * they name the same manager instance; choosing one of two different gates by
9
+ * property order would make archive enforcement depend on object shape.
10
+ */
11
+ export type TopicManagerDependency =
12
+ | {
13
+ readonly topicManager: TopicManager
14
+ /** @deprecated Use {@link topicManager}. */
15
+ readonly threadManager?: TopicManager
16
+ }
17
+ | {
18
+ readonly topicManager?: never
19
+ /** @deprecated Use `topicManager`. */
20
+ readonly threadManager: TopicManager
21
+ }
22
+
23
+ /** Resolve the canonical manager or refuse an ambiguous/missing runtime input. */
24
+ export function resolveTopicManager(dependency: {
25
+ readonly topicManager?: TopicManager
26
+ readonly threadManager?: TopicManager
27
+ }): TopicManager {
28
+ const { topicManager, threadManager } = dependency
29
+ if (topicManager && threadManager && topicManager !== threadManager) {
30
+ throw new TypeError(
31
+ 'topicManager and deprecated threadManager refer to different TopicManager instances; provide one manager, or pass the same instance under both names during migration.',
32
+ )
33
+ }
34
+ const resolved = topicManager ?? threadManager
35
+ if (!resolved) {
36
+ throw new TypeError('A TopicManager is required as topicManager.')
37
+ }
38
+ return resolved
39
+ }
@@ -19,29 +19,17 @@
19
19
  * why the gate lives at the manager layer rather than as a universal store
20
20
  * interceptor (see `archive` JSDoc for the direct-store-bypass boundary).
21
21
  *
22
- * NZ-TOPIC-01 renamed this class from `ThreadManager` (moved from
23
- * `manager/thread/lifecycle.ts`). NZ-TOPIC-04 deleted the `ThreadManager`
24
- * alias entirely (see AGENTS.md's deprecate-before-remove note in the
25
- * changeset for why a major, not a minor, was the right call here) the
26
- * class only lives under `TopicManager` now. NZ-TOPIC-03 renamed the
27
- * `threadId` parameter on every method below to `topicId` — the FK-field
28
- * rename that release deliberately deferred, now landed with its own data
29
- * migration in `store/session/disk.ts`. `threadStore` (a DI dependency,
30
- * not the FK) stayed `topicStore` from that same release. The thrown
31
- * error classes (`ThreadClosedError`/`ThreadNotEmptyError`) are STILL
32
- * unchanged in name, and so is their `details.threadId` field's NAME —
33
- * `session/errors.ts` remains deliberately out of scope for the class and
34
- * field renames (a clean follow-up), though NZ-TOPIC-04 did narrow the
35
- * TYPE backing that field from `ThreadId` to `TopicId` since the former no
36
- * longer exists. Constructing one from a `topicId` local below therefore
37
- * still spells the key out (`{ threadId: topicId, ... }`) rather than
38
- * using shorthand.
22
+ * The former Thread vocabulary has been removed from this public lifecycle:
23
+ * manager names, method parameters, error classes, and structured error
24
+ * details all use Topic. Persistence migrations may still recognize legacy
25
+ * field names, but live manager behavior never asks a caller to translate
26
+ * back to a deleted domain term.
39
27
  */
40
28
 
41
29
  import {
42
- THREAD_NOT_EMPTY_SAMPLE_LIMIT,
43
- ThreadClosedError,
44
- ThreadNotEmptyError,
30
+ TOPIC_NOT_EMPTY_SAMPLE_LIMIT,
31
+ TopicArchivedError,
32
+ TopicNotEmptyError,
45
33
  } from '../../session/errors.js'
46
34
  import type { TenantId } from '../../types/ids/index.js'
47
35
  import type { Session, SessionStatus } from '../../types/session/entity.js'
@@ -91,7 +79,7 @@ export class TopicManager {
91
79
  }
92
80
 
93
81
  /**
94
- * CAS update on a Topic. Propagates {@link import('../../session/errors.js').StaleThreadError}
82
+ * CAS update on a Topic. Propagates {@link import('../../session/errors.js').StaleTopicError}
95
83
  * from the store on `ownerVersion` mismatch — callers re-read, re-apply,
96
84
  * and retry.
97
85
  */
@@ -119,7 +107,7 @@ export class TopicManager {
119
107
  throw new Error(`Topic ${topicId} not found`)
120
108
  }
121
109
  if (topic.status === 'archived') {
122
- throw new ThreadClosedError({ threadId: topicId, op: 'require-open' })
110
+ throw new TopicArchivedError({ topicId, op: 'require-open' })
123
111
  }
124
112
  return topic
125
113
  }
@@ -133,14 +121,14 @@ export class TopicManager {
133
121
  * {@link ARCHIVAL_BLOCKING_STATUSES}). The presence check runs
134
122
  * **before** the idempotent-archive short-circuit so that an already
135
123
  * archived topic harboring a live session still surfaces as
136
- * {@link ThreadNotEmptyError} rather than a silent success.
124
+ * {@link TopicNotEmptyError} rather than a silent success.
137
125
  * 3. If the topic is already `'archived'` the method short-circuits
138
126
  * without an `updateTopic` write (idempotent re-archival). The
139
127
  * returned record reflects the current persisted state.
140
128
  *
141
129
  * On a fresh archive transition the underlying
142
130
  * {@link TopicStore.updateTopic} call commits with `ownerVersion + 1`.
143
- * A {@link import('../../session/errors.js').StaleThreadError} from a
131
+ * A {@link import('../../session/errors.js').StaleTopicError} from a
144
132
  * concurrent writer propagates unchanged — the caller is expected to
145
133
  * re-read + retry (mirrors the `updateTopic` contract).
146
134
  *
@@ -166,13 +154,13 @@ export class TopicManager {
166
154
  // Always enforce the blocking-session invariant — even on re-archival.
167
155
  // If the topic is already archived but somehow gained a live session
168
156
  // (direct store mutation, concurrent spawn before a write-barrier
169
- // existed), surfacing that via ThreadNotEmptyError is more useful to
157
+ // existed), surfacing that via TopicNotEmptyError is more useful to
170
158
  // operators than a silent idempotent success.
171
159
  const sessions = await this.deps.sessionStore.listSessionsByTopic(topicId, tenantId)
172
160
  const blocking = sessions.filter((s) => ARCHIVAL_BLOCKING_STATUSES.has(s.status))
173
161
  if (blocking.length > 0) {
174
- throw new ThreadNotEmptyError({
175
- threadId: topicId,
162
+ throw new TopicNotEmptyError({
163
+ topicId,
176
164
  tenantId,
177
165
  op: 'archive',
178
166
  blockingSessions: summarizeBlocking(blocking),
@@ -199,7 +187,7 @@ export class TopicManager {
199
187
  }
200
188
 
201
189
  /**
202
- * Hard-delete a Topic record. Rejects with {@link ThreadNotEmptyError}
190
+ * Hard-delete a Topic record. Rejects with {@link TopicNotEmptyError}
203
191
  * (`op: 'delete'`) when ANY Session still references the Topic —
204
192
  * deletion is stricter than archival, which tolerates quiescent sessions.
205
193
  * Callers must first delete or archive-and-tombstone every attached
@@ -214,8 +202,8 @@ export class TopicManager {
214
202
  async delete(topicId: TopicId, tenantId: TenantId): Promise<void> {
215
203
  const sessions = await this.deps.sessionStore.listSessionsByTopic(topicId, tenantId)
216
204
  if (sessions.length > 0) {
217
- throw new ThreadNotEmptyError({
218
- threadId: topicId,
205
+ throw new TopicNotEmptyError({
206
+ topicId,
219
207
  tenantId,
220
208
  op: 'delete',
221
209
  blockingSessions: summarizeBlocking(sessions),
@@ -230,6 +218,6 @@ function summarizeBlocking(
230
218
  sessions: readonly Session[],
231
219
  ): ReadonlyArray<{ sessionId: Session['id']; status: SessionStatus }> {
232
220
  return sessions
233
- .slice(0, THREAD_NOT_EMPTY_SAMPLE_LIMIT)
221
+ .slice(0, TOPIC_NOT_EMPTY_SAMPLE_LIMIT)
234
222
  .map((s) => ({ sessionId: s.id, status: s.status }))
235
223
  }
@@ -1,3 +1,4 @@
1
1
  export { discoverPlugins, loadPluginManifest, discoverAllPluginDirs } from './loader.js'
2
+ export type { PluginDiscoveryOptions, PluginEnablementCapabilities } from './loader.js'
2
3
  export { PluginLifecycleManager } from './lifecycle.js'
3
4
  export { PluginResolver } from './resolver.js'
@@ -54,9 +54,50 @@ interface PluginContributionRecord {
54
54
  mcpSupervisors: MCPReconnectSupervisor[]
55
55
  }
56
56
 
57
+ interface PluginAdmission {
58
+ readonly id: PluginId
59
+ readonly manifest: PluginDefinition['manifest']
60
+ readonly scope: PluginScope
61
+ readonly rootDir: string
62
+ readonly installedAt: number
63
+ }
64
+
65
+ function immutableManifest(manifest: PluginDefinition['manifest']): PluginDefinition['manifest'] {
66
+ const mcpServers = manifest.mcpServers?.map((server) =>
67
+ Object.freeze({
68
+ name: server.name,
69
+ command: server.command,
70
+ ...(server.args ? { args: Object.freeze([...server.args]) } : {}),
71
+ ...(server.env ? { env: Object.freeze({ ...server.env }) } : {}),
72
+ }),
73
+ )
74
+ return Object.freeze({
75
+ name: manifest.name,
76
+ version: manifest.version,
77
+ description: manifest.description,
78
+ ...(manifest.author !== undefined ? { author: manifest.author } : {}),
79
+ ...(manifest.tools ? { tools: Object.freeze([...manifest.tools]) } : {}),
80
+ ...(manifest.skills ? { skills: Object.freeze([...manifest.skills]) } : {}),
81
+ ...(manifest.hooks ? { hooks: Object.freeze([...manifest.hooks]) } : {}),
82
+ ...(mcpServers ? { mcpServers: Object.freeze(mcpServers) } : {}),
83
+ ...(manifest.connectors ? { connectors: Object.freeze([...manifest.connectors]) } : {}),
84
+ ...(manifest.personas ? { personas: Object.freeze([...manifest.personas]) } : {}),
85
+ })
86
+ }
87
+
57
88
  export interface PluginLifecycleManagerConfig {
58
89
  pluginRegistry: PluginRegistry
59
90
  toolRegistry: ToolRegistryContract
91
+ /**
92
+ * Filesystem authorities for each plugin scope.
93
+ *
94
+ * Required because `scope` is not an authority by itself. The manager
95
+ * canonicalizes a plugin against the matching root before reading its
96
+ * manifest and repeats that admission for legacy registry records before
97
+ * enabling them. A project manager normally uses the trusted working
98
+ * directory; a user manager normally uses the user's home directory.
99
+ */
100
+ scopeRoots: Readonly<Record<PluginScope, string>>
60
101
  /**
61
102
  * Where a plugin's declared skills land.
62
103
  *
@@ -121,8 +162,11 @@ export class PluginLifecycleManager {
121
162
  }>
122
163
  > = new Map()
123
164
  private pluginContributions: Map<PluginId, PluginContributionRecord> = new Map()
165
+ /** Immutable executable admissions owned by this manager, never by the mutable registry. */
166
+ private pluginAdmissions: Map<PluginId, PluginAdmission> = new Map()
124
167
  private hookTimeoutMs: number
125
168
  private readonly configRegistry: ConfigRegistry | undefined
169
+ private readonly scopeRoots: Readonly<Record<PluginScope, string>>
126
170
  private log: Logger
127
171
  /**
128
172
  * The admission boundary for everything a plugin's MCP servers advertise.
@@ -146,6 +190,7 @@ export class PluginLifecycleManager {
146
190
  this.pluginRegistry = config.pluginRegistry
147
191
  this.toolRegistry = config.toolRegistry
148
192
  this.skillRegistry = config.skillRegistry
193
+ this.scopeRoots = Object.freeze({ ...config.scopeRoots })
149
194
  this.hookTimeoutMs = config.hookTimeoutMs ?? HOOK_TIMEOUT_MS
150
195
  this.configRegistry = config.configRegistry
151
196
  this.log = config.log.child({ [SCOPE_ATTRIBUTE]: 'plugin/lifecycle' })
@@ -195,7 +240,15 @@ export class PluginLifecycleManager {
195
240
  }
196
241
 
197
242
  async install(pluginDir: string, scope: PluginScope): Promise<PluginDefinition> {
198
- const manifest = await loadPluginManifest(pluginDir)
243
+ // Admission and enable read the same constructor-owned capability. The
244
+ // loader defaults this to false for direct callers; a manager that really
245
+ // owns the registry is the authority that can opt the manifest in.
246
+ const rootDir = await resolveWithinReal(this.scopeRoots[scope], pluginDir)
247
+ const manifest = immutableManifest(
248
+ await loadPluginManifest(rootDir, {
249
+ skillsSupported: Boolean(this.skillRegistry),
250
+ }),
251
+ )
199
252
 
200
253
  const existing = this.pluginRegistry.findByName(manifest.name)
201
254
  if (existing) {
@@ -203,16 +256,17 @@ export class PluginLifecycleManager {
203
256
  }
204
257
 
205
258
  const pluginId = generatePluginId()
206
- const definition: PluginDefinition = {
259
+ const admission: PluginAdmission = Object.freeze({
207
260
  id: pluginId,
208
261
  manifest,
209
262
  scope,
210
- status: 'installed',
211
- rootDir: pluginDir,
263
+ rootDir,
212
264
  installedAt: Date.now(),
213
- }
265
+ })
266
+ const definition = this.definitionFrom(admission, 'installed')
214
267
 
215
268
  this.pluginRegistry.register(definition)
269
+ this.pluginAdmissions.set(pluginId, admission)
216
270
 
217
271
  this.emit({
218
272
  type: 'plugin_installed',
@@ -231,16 +285,81 @@ export class PluginLifecycleManager {
231
285
  return definition
232
286
  }
233
287
 
288
+ private definitionFrom(
289
+ admission: PluginAdmission,
290
+ status: PluginDefinition['status'],
291
+ enabledAt?: number,
292
+ ): PluginDefinition {
293
+ return Object.freeze({
294
+ ...admission,
295
+ status,
296
+ ...(enabledAt !== undefined ? { enabledAt } : {}),
297
+ })
298
+ }
299
+
300
+ private async readLegacyAdmission(plugin: PluginDefinition): Promise<PluginAdmission> {
301
+ const rootDir = await resolveWithinReal(this.scopeRoots[plugin.scope], plugin.rootDir)
302
+ const manifest = immutableManifest(
303
+ await loadPluginManifest(rootDir, {
304
+ skillsSupported: Boolean(this.skillRegistry),
305
+ }),
306
+ )
307
+ if (manifest.name !== plugin.manifest.name) {
308
+ throw new Error(
309
+ `Plugin registry record "${plugin.id}" names "${plugin.manifest.name}", but its admitted manifest names "${manifest.name}". Reinstall the plugin from its declared scope root.`,
310
+ )
311
+ }
312
+ const duplicate = this.pluginRegistry
313
+ .getAll()
314
+ .find((candidate) => candidate.id !== plugin.id && candidate.manifest.name === manifest.name)
315
+ if (duplicate) {
316
+ throw new Error(
317
+ `Plugin "${manifest.name}" is already installed (id: ${duplicate.id}); legacy record ${plugin.id} cannot be re-admitted.`,
318
+ )
319
+ }
320
+ return Object.freeze({
321
+ id: plugin.id,
322
+ manifest,
323
+ scope: plugin.scope,
324
+ rootDir,
325
+ installedAt: plugin.installedAt,
326
+ })
327
+ }
328
+
234
329
  async enable(pluginId: PluginId): Promise<void> {
235
330
  const plugin = this.pluginRegistry.getOrThrow(pluginId)
331
+ let admission = this.pluginAdmissions.get(pluginId)
236
332
 
237
- if (plugin.status !== 'installed' && plugin.status !== 'disabled') {
333
+ // The registry is a public projection and can be overwritten by a host.
334
+ // Contribution ownership is the executable lifecycle truth: trusting a
335
+ // forged `disabled` status here would register every hook/tool/MCP client
336
+ // twice and lose teardown ownership of the first set.
337
+ if (this.pluginContributions.has(pluginId)) {
238
338
  throw new Error(
239
- `Cannot enable plugin "${plugin.manifest.name}": status is "${plugin.status}" (expected "installed" or "disabled")`,
339
+ `Cannot enable plugin "${admission?.manifest.name ?? plugin.manifest.name}": status is "enabled" (expected "installed" or "disabled")`,
240
340
  )
241
341
  }
242
342
 
243
- const { manifest } = plugin
343
+ if (!admission) {
344
+ if (plugin.status !== 'installed' && plugin.status !== 'disabled') {
345
+ throw new Error(
346
+ `Cannot enable plugin "${plugin.manifest.name}": status is "${plugin.status}" (expected "installed" or "disabled")`,
347
+ )
348
+ }
349
+ try {
350
+ admission = await this.readLegacyAdmission(plugin)
351
+ this.pluginAdmissions.set(pluginId, admission)
352
+ } catch (error) {
353
+ this.pluginRegistry.register({
354
+ ...plugin,
355
+ status: 'error',
356
+ error: toErrorMessage(error),
357
+ })
358
+ throw error
359
+ }
360
+ }
361
+
362
+ const { manifest } = admission
244
363
 
245
364
  // The same refusal the loader applies at install, kept here as the
246
365
  // backstop for a plugin that reached this point another way — a
@@ -252,7 +371,10 @@ export class PluginLifecycleManager {
252
371
  try {
253
372
  assertEnableable(manifest, { skillsSupported: Boolean(this.skillRegistry) })
254
373
  } catch (err) {
255
- this.pluginRegistry.register({ ...plugin, status: 'error' })
374
+ this.pluginRegistry.register({
375
+ ...this.definitionFrom(admission, 'error'),
376
+ error: toErrorMessage(err),
377
+ })
256
378
  throw err
257
379
  }
258
380
 
@@ -267,7 +389,7 @@ export class PluginLifecycleManager {
267
389
  // Load tools
268
390
  if (manifest.tools && manifest.tools.length > 0) {
269
391
  for (const toolPath of manifest.tools) {
270
- const absolutePath = await resolveWithinReal(plugin.rootDir, toolPath)
392
+ const absolutePath = await resolveWithinReal(admission.rootDir, toolPath)
271
393
  const fileUrl = pathToFileURL(absolutePath).href
272
394
  const mod = (await import(fileUrl)) as { tools?: ToolDefinition[] }
273
395
 
@@ -302,7 +424,7 @@ export class PluginLifecycleManager {
302
424
  )
303
425
  }
304
426
  for (const skillPath of manifest.skills) {
305
- const absolutePath = await resolveWithinReal(plugin.rootDir, skillPath)
427
+ const absolutePath = await resolveWithinReal(admission.rootDir, skillPath)
306
428
  const { skill } = await loadSkill(absolutePath, 'metadata', this.log)
307
429
  const namespacedName = manifest.name + PLUGIN_NAMESPACE_SEPARATOR + skill.metadata.name
308
430
  skillRegistry.add(namespacedName, {
@@ -316,7 +438,7 @@ export class PluginLifecycleManager {
316
438
  // Load hooks
317
439
  if (manifest.hooks && manifest.hooks.length > 0) {
318
440
  for (const hookPath of manifest.hooks) {
319
- const absolutePath = await resolveWithinReal(plugin.rootDir, hookPath)
441
+ const absolutePath = await resolveWithinReal(admission.rootDir, hookPath)
320
442
  const fileUrl = pathToFileURL(absolutePath).href
321
443
  const mod = (await import(fileUrl)) as { hooks?: PluginHookDefinition[] }
322
444
 
@@ -345,11 +467,7 @@ export class PluginLifecycleManager {
345
467
 
346
468
  this.pluginContributions.set(pluginId, contributions)
347
469
 
348
- const enabled: PluginDefinition = {
349
- ...plugin,
350
- status: 'enabled',
351
- enabledAt: Date.now(),
352
- }
470
+ const enabled = this.definitionFrom(admission, 'enabled', Date.now())
353
471
  this.pluginRegistry.register(enabled)
354
472
 
355
473
  this.emit({
@@ -490,20 +608,15 @@ export class PluginLifecycleManager {
490
608
 
491
609
  async disable(pluginId: PluginId): Promise<void> {
492
610
  const plugin = this.pluginRegistry.getOrThrow(pluginId)
611
+ const admission = this.pluginAdmissions.get(pluginId)
612
+ const contributions = this.pluginContributions.get(pluginId)
493
613
 
494
- if (plugin.status !== 'enabled') {
614
+ if (!contributions) {
495
615
  throw new Error(
496
- `Cannot disable plugin "${plugin.manifest.name}": status is "${plugin.status}" (expected "enabled")`,
616
+ `Cannot disable plugin "${admission?.manifest.name ?? plugin.manifest.name}": status is not "enabled"`,
497
617
  )
498
618
  }
499
619
 
500
- const contributions = this.pluginContributions.get(pluginId) ?? {
501
- toolNames: [],
502
- mcpClients: [],
503
- skillNames: [],
504
- mcpSupervisors: [],
505
- }
506
-
507
620
  // Stop supervising first, for the same reason as the rollback path: the
508
621
  // disconnect below emits the event the supervisor treats as a fault.
509
622
  for (const supervisor of contributions.mcpSupervisors) supervisor.stop()
@@ -545,42 +658,42 @@ export class PluginLifecycleManager {
545
658
  this.pluginContributions.delete(pluginId)
546
659
 
547
660
  // Update status to disabled
548
- const disabled: PluginDefinition = {
549
- ...plugin,
550
- status: 'disabled',
551
- enabledAt: undefined,
552
- }
661
+ const disabled: PluginDefinition = admission
662
+ ? this.definitionFrom(admission, 'disabled')
663
+ : { ...plugin, status: 'disabled', enabledAt: undefined }
553
664
  this.pluginRegistry.register(disabled)
554
665
 
555
666
  this.emit({
556
667
  type: 'plugin_disabled',
557
668
  pluginId,
558
- name: plugin.manifest.name,
669
+ name: disabled.manifest.name,
559
670
  })
560
671
 
561
672
  this.log.info('Plugin disabled', {
562
- 'namzu.plugin.name': plugin.manifest.name,
673
+ 'namzu.plugin.name': disabled.manifest.name,
563
674
  'namzu.plugin.id': pluginId,
564
675
  })
565
676
  }
566
677
 
567
678
  async uninstall(pluginId: PluginId): Promise<void> {
568
679
  const plugin = this.pluginRegistry.getOrThrow(pluginId)
680
+ const admission = this.pluginAdmissions.get(pluginId)
569
681
 
570
- if (plugin.status === 'enabled') {
682
+ if (this.pluginContributions.has(pluginId)) {
571
683
  await this.disable(pluginId)
572
684
  }
573
685
 
574
686
  this.pluginRegistry.unregister(pluginId)
687
+ this.pluginAdmissions.delete(pluginId)
575
688
 
576
689
  this.emit({
577
690
  type: 'plugin_uninstalled',
578
691
  pluginId,
579
- name: plugin.manifest.name,
692
+ name: admission?.manifest.name ?? plugin.manifest.name,
580
693
  })
581
694
 
582
695
  this.log.info('Plugin uninstalled', {
583
- 'namzu.plugin.name': plugin.manifest.name,
696
+ 'namzu.plugin.name': admission?.manifest.name ?? plugin.manifest.name,
584
697
  'namzu.plugin.id': pluginId,
585
698
  })
586
699
  }
@@ -590,6 +703,8 @@ export class PluginLifecycleManager {
590
703
  context: Omit<PluginHookContext, 'pluginId' | 'event'>,
591
704
  emitRunEvent?: (event: RunEvent) => Promise<void>,
592
705
  ): Promise<PluginHookResult[]> {
706
+ const callerSignal = context.signal
707
+ callerSignal?.throwIfAborted()
593
708
  const handlers = this.hookHandlers.get(event)
594
709
  if (!handlers || handlers.length === 0) {
595
710
  return []
@@ -634,6 +749,7 @@ export class PluginLifecycleManager {
634
749
  pluginId,
635
750
  hookEvent: event,
636
751
  })
752
+ callerSignal?.throwIfAborted()
637
753
  }
638
754
 
639
755
  const start = performance.now()
@@ -647,11 +763,15 @@ export class PluginLifecycleManager {
647
763
  // until the last one expired. Nothing failed — it just hung, for
648
764
  // up to the timeout, every time.
649
765
  const deadline = new AbortController()
766
+ const hookSignal = callerSignal
767
+ ? AbortSignal.any([callerSignal, deadline.signal])
768
+ : deadline.signal
650
769
  let timer: ReturnType<typeof setTimeout> | undefined
770
+ let onCallerAbort: (() => void) | undefined
651
771
 
652
772
  try {
653
- result = await Promise.race([
654
- handlerFn({ ...hookContext, signal: deadline.signal }),
773
+ const races: Promise<PluginHookResult>[] = [
774
+ Promise.resolve().then(() => handlerFn({ ...hookContext, signal: hookSignal })),
655
775
  new Promise<PluginHookResult>((_, reject) => {
656
776
  timer = setTimeout(() => {
657
777
  // Told, not just abandoned: a hook holding a socket
@@ -660,14 +780,33 @@ export class PluginLifecycleManager {
660
780
  reject(new Error('Hook timeout'))
661
781
  }, this.hookTimeoutMs)
662
782
  }),
663
- ])
783
+ ]
784
+ if (callerSignal) {
785
+ races.push(
786
+ new Promise<PluginHookResult>((_, reject) => {
787
+ onCallerAbort = () => reject(callerSignal.reason)
788
+ callerSignal.addEventListener('abort', onCallerAbort, {
789
+ once: true,
790
+ })
791
+ if (callerSignal.aborted) onCallerAbort()
792
+ }),
793
+ )
794
+ }
795
+ result = await Promise.race(races)
796
+ callerSignal?.throwIfAborted()
664
797
  } catch (err) {
798
+ // Cancellation belongs to the run, not to the plugin. Turning it
799
+ // into a hook error would let the query continue after its caller
800
+ // withdrew authority and would report Stop as a plugin failure.
801
+ if (callerSignal?.aborted) throw callerSignal.reason
665
802
  const message = toErrorMessage(err)
666
803
  result = { action: 'error', message }
667
804
  } finally {
668
805
  if (timer !== undefined) clearTimeout(timer)
806
+ if (onCallerAbort) callerSignal?.removeEventListener('abort', onCallerAbort)
669
807
  }
670
808
 
809
+ callerSignal?.throwIfAborted()
671
810
  const durationMs = Math.round(performance.now() - start)
672
811
 
673
812
  this.emit({
@@ -678,6 +817,7 @@ export class PluginLifecycleManager {
678
817
  })
679
818
 
680
819
  if (emitRunEvent) {
820
+ callerSignal?.throwIfAborted()
681
821
  await emitRunEvent({
682
822
  type: 'plugin_hook_completed',
683
823
  runId: context.runId,
@@ -685,6 +825,7 @@ export class PluginLifecycleManager {
685
825
  hookEvent: event,
686
826
  result,
687
827
  })
828
+ callerSignal?.throwIfAborted()
688
829
  }
689
830
 
690
831
  results.push(result)