@namzu/sdk 34.2.0 → 35.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 (637) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/README.md +2 -6
  3. package/dist/agents/PipelineAgent.d.ts.map +1 -1
  4. package/dist/agents/PipelineAgent.js +118 -100
  5. package/dist/agents/PipelineAgent.js.map +1 -1
  6. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  7. package/dist/agents/ReactiveAgent.js +2 -0
  8. package/dist/agents/ReactiveAgent.js.map +1 -1
  9. package/dist/agents/RouterAgent.d.ts.map +1 -1
  10. package/dist/agents/RouterAgent.js +105 -61
  11. package/dist/agents/RouterAgent.js.map +1 -1
  12. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  13. package/dist/agents/SupervisorAgent.js +8 -4
  14. package/dist/agents/SupervisorAgent.js.map +1 -1
  15. package/dist/agents/budget.d.ts +6 -0
  16. package/dist/agents/budget.d.ts.map +1 -0
  17. package/dist/agents/budget.js +33 -0
  18. package/dist/agents/budget.js.map +1 -0
  19. package/dist/agents/explore.d.ts +20 -0
  20. package/dist/agents/explore.d.ts.map +1 -0
  21. package/dist/agents/explore.js +26 -0
  22. package/dist/agents/explore.js.map +1 -0
  23. package/dist/agents/file-definitions.d.ts +80 -0
  24. package/dist/agents/file-definitions.d.ts.map +1 -0
  25. package/dist/agents/file-definitions.js +179 -0
  26. package/dist/agents/file-definitions.js.map +1 -0
  27. package/dist/agents/index.d.ts +3 -0
  28. package/dist/agents/index.d.ts.map +1 -1
  29. package/dist/agents/index.js +2 -0
  30. package/dist/agents/index.js.map +1 -1
  31. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  32. package/dist/bridge/a2a/mapper.js +6 -0
  33. package/dist/bridge/a2a/mapper.js.map +1 -1
  34. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  35. package/dist/bridge/sse/mapper.js +22 -0
  36. package/dist/bridge/sse/mapper.js.map +1 -1
  37. package/dist/bus/lock.d.ts.map +1 -1
  38. package/dist/bus/lock.js +1 -10
  39. package/dist/bus/lock.js.map +1 -1
  40. package/dist/compaction/consolidation.d.ts +31 -0
  41. package/dist/compaction/consolidation.d.ts.map +1 -0
  42. package/dist/compaction/consolidation.js +63 -0
  43. package/dist/compaction/consolidation.js.map +1 -0
  44. package/dist/compaction/factory.d.ts.map +1 -1
  45. package/dist/compaction/factory.js +3 -0
  46. package/dist/compaction/factory.js.map +1 -1
  47. package/dist/compaction/index.d.ts +6 -1
  48. package/dist/compaction/index.d.ts.map +1 -1
  49. package/dist/compaction/index.js +6 -0
  50. package/dist/compaction/index.js.map +1 -1
  51. package/dist/compaction/manager.d.ts +7 -0
  52. package/dist/compaction/manager.d.ts.map +1 -1
  53. package/dist/compaction/manager.js +31 -0
  54. package/dist/compaction/manager.js.map +1 -1
  55. package/dist/compaction/plan.d.ts +23 -0
  56. package/dist/compaction/plan.d.ts.map +1 -1
  57. package/dist/compaction/plan.js +41 -24
  58. package/dist/compaction/plan.js.map +1 -1
  59. package/dist/compaction/salience/bm25.d.ts +26 -0
  60. package/dist/compaction/salience/bm25.d.ts.map +1 -0
  61. package/dist/compaction/salience/bm25.js +56 -0
  62. package/dist/compaction/salience/bm25.js.map +1 -0
  63. package/dist/compaction/salience/goal.d.ts +21 -0
  64. package/dist/compaction/salience/goal.d.ts.map +1 -0
  65. package/dist/compaction/salience/goal.js +32 -0
  66. package/dist/compaction/salience/goal.js.map +1 -0
  67. package/dist/compaction/salience/index.d.ts +4 -0
  68. package/dist/compaction/salience/index.d.ts.map +1 -0
  69. package/dist/compaction/salience/index.js +4 -0
  70. package/dist/compaction/salience/index.js.map +1 -0
  71. package/dist/compaction/salience/minhash.d.ts +17 -0
  72. package/dist/compaction/salience/minhash.d.ts.map +1 -0
  73. package/dist/compaction/salience/minhash.js +54 -0
  74. package/dist/compaction/salience/minhash.js.map +1 -0
  75. package/dist/compaction/salience/score.d.ts +64 -0
  76. package/dist/compaction/salience/score.d.ts.map +1 -0
  77. package/dist/compaction/salience/score.js +256 -0
  78. package/dist/compaction/salience/score.js.map +1 -0
  79. package/dist/compaction/salience/tokenize.d.ts +20 -0
  80. package/dist/compaction/salience/tokenize.d.ts.map +1 -0
  81. package/dist/compaction/salience/tokenize.js +92 -0
  82. package/dist/compaction/salience/tokenize.js.map +1 -0
  83. package/dist/compaction/salience/working-set.d.ts +59 -0
  84. package/dist/compaction/salience/working-set.d.ts.map +1 -0
  85. package/dist/compaction/salience/working-set.js +137 -0
  86. package/dist/compaction/salience/working-set.js.map +1 -0
  87. package/dist/compaction/serializer.d.ts +2 -0
  88. package/dist/compaction/serializer.d.ts.map +1 -1
  89. package/dist/compaction/serializer.js +15 -0
  90. package/dist/compaction/serializer.js.map +1 -1
  91. package/dist/compaction/token-estimate.d.ts +13 -0
  92. package/dist/compaction/token-estimate.d.ts.map +1 -0
  93. package/dist/compaction/token-estimate.js +58 -0
  94. package/dist/compaction/token-estimate.js.map +1 -0
  95. package/dist/compaction/tool-result-editing.d.ts +10 -2
  96. package/dist/compaction/tool-result-editing.d.ts.map +1 -1
  97. package/dist/compaction/tool-result-editing.js +22 -24
  98. package/dist/compaction/tool-result-editing.js.map +1 -1
  99. package/dist/compaction/types.d.ts +22 -1
  100. package/dist/compaction/types.d.ts.map +1 -1
  101. package/dist/compaction/wire.d.ts +3 -1
  102. package/dist/compaction/wire.d.ts.map +1 -1
  103. package/dist/compaction/wire.js +2 -0
  104. package/dist/compaction/wire.js.map +1 -1
  105. package/dist/config/runtime.d.ts +58 -28
  106. package/dist/config/runtime.d.ts.map +1 -1
  107. package/dist/config/runtime.js +13 -1
  108. package/dist/config/runtime.js.map +1 -1
  109. package/dist/connector/builtins/http.d.ts.map +1 -1
  110. package/dist/connector/builtins/http.js +2 -8
  111. package/dist/connector/builtins/http.js.map +1 -1
  112. package/dist/connector/builtins/webhook.js +2 -2
  113. package/dist/connector/builtins/webhook.js.map +1 -1
  114. package/dist/connector/mcp/adapter.d.ts +2 -0
  115. package/dist/connector/mcp/adapter.d.ts.map +1 -1
  116. package/dist/connector/mcp/adapter.js +30 -0
  117. package/dist/connector/mcp/adapter.js.map +1 -1
  118. package/dist/connector/tools/adapter.js +2 -2
  119. package/dist/connector/tools/adapter.js.map +1 -1
  120. package/dist/connector/tools/definitions.js +2 -2
  121. package/dist/connector/tools/definitions.js.map +1 -1
  122. package/dist/constants/compaction/index.d.ts +1 -0
  123. package/dist/constants/compaction/index.d.ts.map +1 -1
  124. package/dist/constants/compaction/index.js +1 -0
  125. package/dist/constants/compaction/index.js.map +1 -1
  126. package/dist/constants/telemetry/index.d.ts +0 -1
  127. package/dist/constants/telemetry/index.d.ts.map +1 -1
  128. package/dist/constants/telemetry/index.js +0 -1
  129. package/dist/constants/telemetry/index.js.map +1 -1
  130. package/dist/contracts/a2a.d.ts +5 -5
  131. package/dist/contracts/api.d.ts +4 -2
  132. package/dist/contracts/api.d.ts.map +1 -1
  133. package/dist/contracts/schemas.d.ts +1 -15
  134. package/dist/contracts/schemas.d.ts.map +1 -1
  135. package/dist/contracts/schemas.js +5 -20
  136. package/dist/contracts/schemas.js.map +1 -1
  137. package/dist/invariants/index.d.ts +1 -1
  138. package/dist/manager/agent/lifecycle.d.ts +2 -18
  139. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  140. package/dist/manager/agent/lifecycle.js +373 -340
  141. package/dist/manager/agent/lifecycle.js.map +1 -1
  142. package/dist/manager/run/persistence.d.ts +3 -0
  143. package/dist/manager/run/persistence.d.ts.map +1 -1
  144. package/dist/manager/run/persistence.js +35 -5
  145. package/dist/manager/run/persistence.js.map +1 -1
  146. package/dist/plugin/index.d.ts +2 -0
  147. package/dist/plugin/index.d.ts.map +1 -1
  148. package/dist/plugin/index.js +1 -0
  149. package/dist/plugin/index.js.map +1 -1
  150. package/dist/plugin/shell-hook.d.ts +128 -0
  151. package/dist/plugin/shell-hook.d.ts.map +1 -0
  152. package/dist/plugin/shell-hook.js +299 -0
  153. package/dist/plugin/shell-hook.js.map +1 -0
  154. package/dist/prompt/coding-agent-doctrine.d.ts +63 -0
  155. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -0
  156. package/dist/prompt/coding-agent-doctrine.js +100 -0
  157. package/dist/prompt/coding-agent-doctrine.js.map +1 -0
  158. package/dist/prompt/index.d.ts +2 -0
  159. package/dist/prompt/index.d.ts.map +1 -1
  160. package/dist/prompt/index.js +1 -0
  161. package/dist/prompt/index.js.map +1 -1
  162. package/dist/provider/errors.d.ts +1 -1
  163. package/dist/provider/errors.js +1 -1
  164. package/dist/provider/fallback.d.ts +2 -0
  165. package/dist/provider/fallback.d.ts.map +1 -1
  166. package/dist/provider/fallback.js +3 -1
  167. package/dist/provider/fallback.js.map +1 -1
  168. package/dist/provider/retry.d.ts +2 -0
  169. package/dist/provider/retry.d.ts.map +1 -1
  170. package/dist/provider/retry.js +3 -1
  171. package/dist/provider/retry.js.map +1 -1
  172. package/dist/provider/token-budget.d.ts +13 -0
  173. package/dist/provider/token-budget.d.ts.map +1 -0
  174. package/dist/provider/token-budget.js +102 -0
  175. package/dist/provider/token-budget.js.map +1 -0
  176. package/dist/public-runtime.d.ts +12 -12
  177. package/dist/public-runtime.d.ts.map +1 -1
  178. package/dist/public-runtime.js +14 -9
  179. package/dist/public-runtime.js.map +1 -1
  180. package/dist/public-tools.d.ts +2 -0
  181. package/dist/public-tools.d.ts.map +1 -1
  182. package/dist/public-tools.js +2 -0
  183. package/dist/public-tools.js.map +1 -1
  184. package/dist/public-types.d.ts +12 -2
  185. package/dist/public-types.d.ts.map +1 -1
  186. package/dist/registry/command/kernel-commands.d.ts.map +1 -1
  187. package/dist/registry/command/kernel-commands.js +18 -6
  188. package/dist/registry/command/kernel-commands.js.map +1 -1
  189. package/dist/registry/tool/execute.d.ts.map +1 -1
  190. package/dist/registry/tool/execute.js +4 -1
  191. package/dist/registry/tool/execute.js.map +1 -1
  192. package/dist/run/LimitChecker.js +1 -1
  193. package/dist/run/LimitChecker.js.map +1 -1
  194. package/dist/run/drain.js +1 -1
  195. package/dist/run/reporter.d.ts.map +1 -1
  196. package/dist/run/reporter.js +15 -0
  197. package/dist/run/reporter.js.map +1 -1
  198. package/dist/run/token-budget.d.ts +108 -0
  199. package/dist/run/token-budget.d.ts.map +1 -0
  200. package/dist/run/token-budget.js +591 -0
  201. package/dist/run/token-budget.js.map +1 -0
  202. package/dist/runtime/jobs/registry.d.ts +29 -0
  203. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  204. package/dist/runtime/jobs/registry.js +98 -18
  205. package/dist/runtime/jobs/registry.js.map +1 -1
  206. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  207. package/dist/runtime/query/checkpoint.js +10 -3
  208. package/dist/runtime/query/checkpoint.js.map +1 -1
  209. package/dist/runtime/query/context.d.ts +2 -26
  210. package/dist/runtime/query/context.d.ts.map +1 -1
  211. package/dist/runtime/query/context.js +1 -29
  212. package/dist/runtime/query/context.js.map +1 -1
  213. package/dist/runtime/query/executor.d.ts +12 -9
  214. package/dist/runtime/query/executor.d.ts.map +1 -1
  215. package/dist/runtime/query/executor.js +95 -46
  216. package/dist/runtime/query/executor.js.map +1 -1
  217. package/dist/runtime/query/guard.d.ts.map +1 -1
  218. package/dist/runtime/query/guard.js +8 -0
  219. package/dist/runtime/query/guard.js.map +1 -1
  220. package/dist/runtime/query/index.d.ts +35 -4
  221. package/dist/runtime/query/index.d.ts.map +1 -1
  222. package/dist/runtime/query/index.js +152 -52
  223. package/dist/runtime/query/index.js.map +1 -1
  224. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  225. package/dist/runtime/query/iteration/index.js +16 -5
  226. package/dist/runtime/query/iteration/index.js.map +1 -1
  227. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  228. package/dist/runtime/query/iteration/phases/compaction.js +98 -30
  229. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  230. package/dist/runtime/query/iteration/phases/context.d.ts +2 -0
  231. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  232. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  233. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  234. package/dist/runtime/query/iteration/phases/tool-review.js +29 -7
  235. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  236. package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -1
  237. package/dist/runtime/query/iteration/phases/working-memory.js +25 -15
  238. package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -1
  239. package/dist/runtime/query/plugin-hooks.d.ts +1 -1
  240. package/dist/runtime/query/plugin-hooks.d.ts.map +1 -1
  241. package/dist/runtime/query/plugin-hooks.js +20 -1
  242. package/dist/runtime/query/plugin-hooks.js.map +1 -1
  243. package/dist/runtime/query/repeat-call.d.ts +20 -2
  244. package/dist/runtime/query/repeat-call.d.ts.map +1 -1
  245. package/dist/runtime/query/repeat-call.js +35 -7
  246. package/dist/runtime/query/repeat-call.js.map +1 -1
  247. package/dist/runtime/query/result.d.ts.map +1 -1
  248. package/dist/runtime/query/result.js +9 -0
  249. package/dist/runtime/query/result.js.map +1 -1
  250. package/dist/runtime/query/review-policy.d.ts +142 -0
  251. package/dist/runtime/query/review-policy.d.ts.map +1 -0
  252. package/dist/runtime/query/review-policy.js +144 -0
  253. package/dist/runtime/query/review-policy.js.map +1 -0
  254. package/dist/runtime/query/run-state.d.ts.map +1 -1
  255. package/dist/runtime/query/run-state.js +4 -0
  256. package/dist/runtime/query/run-state.js.map +1 -1
  257. package/dist/runtime/query/steering.d.ts +4 -0
  258. package/dist/runtime/query/steering.d.ts.map +1 -1
  259. package/dist/runtime/query/steering.js +29 -0
  260. package/dist/runtime/query/steering.js.map +1 -1
  261. package/dist/runtime/query/token-budget.d.ts +7 -0
  262. package/dist/runtime/query/token-budget.d.ts.map +1 -0
  263. package/dist/runtime/query/token-budget.js +101 -0
  264. package/dist/runtime/query/token-budget.js.map +1 -0
  265. package/dist/runtime/query/tool-output-budget.d.ts +2 -0
  266. package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
  267. package/dist/runtime/query/tool-output-budget.js +29 -11
  268. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  269. package/dist/runtime/query/tool-pause.d.ts.map +1 -1
  270. package/dist/runtime/query/tool-pause.js +4 -2
  271. package/dist/runtime/query/tool-pause.js.map +1 -1
  272. package/dist/runtime/query/tooling.d.ts +4 -0
  273. package/dist/runtime/query/tooling.d.ts.map +1 -1
  274. package/dist/runtime/query/tooling.js +4 -0
  275. package/dist/runtime/query/tooling.js.map +1 -1
  276. package/dist/sandbox/provider/local.d.ts +3 -1
  277. package/dist/sandbox/provider/local.d.ts.map +1 -1
  278. package/dist/sandbox/provider/local.js +112 -12
  279. package/dist/sandbox/provider/local.js.map +1 -1
  280. package/dist/scheduler/delegating.d.ts +1 -0
  281. package/dist/scheduler/delegating.d.ts.map +1 -1
  282. package/dist/scheduler/delegating.js +29 -12
  283. package/dist/scheduler/delegating.js.map +1 -1
  284. package/dist/scheduler/local.d.ts +1 -0
  285. package/dist/scheduler/local.d.ts.map +1 -1
  286. package/dist/scheduler/local.js +4 -7
  287. package/dist/scheduler/local.js.map +1 -1
  288. package/dist/session/index.d.ts +0 -1
  289. package/dist/session/index.d.ts.map +1 -1
  290. package/dist/session/index.js +0 -1
  291. package/dist/session/index.js.map +1 -1
  292. package/dist/session/workspace/path-builder.d.ts.map +1 -1
  293. package/dist/session/workspace/path-builder.js +5 -4
  294. package/dist/session/workspace/path-builder.js.map +1 -1
  295. package/dist/store/feedback/disk.d.ts.map +1 -1
  296. package/dist/store/feedback/disk.js +4 -6
  297. package/dist/store/feedback/disk.js.map +1 -1
  298. package/dist/store/index.d.ts +2 -0
  299. package/dist/store/index.d.ts.map +1 -1
  300. package/dist/store/index.js +1 -0
  301. package/dist/store/index.js.map +1 -1
  302. package/dist/store/memory/disk.d.ts.map +1 -1
  303. package/dist/store/memory/disk.js +3 -12
  304. package/dist/store/memory/disk.js.map +1 -1
  305. package/dist/store/run/checkpoint-disk.d.ts +3 -3
  306. package/dist/store/run/checkpoint-disk.d.ts.map +1 -1
  307. package/dist/store/run/checkpoint-disk.js +14 -26
  308. package/dist/store/run/checkpoint-disk.js.map +1 -1
  309. package/dist/store/run/claim-disk.js +1 -1
  310. package/dist/store/run/conformance.d.ts +1 -1
  311. package/dist/store/run/conformance.d.ts.map +1 -1
  312. package/dist/store/run/conformance.js +41 -33
  313. package/dist/store/run/conformance.js.map +1 -1
  314. package/dist/store/run/disk.d.ts.map +1 -1
  315. package/dist/store/run/disk.js +20 -4
  316. package/dist/store/run/disk.js.map +1 -1
  317. package/dist/store/run/token-budget-disk.d.ts +37 -0
  318. package/dist/store/run/token-budget-disk.d.ts.map +1 -0
  319. package/dist/store/run/token-budget-disk.js +208 -0
  320. package/dist/store/run/token-budget-disk.js.map +1 -0
  321. package/dist/store/session/disk.d.ts +4 -13
  322. package/dist/store/session/disk.d.ts.map +1 -1
  323. package/dist/store/session/disk.js +34 -31
  324. package/dist/store/session/disk.js.map +1 -1
  325. package/dist/store/session/memory.d.ts +2 -0
  326. package/dist/store/session/memory.d.ts.map +1 -1
  327. package/dist/store/session/memory.js +41 -2
  328. package/dist/store/session/memory.js.map +1 -1
  329. package/dist/store/task/disk.d.ts.map +1 -1
  330. package/dist/store/task/disk.js +7 -8
  331. package/dist/store/task/disk.js.map +1 -1
  332. package/dist/store/topic/memory.d.ts +2 -0
  333. package/dist/store/topic/memory.d.ts.map +1 -1
  334. package/dist/store/topic/memory.js +13 -1
  335. package/dist/store/topic/memory.js.map +1 -1
  336. package/dist/test-support/ids.d.ts +4 -19
  337. package/dist/test-support/ids.d.ts.map +1 -1
  338. package/dist/test-support/ids.js +51 -59
  339. package/dist/test-support/ids.js.map +1 -1
  340. package/dist/tools/advisory/index.d.ts.map +1 -1
  341. package/dist/tools/advisory/index.js +3 -1
  342. package/dist/tools/advisory/index.js.map +1 -1
  343. package/dist/tools/builtins/bash.d.ts +2 -0
  344. package/dist/tools/builtins/bash.d.ts.map +1 -1
  345. package/dist/tools/builtins/bash.js +9 -11
  346. package/dist/tools/builtins/bash.js.map +1 -1
  347. package/dist/tools/builtins/computer-use.d.ts +2 -2
  348. package/dist/tools/builtins/computer-use.d.ts.map +1 -1
  349. package/dist/tools/builtins/computer-use.js +4 -2
  350. package/dist/tools/builtins/computer-use.js.map +1 -1
  351. package/dist/tools/builtins/edit.js +2 -2
  352. package/dist/tools/builtins/edit.js.map +1 -1
  353. package/dist/tools/builtins/glob.js +3 -3
  354. package/dist/tools/builtins/glob.js.map +1 -1
  355. package/dist/tools/builtins/grep.js +2 -2
  356. package/dist/tools/builtins/grep.js.map +1 -1
  357. package/dist/tools/builtins/ls.js +2 -2
  358. package/dist/tools/builtins/ls.js.map +1 -1
  359. package/dist/tools/builtins/lsp.js +2 -2
  360. package/dist/tools/builtins/lsp.js.map +1 -1
  361. package/dist/tools/builtins/read-file.js +2 -2
  362. package/dist/tools/builtins/read-file.js.map +1 -1
  363. package/dist/tools/builtins/write-file.js +2 -2
  364. package/dist/tools/builtins/write-file.js.map +1 -1
  365. package/dist/tools/coordinator/ask-user-question.d.ts +33 -0
  366. package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -0
  367. package/dist/tools/coordinator/ask-user-question.js +237 -0
  368. package/dist/tools/coordinator/ask-user-question.js.map +1 -0
  369. package/dist/tools/coordinator/index.d.ts +1 -2
  370. package/dist/tools/coordinator/index.d.ts.map +1 -1
  371. package/dist/tools/coordinator/index.js +4 -220
  372. package/dist/tools/coordinator/index.js.map +1 -1
  373. package/dist/tools/memory/read.d.ts.map +1 -1
  374. package/dist/tools/memory/read.js +2 -4
  375. package/dist/tools/memory/read.js.map +1 -1
  376. package/dist/tools/paths.d.ts +13 -0
  377. package/dist/tools/paths.d.ts.map +1 -1
  378. package/dist/tools/paths.js +53 -0
  379. package/dist/tools/paths.js.map +1 -1
  380. package/dist/tools/roster.d.ts +27 -0
  381. package/dist/tools/roster.d.ts.map +1 -0
  382. package/dist/tools/roster.js +42 -0
  383. package/dist/tools/roster.js.map +1 -0
  384. package/dist/types/agent/base.d.ts +5 -0
  385. package/dist/types/agent/base.d.ts.map +1 -1
  386. package/dist/types/agent/pipeline.d.ts +3 -0
  387. package/dist/types/agent/pipeline.d.ts.map +1 -1
  388. package/dist/types/agent/router.d.ts +2 -3
  389. package/dist/types/agent/router.d.ts.map +1 -1
  390. package/dist/types/agent/scheduler.d.ts +3 -0
  391. package/dist/types/agent/scheduler.d.ts.map +1 -1
  392. package/dist/types/agent/task.d.ts +5 -16
  393. package/dist/types/agent/task.d.ts.map +1 -1
  394. package/dist/types/agent/task.js.map +1 -1
  395. package/dist/types/common/index.d.ts.map +1 -1
  396. package/dist/types/common/index.js +3 -0
  397. package/dist/types/common/index.js.map +1 -1
  398. package/dist/types/computer-use/index.d.ts +8 -0
  399. package/dist/types/computer-use/index.d.ts.map +1 -1
  400. package/dist/types/computer-use/index.js.map +1 -1
  401. package/dist/types/hitl/index.d.ts +5 -0
  402. package/dist/types/hitl/index.d.ts.map +1 -1
  403. package/dist/types/hitl/index.js.map +1 -1
  404. package/dist/types/ids/brand.d.ts +5 -47
  405. package/dist/types/ids/brand.d.ts.map +1 -1
  406. package/dist/types/ids/brand.js +2 -39
  407. package/dist/types/ids/brand.js.map +1 -1
  408. package/dist/types/ids/index.d.ts +59 -69
  409. package/dist/types/ids/index.d.ts.map +1 -1
  410. package/dist/types/ids/index.js +12 -10
  411. package/dist/types/ids/index.js.map +1 -1
  412. package/dist/types/permission/index.d.ts +9 -0
  413. package/dist/types/permission/index.d.ts.map +1 -1
  414. package/dist/types/permission/index.js +9 -1
  415. package/dist/types/permission/index.js.map +1 -1
  416. package/dist/types/plugin/index.d.ts +45 -4
  417. package/dist/types/plugin/index.d.ts.map +1 -1
  418. package/dist/types/plugin/index.js +7 -0
  419. package/dist/types/plugin/index.js.map +1 -1
  420. package/dist/types/run/config.d.ts +3 -0
  421. package/dist/types/run/config.d.ts.map +1 -1
  422. package/dist/types/run/emergency.d.ts +5 -0
  423. package/dist/types/run/emergency.d.ts.map +1 -1
  424. package/dist/types/run/emergency.js.map +1 -1
  425. package/dist/types/run/entity.d.ts +6 -2
  426. package/dist/types/run/entity.d.ts.map +1 -1
  427. package/dist/types/run/events.d.ts +35 -0
  428. package/dist/types/run/events.d.ts.map +1 -1
  429. package/dist/types/run/events.js.map +1 -1
  430. package/dist/types/run/index.d.ts +1 -0
  431. package/dist/types/run/index.d.ts.map +1 -1
  432. package/dist/types/run/index.js +1 -0
  433. package/dist/types/run/index.js.map +1 -1
  434. package/dist/types/run/state.d.ts +16 -15
  435. package/dist/types/run/state.d.ts.map +1 -1
  436. package/dist/types/run/state.js +41 -22
  437. package/dist/types/run/state.js.map +1 -1
  438. package/dist/types/run/stop-reason.d.ts +3 -14
  439. package/dist/types/run/stop-reason.d.ts.map +1 -1
  440. package/dist/types/run/token-budget-store.d.ts +29 -0
  441. package/dist/types/run/token-budget-store.d.ts.map +1 -0
  442. package/dist/types/run/token-budget-store.js +25 -0
  443. package/dist/types/run/token-budget-store.js.map +1 -0
  444. package/dist/types/sandbox/index.d.ts +27 -2
  445. package/dist/types/sandbox/index.d.ts.map +1 -1
  446. package/dist/types/sandbox/index.js.map +1 -1
  447. package/dist/types/session/store.d.ts +8 -0
  448. package/dist/types/session/store.d.ts.map +1 -1
  449. package/dist/types/tool/index.d.ts +15 -0
  450. package/dist/types/tool/index.d.ts.map +1 -1
  451. package/dist/types/tool/index.js.map +1 -1
  452. package/dist/utils/frontmatter.d.ts +1 -1
  453. package/dist/utils/frontmatter.js +1 -1
  454. package/dist/utils/id-format.d.ts +3 -0
  455. package/dist/utils/id-format.d.ts.map +1 -0
  456. package/dist/utils/id-format.js +9 -0
  457. package/dist/utils/id-format.js.map +1 -0
  458. package/dist/utils/id.d.ts +65 -32
  459. package/dist/utils/id.d.ts.map +1 -1
  460. package/dist/utils/id.js +168 -148
  461. package/dist/utils/id.js.map +1 -1
  462. package/dist/utils/log/exception.js +1 -1
  463. package/dist/utils/log/exception.js.map +1 -1
  464. package/dist/utils/log/index.d.ts.map +1 -1
  465. package/dist/utils/log/index.js +1 -2
  466. package/dist/utils/log/index.js.map +1 -1
  467. package/dist/utils/log/templates.d.ts.map +1 -1
  468. package/dist/utils/log/templates.js +0 -1
  469. package/dist/utils/log/templates.js.map +1 -1
  470. package/package.json +1 -1
  471. package/src/agents/AGENTS.md +1 -1
  472. package/src/agents/PipelineAgent.ts +129 -109
  473. package/src/agents/ReactiveAgent.ts +2 -0
  474. package/src/agents/RouterAgent.ts +120 -73
  475. package/src/agents/SupervisorAgent.ts +12 -4
  476. package/src/agents/budget.ts +42 -0
  477. package/src/agents/explore.ts +29 -0
  478. package/src/agents/file-definitions.ts +237 -0
  479. package/src/agents/index.ts +15 -0
  480. package/src/bridge/a2a/mapper.ts +6 -0
  481. package/src/bridge/sse/mapper.ts +22 -0
  482. package/src/bus/lock.ts +1 -10
  483. package/src/compaction/consolidation.ts +79 -0
  484. package/src/compaction/factory.ts +3 -0
  485. package/src/compaction/index.ts +34 -4
  486. package/src/compaction/manager.ts +39 -1
  487. package/src/compaction/plan.ts +52 -21
  488. package/src/compaction/salience/bm25.ts +72 -0
  489. package/src/compaction/salience/goal.ts +44 -0
  490. package/src/compaction/salience/index.ts +19 -0
  491. package/src/compaction/salience/minhash.ts +53 -0
  492. package/src/compaction/salience/score.ts +305 -0
  493. package/src/compaction/salience/tokenize.ts +89 -0
  494. package/src/compaction/salience/working-set.ts +187 -0
  495. package/src/compaction/serializer.ts +16 -0
  496. package/src/compaction/token-estimate.ts +57 -0
  497. package/src/compaction/tool-result-editing.ts +28 -26
  498. package/src/compaction/types.ts +24 -1
  499. package/src/compaction/wire.ts +5 -1
  500. package/src/config/runtime.ts +13 -1
  501. package/src/connector/builtins/http.ts +2 -8
  502. package/src/connector/builtins/webhook.ts +2 -2
  503. package/src/connector/mcp/adapter.ts +32 -0
  504. package/src/connector/tools/adapter.ts +2 -2
  505. package/src/connector/tools/definitions.ts +2 -2
  506. package/src/constants/compaction/index.ts +1 -0
  507. package/src/constants/telemetry/index.ts +0 -1
  508. package/src/contracts/api.ts +5 -1
  509. package/src/contracts/schemas.ts +6 -20
  510. package/src/invariants/index.ts +1 -1
  511. package/src/manager/agent/lifecycle.ts +380 -352
  512. package/src/manager/run/persistence.ts +35 -5
  513. package/src/plugin/index.ts +19 -0
  514. package/src/plugin/shell-hook.ts +403 -0
  515. package/src/prompt/coding-agent-doctrine.ts +118 -0
  516. package/src/prompt/index.ts +8 -0
  517. package/src/provider/errors.ts +1 -1
  518. package/src/provider/fallback.ts +4 -1
  519. package/src/provider/retry.ts +4 -1
  520. package/src/provider/token-budget.ts +114 -0
  521. package/src/public-runtime.ts +54 -27
  522. package/src/public-tools.ts +5 -0
  523. package/src/public-types.ts +65 -0
  524. package/src/registry/command/kernel-commands.ts +16 -6
  525. package/src/registry/tool/execute.ts +4 -1
  526. package/src/run/LimitChecker.ts +1 -1
  527. package/src/run/drain.ts +1 -1
  528. package/src/run/reporter.ts +15 -0
  529. package/src/run/token-budget.ts +692 -0
  530. package/src/runtime/jobs/registry.ts +123 -17
  531. package/src/runtime/query/checkpoint.ts +10 -3
  532. package/src/runtime/query/context.ts +3 -57
  533. package/src/runtime/query/executor.ts +128 -58
  534. package/src/runtime/query/guard.ts +8 -0
  535. package/src/runtime/query/index.ts +201 -62
  536. package/src/runtime/query/iteration/index.ts +24 -6
  537. package/src/runtime/query/iteration/phases/compaction.ts +130 -31
  538. package/src/runtime/query/iteration/phases/context.ts +2 -0
  539. package/src/runtime/query/iteration/phases/tool-review.ts +39 -7
  540. package/src/runtime/query/iteration/phases/working-memory.ts +23 -14
  541. package/src/runtime/query/plugin-hooks.ts +24 -2
  542. package/src/runtime/query/repeat-call.ts +42 -7
  543. package/src/runtime/query/result.ts +9 -0
  544. package/src/runtime/query/review-policy.ts +231 -0
  545. package/src/runtime/query/run-state.ts +4 -0
  546. package/src/runtime/query/steering.ts +32 -0
  547. package/src/runtime/query/token-budget.ts +127 -0
  548. package/src/runtime/query/tool-output-budget.ts +33 -10
  549. package/src/runtime/query/tool-pause.ts +4 -2
  550. package/src/runtime/query/tooling.ts +8 -0
  551. package/src/sandbox/provider/local.ts +123 -13
  552. package/src/scheduler/delegating.ts +35 -13
  553. package/src/scheduler/local.ts +5 -7
  554. package/src/session/index.ts +0 -1
  555. package/src/session/workspace/path-builder.ts +5 -4
  556. package/src/store/feedback/disk.ts +4 -6
  557. package/src/store/index.ts +2 -0
  558. package/src/store/memory/disk.ts +3 -11
  559. package/src/store/run/checkpoint-disk.ts +14 -27
  560. package/src/store/run/claim-disk.ts +1 -1
  561. package/src/store/run/conformance.ts +55 -39
  562. package/src/store/run/disk.ts +19 -4
  563. package/src/store/run/token-budget-disk.ts +247 -0
  564. package/src/store/session/disk.ts +36 -29
  565. package/src/store/session/memory.ts +38 -1
  566. package/src/store/task/disk.ts +7 -8
  567. package/src/store/topic/memory.ts +13 -1
  568. package/src/test-support/ids.ts +62 -59
  569. package/src/tools/advisory/index.ts +3 -1
  570. package/src/tools/builtins/bash.ts +11 -12
  571. package/src/tools/builtins/computer-use.ts +6 -2
  572. package/src/tools/builtins/edit.ts +2 -2
  573. package/src/tools/builtins/glob.ts +3 -3
  574. package/src/tools/builtins/grep.ts +2 -2
  575. package/src/tools/builtins/ls.ts +2 -2
  576. package/src/tools/builtins/lsp.ts +2 -2
  577. package/src/tools/builtins/read-file.ts +2 -2
  578. package/src/tools/builtins/write-file.ts +2 -2
  579. package/src/tools/coordinator/ask-user-question.ts +284 -0
  580. package/src/tools/coordinator/index.ts +5 -248
  581. package/src/tools/memory/read.ts +2 -4
  582. package/src/tools/paths.ts +64 -0
  583. package/src/tools/roster.ts +46 -0
  584. package/src/types/agent/base.ts +6 -0
  585. package/src/types/agent/pipeline.ts +3 -0
  586. package/src/types/agent/router.ts +2 -3
  587. package/src/types/agent/scheduler.ts +4 -0
  588. package/src/types/agent/task.ts +5 -18
  589. package/src/types/common/index.ts +3 -0
  590. package/src/types/computer-use/index.ts +8 -0
  591. package/src/types/hitl/index.ts +5 -0
  592. package/src/types/ids/brand.ts +5 -48
  593. package/src/types/ids/index.ts +66 -75
  594. package/src/types/permission/index.ts +11 -0
  595. package/src/types/plugin/index.ts +49 -1
  596. package/src/types/run/config.ts +3 -0
  597. package/src/types/run/emergency.ts +5 -0
  598. package/src/types/run/entity.ts +6 -2
  599. package/src/types/run/events.ts +37 -0
  600. package/src/types/run/index.ts +1 -0
  601. package/src/types/run/state.ts +58 -30
  602. package/src/types/run/stop-reason.ts +3 -14
  603. package/src/types/run/token-budget-store.ts +54 -0
  604. package/src/types/sandbox/index.ts +32 -0
  605. package/src/types/session/store.ts +8 -0
  606. package/src/types/tool/index.ts +15 -0
  607. package/src/utils/frontmatter.ts +1 -1
  608. package/src/utils/id-format.ts +9 -0
  609. package/src/utils/id.ts +222 -181
  610. package/src/utils/log/exception.ts +1 -1
  611. package/src/utils/log/index.ts +1 -2
  612. package/src/utils/log/templates.ts +0 -1
  613. package/dist/session/migration/errors.d.ts +0 -26
  614. package/dist/session/migration/errors.d.ts.map +0 -1
  615. package/dist/session/migration/errors.js +0 -22
  616. package/dist/session/migration/errors.js.map +0 -1
  617. package/dist/session/migration/filesystem.d.ts +0 -122
  618. package/dist/session/migration/filesystem.d.ts.map +0 -1
  619. package/dist/session/migration/filesystem.js +0 -379
  620. package/dist/session/migration/filesystem.js.map +0 -1
  621. package/dist/session/migration/id-prefix.d.ts +0 -113
  622. package/dist/session/migration/id-prefix.d.ts.map +0 -1
  623. package/dist/session/migration/id-prefix.js +0 -132
  624. package/dist/session/migration/id-prefix.js.map +0 -1
  625. package/dist/session/migration/index.d.ts +0 -12
  626. package/dist/session/migration/index.d.ts.map +0 -1
  627. package/dist/session/migration/index.js +0 -12
  628. package/dist/session/migration/index.js.map +0 -1
  629. package/dist/session/migration/marker.d.ts +0 -57
  630. package/dist/session/migration/marker.d.ts.map +0 -1
  631. package/dist/session/migration/marker.js +0 -123
  632. package/dist/session/migration/marker.js.map +0 -1
  633. package/src/session/migration/errors.ts +0 -23
  634. package/src/session/migration/filesystem.ts +0 -468
  635. package/src/session/migration/id-prefix.ts +0 -166
  636. package/src/session/migration/index.ts +0 -41
  637. package/src/session/migration/marker.ts +0 -142
@@ -53,10 +53,15 @@ import type {
53
53
  SessionSummaryRef,
54
54
  } from '../../types/summary/ref.js'
55
55
  import {
56
+ asProjectId,
57
+ asSessionId,
58
+ asSubSessionId,
59
+ asTopicId,
56
60
  generateMessageId,
57
61
  generateProjectId,
58
62
  generateSessionId,
59
63
  generateSubSessionId,
64
+ isEntityId,
60
65
  } from '../../utils/id.js'
61
66
  import { DiskRecordStore } from '../kv/record-store.js'
62
67
  import {
@@ -151,26 +156,19 @@ const rootPathBindings = new DiskRevisionRecordStore<RootPathBinding>(
151
156
  )
152
157
 
153
158
  /**
154
- * v2 v3: NZ-TOPIC-04 narrows the Topic id prefix from `thd_` to `top_`.
155
- * The FIELD is already `topicId` (the v1→v2 step above handled that); this
156
- * step rewrites only the VALUE, and only when it still carries the old
157
- * prefix — a record already at v3, or one that just arrived here via the
158
- * v1→v2 step in the same `migrate()` call, has `topicId` starting `top_`
159
- * (or `thd_`, freshly renamed from `threadId` — this step runs on it next
160
- * in the same pass) either way, and the check below is what makes running
161
- * it on an already-correct value a same-object no-op rather than a
162
- * needless copy. Same one-function-runs-over-every-kind shape as its
163
- * v1→v2 sibling: only `PersistedSession.topicId` is ever `thd_`-prefixed,
164
- * so every other kind this schema stamps (project.json, subsession.json,
165
- * summary.json, each messages.jsonl line) has no `topicId` key and comes
166
- * back untouched.
159
+ * Validate topic UUIDs before accepting a stored record. Prefixed IDs are
160
+ * rejected without rewriting stored references.
161
+ * This migrator runs over every session-store record kind; records without
162
+ * a topicId are intentionally untouched.
167
163
  */
168
164
  export function migrateSessionStoreTopicIdPrefix(
169
165
  record: Record<string, unknown>,
170
166
  ): Record<string, unknown> {
171
167
  const topicId = record.topicId
172
- if (typeof topicId !== 'string' || !topicId.startsWith('thd_')) return record
173
- return { ...record, topicId: `top_${topicId.slice('thd_'.length)}` }
168
+ if (typeof topicId === 'string') {
169
+ asTopicId(topicId)
170
+ }
171
+ return record
174
172
  }
175
173
 
176
174
  /**
@@ -567,6 +565,7 @@ export class DiskSessionStore implements SessionStore {
567
565
 
568
566
  const found: Project[] = []
569
567
  for (const entry of entries) {
568
+ if (!isEntityId(entry, 'project')) continue
570
569
  const raw = await records.read<PersistedProject>(join(projectsRoot, entry, 'project.json'))
571
570
  if (!raw) continue
572
571
  // Another tenant's project is absent, not an error — a listing is a
@@ -585,13 +584,17 @@ export class DiskSessionStore implements SessionStore {
585
584
  // Session CRUD ------------------------------------------------------------
586
585
 
587
586
  async createSession(params: CreateSessionParams, tenantId: TenantId): Promise<Session> {
587
+ const id = params.id === undefined ? generateSessionId() : asSessionId(params.id)
588
588
  const project = await this.getProject(params.projectId, tenantId)
589
589
  if (!project) {
590
590
  throw new Error(`Project ${params.projectId} not found`)
591
591
  }
592
592
  const now = new Date()
593
+ if (params.id !== undefined && (await this.getSession(id, tenantId))) {
594
+ throw new Error(`Session ${params.id} already exists`)
595
+ }
593
596
  const session: Session = {
594
- id: generateSessionId(),
597
+ id,
595
598
  topicId: params.topicId,
596
599
  projectId: params.projectId,
597
600
  tenantId,
@@ -647,11 +650,11 @@ export class DiskSessionStore implements SessionStore {
647
650
 
648
651
  const results: Session[] = []
649
652
  for (const rawProject of projectDirs) {
650
- if (!rawProject.startsWith('prj_')) continue
653
+ if (!isEntityId(rawProject, 'project')) continue
651
654
  const sessionsRoot = join(projectsDir, rawProject, 'sessions')
652
655
  const sessionDirs = await records.scanNames(sessionsRoot, '')
653
656
  for (const rawSessionId of sessionDirs) {
654
- if (!rawSessionId.startsWith('ses_')) continue
657
+ if (!isEntityId(rawSessionId, 'session')) continue
655
658
  const path = join(sessionsRoot, rawSessionId)
656
659
  const raw = await records.read<PersistedSession>(join(path, 'session.json'))
657
660
  if (!raw) continue
@@ -682,7 +685,7 @@ export class DiskSessionStore implements SessionStore {
682
685
 
683
686
  const results: Session[] = []
684
687
  for (const rawSessionId of sessionDirs) {
685
- if (!rawSessionId.startsWith('ses_')) continue
688
+ if (!isEntityId(rawSessionId, 'session')) continue
686
689
  const path = join(sessionsRoot, rawSessionId)
687
690
  const raw = await records.read<PersistedSession>(join(path, 'session.json'))
688
691
  if (!raw) continue
@@ -747,7 +750,7 @@ export class DiskSessionStore implements SessionStore {
747
750
  // match the in-memory semantics.
748
751
  const subsDir = join(located.path, 'subsessions')
749
752
  const subEntries = await records.scanNames(subsDir, '')
750
- if (subEntries.some((e) => e.startsWith('sub_'))) {
753
+ if (subEntries.some((entry) => isEntityId(entry, 'subSession'))) {
751
754
  throw new Error(
752
755
  `Session ${sessionId} has attached sub-sessions; delete them before deleting the session`,
753
756
  )
@@ -761,15 +764,15 @@ export class DiskSessionStore implements SessionStore {
761
764
  const projectsDir = join(this.rootDir, 'projects')
762
765
  const projectDirs = await records.scanNames(projectsDir, '')
763
766
  for (const rawProject of projectDirs) {
764
- if (!rawProject.startsWith('prj_')) continue
767
+ if (!isEntityId(rawProject, 'project')) continue
765
768
  const sessionsRoot = join(projectsDir, rawProject, 'sessions')
766
769
  const siblingSessions = await records.scanNames(sessionsRoot, '')
767
770
  for (const rawSib of siblingSessions) {
768
- if (!rawSib.startsWith('ses_')) continue
771
+ if (!isEntityId(rawSib, 'session')) continue
769
772
  const sibSubsDir = join(sessionsRoot, rawSib, 'subsessions')
770
773
  const sibSubs = await records.scanNames(sibSubsDir, '')
771
774
  for (const rawSub of sibSubs) {
772
- if (!rawSub.startsWith('sub_')) continue
775
+ if (!isEntityId(rawSub, 'subSession')) continue
773
776
  const subRaw = await records.read<PersistedSubSession>(
774
777
  join(sibSubsDir, rawSub, 'subsession.json'),
775
778
  )
@@ -1091,6 +1094,7 @@ export class DiskSessionStore implements SessionStore {
1091
1094
  }
1092
1095
 
1093
1096
  private projectDir(projectId: ProjectId): string {
1097
+ asProjectId(projectId)
1094
1098
  const cached = this.projectIndex.get(projectId)
1095
1099
  if (cached) return cached.path
1096
1100
  const path = join(this.rootDir, 'projects', projectId)
@@ -1099,6 +1103,7 @@ export class DiskSessionStore implements SessionStore {
1099
1103
  }
1100
1104
 
1101
1105
  private async locateSession(sessionId: SessionId): Promise<SessionIndexEntry | null> {
1106
+ asSessionId(sessionId)
1102
1107
  const cached = this.sessionIndex.get(sessionId)
1103
1108
  if (cached) return cached
1104
1109
 
@@ -1107,12 +1112,12 @@ export class DiskSessionStore implements SessionStore {
1107
1112
  // same `return null` the old catch took directly.
1108
1113
  const projectDirs = await records.scanNames(projectsDir, '')
1109
1114
  for (const rawId of projectDirs) {
1110
- if (!rawId.startsWith('prj_')) continue
1115
+ if (!isEntityId(rawId, 'project')) continue
1111
1116
  const projectId = rawId as ProjectId
1112
1117
  const sessionsRoot = join(projectsDir, projectId, 'sessions')
1113
1118
  const sessionDirs = await records.scanNames(sessionsRoot, '')
1114
1119
  for (const rawSessionId of sessionDirs) {
1115
- if (!rawSessionId.startsWith('ses_')) continue
1120
+ if (!isEntityId(rawSessionId, 'session')) continue
1116
1121
  if (rawSessionId === sessionId) {
1117
1122
  const entry: SessionIndexEntry = {
1118
1123
  sessionId,
@@ -1133,6 +1138,7 @@ export class DiskSessionStore implements SessionStore {
1133
1138
  projectId: ProjectId
1134
1139
  path: string
1135
1140
  } | null> {
1141
+ asSubSessionId(subSessionId)
1136
1142
  const cached = this.subSessionIndex.get(subSessionId)
1137
1143
  if (cached) return cached
1138
1144
 
@@ -1141,12 +1147,12 @@ export class DiskSessionStore implements SessionStore {
1141
1147
  // same `return null` the old catch took directly.
1142
1148
  const projectDirs = await records.scanNames(projectsDir, '')
1143
1149
  for (const rawProject of projectDirs) {
1144
- if (!rawProject.startsWith('prj_')) continue
1150
+ if (!isEntityId(rawProject, 'project')) continue
1145
1151
  const projectId = rawProject as ProjectId
1146
1152
  const sessionsRoot = join(projectsDir, projectId, 'sessions')
1147
1153
  const sessionDirs = await records.scanNames(sessionsRoot, '')
1148
1154
  for (const rawSession of sessionDirs) {
1149
- if (!rawSession.startsWith('ses_')) continue
1155
+ if (!isEntityId(rawSession, 'session')) continue
1150
1156
  const sessionId = rawSession as SessionId
1151
1157
  const subsDir = join(sessionsRoot, sessionId, 'subsessions')
1152
1158
  const subDirs = await records.scanNames(subsDir, '')
@@ -1177,14 +1183,15 @@ export class DiskSessionStore implements SessionStore {
1177
1183
  const projectDirs = await records.scanNames(projectsDir, '')
1178
1184
 
1179
1185
  for (const rawProject of projectDirs) {
1180
- if (!rawProject.startsWith('prj_')) continue
1186
+ if (!isEntityId(rawProject, 'project')) continue
1181
1187
  const sessionsRoot = join(projectsDir, rawProject, 'sessions')
1182
1188
  const sessionDirs = await records.scanNames(sessionsRoot, '')
1183
1189
  for (const rawSession of sessionDirs) {
1184
- if (!rawSession.startsWith('ses_')) continue
1190
+ if (!isEntityId(rawSession, 'session')) continue
1185
1191
  const subsRoot = join(sessionsRoot, rawSession, 'subsessions')
1186
1192
  const subDirs = await records.scanNames(subsRoot, '')
1187
1193
  for (const rawSub of subDirs) {
1194
+ if (!isEntityId(rawSub, 'subSession')) continue
1188
1195
  const raw = await records.read<PersistedSubSession>(
1189
1196
  join(subsRoot, rawSub, 'subsession.json'),
1190
1197
  )
@@ -8,6 +8,8 @@
8
8
  * (Convention #5 deny-by-default, session-hierarchy.md §12.2).
9
9
  */
10
10
 
11
+ import { realpathSync } from 'node:fs'
12
+ import { resolve } from 'node:path'
11
13
  import {
12
14
  ProjectRootPathTakenError,
13
15
  StaleProjectError,
@@ -32,6 +34,8 @@ import type {
32
34
  import type { SubSession } from '../../types/session/sub-session.js'
33
35
  import type { SessionSummaryRef } from '../../types/summary/ref.js'
34
36
  import {
37
+ asProjectId,
38
+ asTenantId,
35
39
  generateMessageId,
36
40
  generateProjectId,
37
41
  generateSessionId,
@@ -80,6 +84,36 @@ export class InMemorySessionStore implements SessionStore {
80
84
  private readonly messages = new Map<SessionId, SessionMessage[]>()
81
85
  private readonly summaries = new Map<SessionId, SummaryRecord>()
82
86
 
87
+ /** Hydrate existing Project snapshots without minting replacement identities. */
88
+ constructor(projects: readonly Project[] = []) {
89
+ const roots = new Map<string, ProjectId>()
90
+ for (const input of projects) {
91
+ const project = structuredClone(input)
92
+ asProjectId(project.id)
93
+ asTenantId(project.tenantId)
94
+ if (this.projects.has(project.id)) throw new Error(`Duplicate project ${project.id}`)
95
+ if (project.rootPath !== undefined) {
96
+ let rootPath: string
97
+ try {
98
+ rootPath = realpathSync(project.rootPath)
99
+ } catch (error) {
100
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
101
+ rootPath = resolve(project.rootPath)
102
+ }
103
+ const key = `${project.tenantId}\0${rootPath}`
104
+ const existingProjectId = roots.get(key)
105
+ if (existingProjectId) throw new ProjectRootPathTakenError({ rootPath, existingProjectId })
106
+ roots.set(key, project.id)
107
+ this.projects.set(project.id, {
108
+ tenantId: project.tenantId,
109
+ project: { ...project, rootPath },
110
+ })
111
+ } else {
112
+ this.projects.set(project.id, { tenantId: project.tenantId, project })
113
+ }
114
+ }
115
+ }
116
+
83
117
  // Project CRUD ------------------------------------------------------------
84
118
 
85
119
  async createProject(params: CreateProjectParams, tenantId: TenantId): Promise<Project> {
@@ -229,8 +263,11 @@ export class InMemorySessionStore implements SessionStore {
229
263
  this.assertTenant(projectRecord.tenantId, tenantId, `project(${params.projectId})`)
230
264
 
231
265
  const now = new Date()
266
+ if (params.id !== undefined && (await this.getSession(params.id, tenantId))) {
267
+ throw new Error(`Session ${params.id} already exists`)
268
+ }
232
269
  const session: Session = {
233
- id: generateSessionId(),
270
+ id: params.id ?? generateSessionId(),
234
271
  topicId: params.topicId,
235
272
  projectId: params.projectId,
236
273
  tenantId,
@@ -11,7 +11,7 @@ import type {
11
11
  TaskStore,
12
12
  UpdateTaskParams,
13
13
  } from '../../types/task/index.js'
14
- import { generateTaskId } from '../../utils/id.js'
14
+ import { asRunId, asTaskId, asTenantId, generateTaskId, isEntityId } from '../../utils/id.js'
15
15
  import { SCOPE_ATTRIBUTE } from '../../utils/log/types.js'
16
16
  import { type Logger, resolveLogger } from '../../utils/logger.js'
17
17
  import { DiskRecordStore } from '../kv/record-store.js'
@@ -82,12 +82,13 @@ export class DiskTaskStore implements TaskStore {
82
82
 
83
83
  constructor(config: DiskTaskStoreConfig) {
84
84
  this.baseDir = config.baseDir
85
- this.defaultRunId = config.defaultRunId
86
- this.tenantId = config.tenantId
85
+ this.defaultRunId = asRunId(config.defaultRunId)
86
+ this.tenantId = config.tenantId === undefined ? undefined : asTenantId(config.tenantId)
87
87
  this.log = resolveLogger(config.logger).child({ [SCOPE_ATTRIBUTE]: 'store/task/disk' })
88
88
  }
89
89
 
90
90
  private taskDir(runId: RunId): string {
91
+ asRunId(runId)
91
92
  if (this.tenantId) {
92
93
  return join(this.baseDir, 'tenants', this.tenantId, 'tasks', runId)
93
94
  }
@@ -95,6 +96,7 @@ export class DiskTaskStore implements TaskStore {
95
96
  }
96
97
 
97
98
  private taskPath(runId: RunId, taskId: TaskId): string {
99
+ asTaskId(taskId)
98
100
  return join(this.taskDir(runId), `${taskId}.json`)
99
101
  }
100
102
 
@@ -498,12 +500,9 @@ export class DiskTaskStore implements TaskStore {
498
500
  : join(this.baseDir, 'tasks')
499
501
  try {
500
502
  const entries = await readdir(root, { withFileTypes: true })
501
- // Prefix-filtered for the reason `DiskCheckpointStore.readRunDirs`
502
- // gives, including the honest half: a directory that is not a run must
503
- // not be enumerated as one, this is not observable downstream today,
504
- // and it is the declared return type that makes it worth keeping.
503
+ // The tasks directory identifies runs; either ID encoding is valid.
505
504
  return entries
506
- .filter((e) => e.isDirectory() && e.name.startsWith('run_'))
505
+ .filter((e) => e.isDirectory() && isEntityId(e.name, 'run'))
507
506
  .map((e) => e.name as RunId)
508
507
  } catch (err) {
509
508
  const code = (err as NodeJS.ErrnoException).code
@@ -19,7 +19,7 @@ import type { TenantId } from '../../types/ids/index.js'
19
19
  import type { ProjectId, TopicId } from '../../types/session/ids.js'
20
20
  import type { Topic } from '../../types/topic/entity.js'
21
21
  import type { CreateTopicParams, TopicStore } from '../../types/topic/store.js'
22
- import { generateTopicId } from '../../utils/id.js'
22
+ import { asProjectId, asTenantId, asTopicId, generateTopicId } from '../../utils/id.js'
23
23
 
24
24
  interface TopicRecord {
25
25
  tenantId: TenantId
@@ -29,6 +29,18 @@ interface TopicRecord {
29
29
  export class InMemoryTopicStore implements TopicStore {
30
30
  private readonly topics = new Map<TopicId, TopicRecord>()
31
31
 
32
+ /** Hydrate existing Topic snapshots without creating new topic identities. */
33
+ constructor(topics: readonly Topic[] = []) {
34
+ for (const input of topics) {
35
+ const topic = structuredClone(input)
36
+ asTopicId(topic.id)
37
+ asProjectId(topic.projectId)
38
+ asTenantId(topic.tenantId)
39
+ if (this.topics.has(topic.id)) throw new Error(`Duplicate topic ${topic.id}`)
40
+ this.topics.set(topic.id, { tenantId: topic.tenantId, topic })
41
+ }
42
+ }
43
+
32
44
  async createTopic(params: CreateTopicParams, tenantId: TenantId): Promise<Topic> {
33
45
  const now = new Date()
34
46
  const topic: Topic = {
@@ -1,22 +1,6 @@
1
- /**
2
- * Unchecked id constructors, for fixtures only.
3
- *
4
- * A test that needs three hundred distinct ids is not testing prefix
5
- * validation, and paying a `startsWith` per literal to say `ses_1` buys it
6
- * nothing. These are the cheap landing zone for that: same call shape as the
7
- * `as*Id` constructors in `utils/id.ts`, no check.
8
- *
9
- * **Deliberately NOT exported from the package barrel.** The whole value of
10
- * the checked constructors is that a malformed id cannot reach a store key,
11
- * and an unchecked one on the public surface is a supported way around that.
12
- * `test-support/` is reachable from inside this repo and nowhere else, which
13
- * is exactly the reach this needs.
14
- *
15
- * Two shapes rather than forty functions, because a fixture wants brevity:
16
- * `fixtureId.run('a')` reads at the call site, and `unchecked<RunId>(s)`
17
- * covers anything the table misses.
18
- */
1
+ /** Deterministic UUID fixtures. Deliberately absent from the package barrel. */
19
2
 
3
+ import { createHash } from 'node:crypto'
20
4
  import { unsafeId } from '../types/ids/brand.js'
21
5
  import type {
22
6
  ActivityId,
@@ -66,52 +50,71 @@ export function unchecked<T extends string>(value: string): T {
66
50
  return unsafeId<T>(value)
67
51
  }
68
52
 
53
+ /** Maps a readable fixture label to a stable, valid UUID without global state. */
54
+ export function fixtureUuid(label: string): string {
55
+ const bytes = createHash('sha256').update(label).digest().subarray(0, 16)
56
+ bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40
57
+ bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80
58
+ const hex = bytes.toString('hex')
59
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`
60
+ }
61
+
69
62
  /**
70
- * One entry per prefixed id type, keyed by the bare concept rather than the
63
+ * One entry per entity type, keyed by the bare concept rather than the
71
64
  * type name — `fixtureId.run('a')`, not `fixtureId.RunId('a')`.
72
65
  */
73
66
  export const fixtureId = {
74
- run: (suffix: string): RunId => unsafeId<RunId>(`run_${suffix}`),
75
- message: (suffix: string): MessageId => unsafeId<MessageId>(`msg_${suffix}`),
76
- session: (suffix: string): SessionId => unsafeId<SessionId>(`ses_${suffix}`),
77
- toolCall: (suffix: string): ToolCallId => unsafeId<ToolCallId>(`call_${suffix}`),
78
- activity: (suffix: string): ActivityId => unsafeId<ActivityId>(`act_${suffix}`),
79
- task: (suffix: string): TaskId => unsafeId<TaskId>(`task_${suffix}`),
80
- plan: (suffix: string): PlanId => unsafeId<PlanId>(`plan_${suffix}`),
81
- knowledgeBase: (suffix: string): KnowledgeBaseId => unsafeId<KnowledgeBaseId>(`kb_${suffix}`),
82
- document: (suffix: string): DocumentId => unsafeId<DocumentId>(`doc_${suffix}`),
83
- chunk: (suffix: string): ChunkId => unsafeId<ChunkId>(`chk_${suffix}`),
84
- connector: (suffix: string): ConnectorId => unsafeId<ConnectorId>(`conn_${suffix}`),
67
+ run: (suffix: string): RunId => unsafeId<RunId>(fixtureUuid(`run_${suffix}`)),
68
+ message: (suffix: string): MessageId => unsafeId<MessageId>(fixtureUuid(`msg_${suffix}`)),
69
+ session: (suffix: string): SessionId => unsafeId<SessionId>(fixtureUuid(`ses_${suffix}`)),
70
+ toolCall: (suffix: string): ToolCallId => unsafeId<ToolCallId>(fixtureUuid(`call_${suffix}`)),
71
+ activity: (suffix: string): ActivityId => unsafeId<ActivityId>(fixtureUuid(`act_${suffix}`)),
72
+ task: (suffix: string): TaskId => unsafeId<TaskId>(fixtureUuid(`task_${suffix}`)),
73
+ plan: (suffix: string): PlanId => unsafeId<PlanId>(fixtureUuid(`plan_${suffix}`)),
74
+ knowledgeBase: (suffix: string): KnowledgeBaseId =>
75
+ unsafeId<KnowledgeBaseId>(fixtureUuid(`kb_${suffix}`)),
76
+ document: (suffix: string): DocumentId => unsafeId<DocumentId>(fixtureUuid(`doc_${suffix}`)),
77
+ chunk: (suffix: string): ChunkId => unsafeId<ChunkId>(fixtureUuid(`chk_${suffix}`)),
78
+ connector: (suffix: string): ConnectorId => unsafeId<ConnectorId>(fixtureUuid(`conn_${suffix}`)),
85
79
  connectorInstance: (suffix: string): ConnectorInstanceId =>
86
- unsafeId<ConnectorInstanceId>(`ci_${suffix}`),
87
- tenant: (suffix: string): TenantId => unsafeId<TenantId>(`tnt_${suffix}`),
88
- credential: (suffix: string): CredentialId => unsafeId<CredentialId>(`cred_${suffix}`),
80
+ unsafeId<ConnectorInstanceId>(fixtureUuid(`ci_${suffix}`)),
81
+ tenant: (suffix: string): TenantId => unsafeId<TenantId>(fixtureUuid(`tnt_${suffix}`)),
82
+ credential: (suffix: string): CredentialId =>
83
+ unsafeId<CredentialId>(fixtureUuid(`cred_${suffix}`)),
89
84
  executionContext: (suffix: string): ExecutionContextId =>
90
- unsafeId<ExecutionContextId>(`ectx_${suffix}`),
91
- mCPServer: (suffix: string): MCPServerId => unsafeId<MCPServerId>(`mcp_${suffix}`),
92
- mCPClient: (suffix: string): MCPClientId => unsafeId<MCPClientId>(`mcpc_${suffix}`),
93
- mCPSession: (suffix: string): MCPSessionId => unsafeId<MCPSessionId>(`mcps_${suffix}`),
94
- environment: (suffix: string): EnvironmentId => unsafeId<EnvironmentId>(`env_${suffix}`),
95
- checkpoint: (suffix: string): CheckpointId => unsafeId<CheckpointId>(`cp_${suffix}`),
96
- lock: (suffix: string): LockId => unsafeId<LockId>(`lock_${suffix}`),
97
- advisory: (suffix: string): AdvisoryId => unsafeId<AdvisoryId>(`adv_${suffix}`),
98
- advisoryCall: (suffix: string): AdvisoryCallId => unsafeId<AdvisoryCallId>(`advc_${suffix}`),
99
- emergencySave: (suffix: string): EmergencySaveId => unsafeId<EmergencySaveId>(`esave_${suffix}`),
100
- memory: (suffix: string): MemoryId => unsafeId<MemoryId>(`mem_${suffix}`),
101
- plugin: (suffix: string): PluginId => unsafeId<PluginId>(`plg_${suffix}`),
102
- sandbox: (suffix: string): SandboxId => unsafeId<SandboxId>(`sbx_${suffix}`),
103
- auditEvent: (suffix: string): AuditEventId => unsafeId<AuditEventId>(`aud_${suffix}`),
104
- user: (suffix: string): UserId => unsafeId<UserId>(`usr_${suffix}`),
105
- agent: (suffix: string): AgentId => unsafeId<AgentId>(`agt_${suffix}`),
106
- memoryStoreRef: (suffix: string): MemoryStoreRef => unsafeId<MemoryStoreRef>(`mms_${suffix}`),
107
- vaultRef: (suffix: string): VaultRef => unsafeId<VaultRef>(`vlt_${suffix}`),
85
+ unsafeId<ExecutionContextId>(fixtureUuid(`ectx_${suffix}`)),
86
+ mCPServer: (suffix: string): MCPServerId => unsafeId<MCPServerId>(fixtureUuid(`mcp_${suffix}`)),
87
+ mCPClient: (suffix: string): MCPClientId => unsafeId<MCPClientId>(fixtureUuid(`mcpc_${suffix}`)),
88
+ mCPSession: (suffix: string): MCPSessionId =>
89
+ unsafeId<MCPSessionId>(fixtureUuid(`mcps_${suffix}`)),
90
+ environment: (suffix: string): EnvironmentId =>
91
+ unsafeId<EnvironmentId>(fixtureUuid(`env_${suffix}`)),
92
+ checkpoint: (suffix: string): CheckpointId => unsafeId<CheckpointId>(fixtureUuid(`cp_${suffix}`)),
93
+ lock: (suffix: string): LockId => unsafeId<LockId>(fixtureUuid(`lock_${suffix}`)),
94
+ advisory: (suffix: string): AdvisoryId => unsafeId<AdvisoryId>(fixtureUuid(`adv_${suffix}`)),
95
+ advisoryCall: (suffix: string): AdvisoryCallId =>
96
+ unsafeId<AdvisoryCallId>(fixtureUuid(`advc_${suffix}`)),
97
+ emergencySave: (suffix: string): EmergencySaveId =>
98
+ unsafeId<EmergencySaveId>(fixtureUuid(`esave_${suffix}`)),
99
+ memory: (suffix: string): MemoryId => unsafeId<MemoryId>(fixtureUuid(`mem_${suffix}`)),
100
+ plugin: (suffix: string): PluginId => unsafeId<PluginId>(fixtureUuid(`plg_${suffix}`)),
101
+ sandbox: (suffix: string): SandboxId => unsafeId<SandboxId>(fixtureUuid(`sbx_${suffix}`)),
102
+ auditEvent: (suffix: string): AuditEventId =>
103
+ unsafeId<AuditEventId>(fixtureUuid(`aud_${suffix}`)),
104
+ user: (suffix: string): UserId => unsafeId<UserId>(fixtureUuid(`usr_${suffix}`)),
105
+ agent: (suffix: string): AgentId => unsafeId<AgentId>(fixtureUuid(`agt_${suffix}`)),
106
+ memoryStoreRef: (suffix: string): MemoryStoreRef =>
107
+ unsafeId<MemoryStoreRef>(fixtureUuid(`mms_${suffix}`)),
108
+ vaultRef: (suffix: string): VaultRef => unsafeId<VaultRef>(fixtureUuid(`vlt_${suffix}`)),
108
109
  knowledgeBaseRef: (suffix: string): KnowledgeBaseRef =>
109
- unsafeId<KnowledgeBaseRef>(`kbs_${suffix}`),
110
- project: (suffix: string): ProjectId => unsafeId<ProjectId>(`prj_${suffix}`),
111
- topic: (suffix: string): TopicId => unsafeId<TopicId>(`top_${suffix}`),
112
- subSession: (suffix: string): SubSessionId => unsafeId<SubSessionId>(`sub_${suffix}`),
113
- handoff: (suffix: string): HandoffId => unsafeId<HandoffId>(`hof_${suffix}`),
114
- workspace: (suffix: string): WorkspaceId => unsafeId<WorkspaceId>(`wsp_${suffix}`),
115
- summary: (suffix: string): SummaryId => unsafeId<SummaryId>(`sum_${suffix}`),
116
- deliverable: (suffix: string): DeliverableId => unsafeId<DeliverableId>(`del_${suffix}`),
110
+ unsafeId<KnowledgeBaseRef>(fixtureUuid(`kbs_${suffix}`)),
111
+ project: (suffix: string): ProjectId => unsafeId<ProjectId>(fixtureUuid(`prj_${suffix}`)),
112
+ topic: (suffix: string): TopicId => unsafeId<TopicId>(fixtureUuid(`top_${suffix}`)),
113
+ subSession: (suffix: string): SubSessionId =>
114
+ unsafeId<SubSessionId>(fixtureUuid(`sub_${suffix}`)),
115
+ handoff: (suffix: string): HandoffId => unsafeId<HandoffId>(fixtureUuid(`hof_${suffix}`)),
116
+ workspace: (suffix: string): WorkspaceId => unsafeId<WorkspaceId>(fixtureUuid(`wsp_${suffix}`)),
117
+ summary: (suffix: string): SummaryId => unsafeId<SummaryId>(fixtureUuid(`sum_${suffix}`)),
118
+ deliverable: (suffix: string): DeliverableId =>
119
+ unsafeId<DeliverableId>(fixtureUuid(`del_${suffix}`)),
117
120
  } as const
@@ -77,7 +77,9 @@ export function buildAdvisoryTools(opts: AdvisoryToolsOptions): ToolDefinition[]
77
77
  permissions: [],
78
78
  readOnly: true,
79
79
  destructive: false,
80
- concurrencySafe: true,
80
+ // Consultations debit one run account and one per-run advisory quota.
81
+ // Serial execution makes the next admission see the preceding receipt.
82
+ concurrencySafe: false,
81
83
  async execute({ advisor_id, question, domain, urgency, include_context }) {
82
84
  const budgetCheck = advisoryCtx.checkBudget()
83
85
  if (!budgetCheck.allowed) {
@@ -92,6 +92,10 @@ function isDangerousCommand(command: string): boolean {
92
92
  return DANGEROUS_PATTERNS.some((pattern) => pattern.test(command))
93
93
  }
94
94
 
95
+ /** The refusal when a sandbox cannot host a detached process; exported so the test states the same words. */
96
+ export const SANDBOX_CANNOT_DETACH =
97
+ 'run_in_background is unavailable: this sandbox cannot start a detached process, and the job will not be run on the host to get around it. Run the command in the foreground, or raise `timeout` up to the tool maximum.'
98
+
95
99
  export const BashTool = defineTool({
96
100
  name: 'bash',
97
101
  description:
@@ -123,21 +127,16 @@ export const BashTool = defineTool({
123
127
  }
124
128
 
125
129
  if (input.run_in_background) {
126
- // The current registry owns a host process. Foreground execution,
127
- // however, goes through `context.sandbox.exec()` below. Treating the
128
- // same command as host work just because `run_in_background` changed
129
- // would make that boolean an escape hatch from the configured boundary.
130
- //
131
- // Query-built contexts structurally withhold the registry in this
132
- // composition. This explicit check also protects direct tool callers
133
- // and says why the capability is absent instead of misdiagnosing the
134
- // host as having configured no registry.
135
- if (context.sandbox) {
130
+ // A sandboxed run gets a registry only when its sandbox can start a
131
+ // detached process inside the boundary (`Sandbox.spawnDetached`);
132
+ // the executor withholds it otherwise. This check is for direct
133
+ // tool callers, who could hand a host registry and a sandbox to the
134
+ // same context: the boolean is never an escape from the boundary.
135
+ if (context.sandbox && context.sandbox.spawnDetached === undefined) {
136
136
  return {
137
137
  success: false,
138
138
  output: '',
139
- error:
140
- 'run_in_background is unavailable while a sandbox is active because the host background-job registry cannot preserve that sandbox boundary. Run the command in the foreground, or use a sandbox-aware persistent-process capability.',
139
+ error: SANDBOX_CANNOT_DETACH,
141
140
  }
142
141
  }
143
142
  // Refused, not degraded to `cmd &`. The fallback is not a lesser
@@ -152,7 +152,11 @@ function buildDescription(host: ComputerUseHost): string {
152
152
  `Available actions: ${available.join('; ') || 'none'}.`,
153
153
  ]
154
154
  if (unavailable.length > 0) {
155
- lines.push(`Unavailable on this host: ${unavailable.join(', ')}.`)
155
+ lines.push(
156
+ caps.unavailableReason
157
+ ? `Unavailable on this host: ${unavailable.join(', ')} — ${caps.unavailableReason} Do not retry; tell the user.`
158
+ : `Unavailable on this host: ${unavailable.join(', ')}.`,
159
+ )
156
160
  }
157
161
  lines.push(
158
162
  'Coordinates are in logical pixels from the top-left of the primary display. Call getDisplayGeometry through screenshot output before clicking to confirm bounds.',
@@ -303,7 +307,7 @@ export function createComputerUseTool(host: ComputerUseHost): ToolDefinition<Act
303
307
  return {
304
308
  success: false,
305
309
  output: '',
306
- error: `computer_use: action "${input.type}" requires capability "${required}" which is not available on this host (displayServer=${host.capabilities.displayServer}).`,
310
+ error: `computer_use: action "${input.type}" requires capability "${required}" which is not available on this host (displayServer=${host.capabilities.displayServer}).${host.capabilities.unavailableReason ? ` ${host.capabilities.unavailableReason} Do not retry; tell the user.` : ''}`,
307
311
  }
308
312
  }
309
313
  try {
@@ -3,7 +3,7 @@ import { readFile } from 'node:fs/promises'
3
3
  import { z } from 'zod'
4
4
  import type { ToolResult } from '../../types/tool/index.js'
5
5
  import { defineTool } from '../defineTool.js'
6
- import { resolveWithinReal } from '../paths.js'
6
+ import { resolveWithinAnyReal, toolRoots } from '../paths.js'
7
7
  import { atomicWriteFile } from './atomic-write-file.js'
8
8
  import { fingerprintContent, staleFileError } from './content-fingerprint.js'
9
9
  import { withFileMutationLock } from './file-mutation-lock.js'
@@ -350,7 +350,7 @@ export const EditTool = defineTool({
350
350
  // machine, and answers it with whatever happens to exist there.
351
351
  const filePath = context.sandbox
352
352
  ? undefined
353
- : await resolveWithinReal(context.workingDirectory, parsed.data.path)
353
+ : await resolveWithinAnyReal(toolRoots(context), parsed.data.path)
354
354
  // Read-modify-write is not atomic on its own: two edits to the same
355
355
  // path interleave their reads, and the second write lands on content
356
356
  // the first had already replaced — so one edit vanishes and the loser
@@ -5,7 +5,7 @@ import type { Sandbox } from '../../types/sandbox/index.js'
5
5
  import type { ToolResult } from '../../types/tool/index.js'
6
6
  import { defineTool } from '../defineTool.js'
7
7
  import { matchesGlob } from '../glob-match.js'
8
- import { resolveWithin } from '../paths.js'
8
+ import { resolveWithinAny, toolRoots } from '../paths.js'
9
9
  import { joinPosix, relativePosix, resolveWithinPosix } from '../posix-path.js'
10
10
 
11
11
  /**
@@ -111,7 +111,7 @@ export const GlobTool = defineTool({
111
111
  // Contained, not merely resolved. This was a bare `resolve`, so
112
112
  // `path: "../../.."` reached whatever sits above the working
113
113
  // directory — with no sandbox needed to make it work.
114
- const basePath = resolveWithin(context.workingDirectory, input.path)
114
+ const basePath = resolveWithinAny(toolRoots(context), input.path)
115
115
 
116
116
  let searchPath = basePath
117
117
  let pattern = input.pattern
@@ -121,7 +121,7 @@ export const GlobTool = defineTool({
121
121
  // A base directory lifted out of the PATTERN is caller-supplied
122
122
  // too: `pattern: "../../**/*.pem"` is the same escape wearing a
123
123
  // different argument.
124
- const resolvedPatternBase = resolveWithin(context.workingDirectory, baseDir)
124
+ const resolvedPatternBase = resolveWithinAny(toolRoots(context), baseDir)
125
125
  if (resolvedPatternBase === basePath || resolvedPatternBase.startsWith(`${basePath}/`)) {
126
126
  searchPath = resolvedPatternBase
127
127
  pattern = relativePattern
@@ -4,7 +4,7 @@ import { z } from 'zod'
4
4
  import type { Sandbox } from '../../types/sandbox/index.js'
5
5
  import { defineTool } from '../defineTool.js'
6
6
  import { matchesGlob } from '../glob-match.js'
7
- import { resolveWithin } from '../paths.js'
7
+ import { resolveWithinAny } from '../paths.js'
8
8
  import { joinPosix, relativePosix, resolveWithinPosix } from '../posix-path.js'
9
9
 
10
10
  /**
@@ -135,7 +135,7 @@ export const GrepTool = defineTool({
135
135
  // working directory, with no sandbox needed to make it work.
136
136
  const searchRoot = source.posix
137
137
  ? resolveWithinPosix(source.root, input.path)
138
- : resolveWithin(source.root, input.path)
138
+ : resolveWithinAny([source.root, ...(context.additionalDirectories ?? [])], input.path)
139
139
 
140
140
  // Auto-prepend **/ for simple patterns (e.g. "*.ts" → "**/*.ts")
141
141
  let filePattern = input.include ?? '**/*'
@@ -4,7 +4,7 @@ import { z } from 'zod'
4
4
  import type { Sandbox } from '../../types/sandbox/index.js'
5
5
  import type { ToolResult } from '../../types/tool/index.js'
6
6
  import { defineTool } from '../defineTool.js'
7
- import { resolveWithin } from '../paths.js'
7
+ import { resolveWithinAny, toolRoots } from '../paths.js'
8
8
  import { joinPosix, relativePosix, resolveWithinPosix } from '../posix-path.js'
9
9
 
10
10
  const inputSchema = z.object({
@@ -220,7 +220,7 @@ export const LsTool = defineTool({
220
220
  }
221
221
 
222
222
  // Contained, not merely resolved — see `resolveWithin`.
223
- const targetPath = resolveWithin(context.workingDirectory, input.path)
223
+ const targetPath = resolveWithinAny(toolRoots(context), input.path)
224
224
 
225
225
  if (input.recursive) {
226
226
  const output: string[] = []