@namzu/sdk 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/CHANGELOG.md +253 -0
  2. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  3. package/dist/agents/ReactiveAgent.js +5 -0
  4. package/dist/agents/ReactiveAgent.js.map +1 -1
  5. package/dist/agents/SupervisorAgent.d.ts +22 -1
  6. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  7. package/dist/agents/SupervisorAgent.js +47 -14
  8. package/dist/agents/SupervisorAgent.js.map +1 -1
  9. package/dist/agents/__tests__/supervisor-ledger.test.d.ts +2 -0
  10. package/dist/agents/__tests__/supervisor-ledger.test.d.ts.map +1 -0
  11. package/dist/agents/__tests__/supervisor-ledger.test.js +131 -0
  12. package/dist/agents/__tests__/supervisor-ledger.test.js.map +1 -0
  13. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  14. package/dist/bridge/a2a/mapper.js +2 -0
  15. package/dist/bridge/a2a/mapper.js.map +1 -1
  16. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  17. package/dist/bridge/sse/mapper.js +4 -0
  18. package/dist/bridge/sse/mapper.js.map +1 -1
  19. package/dist/config/runtime.d.ts +24 -0
  20. package/dist/config/runtime.d.ts.map +1 -1
  21. package/dist/config/runtime.js +9 -0
  22. package/dist/config/runtime.js.map +1 -1
  23. package/dist/connector/builtins/webhook.test.js +17 -0
  24. package/dist/connector/builtins/webhook.test.js.map +1 -1
  25. package/dist/connector/index.d.ts +1 -0
  26. package/dist/connector/index.d.ts.map +1 -1
  27. package/dist/connector/index.js +1 -0
  28. package/dist/connector/index.js.map +1 -1
  29. package/dist/connector/mcp/client.d.ts.map +1 -1
  30. package/dist/connector/mcp/client.js +4 -0
  31. package/dist/connector/mcp/client.js.map +1 -1
  32. package/dist/connector/mcp/index.d.ts +1 -0
  33. package/dist/connector/mcp/index.d.ts.map +1 -1
  34. package/dist/connector/mcp/index.js +1 -0
  35. package/dist/connector/mcp/index.js.map +1 -1
  36. package/dist/connector/mcp/streamable-http.d.ts +22 -0
  37. package/dist/connector/mcp/streamable-http.d.ts.map +1 -0
  38. package/dist/connector/mcp/streamable-http.js +128 -0
  39. package/dist/connector/mcp/streamable-http.js.map +1 -0
  40. package/dist/connector/mcp/streamable-http.test.d.ts +2 -0
  41. package/dist/connector/mcp/streamable-http.test.d.ts.map +1 -0
  42. package/dist/connector/mcp/streamable-http.test.js +132 -0
  43. package/dist/connector/mcp/streamable-http.test.js.map +1 -0
  44. package/dist/{runtime/query → constants}/continuation.d.ts +5 -0
  45. package/dist/constants/continuation.d.ts.map +1 -0
  46. package/dist/{runtime/query → constants}/continuation.js +5 -0
  47. package/dist/constants/continuation.js.map +1 -0
  48. package/dist/constants/index.d.ts +1 -0
  49. package/dist/constants/index.d.ts.map +1 -1
  50. package/dist/constants/index.js +1 -0
  51. package/dist/constants/index.js.map +1 -1
  52. package/dist/manager/run/persistence.d.ts +11 -0
  53. package/dist/manager/run/persistence.d.ts.map +1 -1
  54. package/dist/manager/run/persistence.js +30 -1
  55. package/dist/manager/run/persistence.js.map +1 -1
  56. package/dist/persona/assembler.d.ts.map +1 -1
  57. package/dist/persona/assembler.js +18 -9
  58. package/dist/persona/assembler.js.map +1 -1
  59. package/dist/provider/capabilities.d.ts +27 -0
  60. package/dist/provider/capabilities.d.ts.map +1 -0
  61. package/dist/provider/capabilities.js +29 -0
  62. package/dist/provider/capabilities.js.map +1 -0
  63. package/dist/provider/collect.d.ts.map +1 -1
  64. package/dist/provider/collect.js +4 -1
  65. package/dist/provider/collect.js.map +1 -1
  66. package/dist/provider/index.d.ts +2 -0
  67. package/dist/provider/index.d.ts.map +1 -1
  68. package/dist/provider/index.js +1 -0
  69. package/dist/provider/index.js.map +1 -1
  70. package/dist/public-runtime.d.ts +4 -3
  71. package/dist/public-runtime.d.ts.map +1 -1
  72. package/dist/public-runtime.js +3 -3
  73. package/dist/public-runtime.js.map +1 -1
  74. package/dist/registry/tool/execute.d.ts +27 -0
  75. package/dist/registry/tool/execute.d.ts.map +1 -1
  76. package/dist/registry/tool/execute.js +124 -21
  77. package/dist/registry/tool/execute.js.map +1 -1
  78. package/dist/registry/tool/execute.test.d.ts +9 -6
  79. package/dist/registry/tool/execute.test.d.ts.map +1 -1
  80. package/dist/registry/tool/execute.test.js +72 -10
  81. package/dist/registry/tool/execute.test.js.map +1 -1
  82. package/dist/registry/toolset/catalog.test.js +62 -0
  83. package/dist/registry/toolset/catalog.test.js.map +1 -1
  84. package/dist/run/reporter.d.ts.map +1 -1
  85. package/dist/run/reporter.js +8 -0
  86. package/dist/run/reporter.js.map +1 -1
  87. package/dist/runtime/query/__tests__/capability-negotiation.test.d.ts +2 -0
  88. package/dist/runtime/query/__tests__/capability-negotiation.test.d.ts.map +1 -0
  89. package/dist/runtime/query/__tests__/capability-negotiation.test.js +184 -0
  90. package/dist/runtime/query/__tests__/capability-negotiation.test.js.map +1 -0
  91. package/dist/runtime/query/__tests__/checkpoint-store.test.d.ts +2 -0
  92. package/dist/runtime/query/__tests__/checkpoint-store.test.d.ts.map +1 -0
  93. package/dist/runtime/query/__tests__/checkpoint-store.test.js +259 -0
  94. package/dist/runtime/query/__tests__/checkpoint-store.test.js.map +1 -0
  95. package/dist/runtime/query/__tests__/checkpoint.test.js +9 -3
  96. package/dist/runtime/query/__tests__/checkpoint.test.js.map +1 -1
  97. package/dist/runtime/query/__tests__/deferred-tools.test.js +43 -5
  98. package/dist/runtime/query/__tests__/deferred-tools.test.js.map +1 -1
  99. package/dist/runtime/query/__tests__/long-document-flow.test.d.ts +2 -0
  100. package/dist/runtime/query/__tests__/long-document-flow.test.d.ts.map +1 -0
  101. package/dist/runtime/query/__tests__/long-document-flow.test.js +154 -0
  102. package/dist/runtime/query/__tests__/long-document-flow.test.js.map +1 -0
  103. package/dist/runtime/query/__tests__/orphan-task-turn-end.test.d.ts +2 -0
  104. package/dist/runtime/query/__tests__/orphan-task-turn-end.test.d.ts.map +1 -0
  105. package/dist/runtime/query/__tests__/orphan-task-turn-end.test.js +110 -0
  106. package/dist/runtime/query/__tests__/orphan-task-turn-end.test.js.map +1 -0
  107. package/dist/runtime/query/__tests__/prompt.test.js +15 -11
  108. package/dist/runtime/query/__tests__/prompt.test.js.map +1 -1
  109. package/dist/runtime/query/checkpoint.d.ts +16 -2
  110. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  111. package/dist/runtime/query/checkpoint.js +21 -7
  112. package/dist/runtime/query/checkpoint.js.map +1 -1
  113. package/dist/runtime/query/context.d.ts +7 -0
  114. package/dist/runtime/query/context.d.ts.map +1 -1
  115. package/dist/runtime/query/context.js +1 -0
  116. package/dist/runtime/query/context.js.map +1 -1
  117. package/dist/runtime/query/index.d.ts +29 -0
  118. package/dist/runtime/query/index.d.ts.map +1 -1
  119. package/dist/runtime/query/index.js +98 -8
  120. package/dist/runtime/query/index.js.map +1 -1
  121. package/dist/runtime/query/iteration/index.d.ts +3 -55
  122. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  123. package/dist/runtime/query/iteration/index.js +260 -656
  124. package/dist/runtime/query/iteration/index.js.map +1 -1
  125. package/dist/runtime/query/iteration/phases/checkpoint.d.ts.map +1 -1
  126. package/dist/runtime/query/iteration/phases/checkpoint.js +24 -2
  127. package/dist/runtime/query/iteration/phases/checkpoint.js.map +1 -1
  128. package/dist/runtime/query/iteration/phases/compaction.d.ts +8 -0
  129. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  130. package/dist/runtime/query/iteration/phases/compaction.js +84 -3
  131. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  132. package/dist/runtime/query/iteration/phases/context.d.ts +13 -2
  133. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  134. package/dist/runtime/query/iteration/phases/context.js +53 -0
  135. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  136. package/dist/runtime/query/iteration/phases/hitl-abort-race.test.d.ts +2 -0
  137. package/dist/runtime/query/iteration/phases/hitl-abort-race.test.d.ts.map +1 -0
  138. package/dist/runtime/query/iteration/phases/hitl-abort-race.test.js +73 -0
  139. package/dist/runtime/query/iteration/phases/hitl-abort-race.test.js.map +1 -0
  140. package/dist/runtime/query/iteration/phases/hitl-answer-question.test.d.ts +2 -0
  141. package/dist/runtime/query/iteration/phases/hitl-answer-question.test.d.ts.map +1 -0
  142. package/dist/runtime/query/iteration/phases/hitl-answer-question.test.js +120 -0
  143. package/dist/runtime/query/iteration/phases/hitl-answer-question.test.js.map +1 -0
  144. package/dist/runtime/query/iteration/phases/tool-review.d.ts +1 -1
  145. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  146. package/dist/runtime/query/iteration/phases/tool-review.js +7 -2
  147. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  148. package/dist/runtime/query/iteration/phases/working-memory-compaction.test.d.ts +19 -0
  149. package/dist/runtime/query/iteration/phases/working-memory-compaction.test.d.ts.map +1 -0
  150. package/dist/runtime/query/iteration/phases/working-memory-compaction.test.js +177 -0
  151. package/dist/runtime/query/iteration/phases/working-memory-compaction.test.js.map +1 -0
  152. package/dist/runtime/query/iteration/phases/working-memory.d.ts +31 -0
  153. package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -0
  154. package/dist/runtime/query/iteration/phases/working-memory.js +81 -0
  155. package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -0
  156. package/dist/runtime/query/iteration/stream-turn.d.ts +35 -0
  157. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -0
  158. package/dist/runtime/query/iteration/stream-turn.js +341 -0
  159. package/dist/runtime/query/iteration/stream-turn.js.map +1 -0
  160. package/dist/runtime/query/replay/list.d.ts +17 -1
  161. package/dist/runtime/query/replay/list.d.ts.map +1 -1
  162. package/dist/runtime/query/replay/list.js +21 -4
  163. package/dist/runtime/query/replay/list.js.map +1 -1
  164. package/dist/runtime/query/replay/prepare.d.ts +10 -0
  165. package/dist/runtime/query/replay/prepare.d.ts.map +1 -1
  166. package/dist/runtime/query/replay/prepare.js +20 -4
  167. package/dist/runtime/query/replay/prepare.js.map +1 -1
  168. package/dist/session/workspace/__tests__/shared-run.test.js +1 -1
  169. package/dist/session/workspace/__tests__/shared-run.test.js.map +1 -1
  170. package/dist/session/workspace/shared-run.js +1 -0
  171. package/dist/session/workspace/shared-run.js.map +1 -1
  172. package/dist/skills/loader.test.js +8 -8
  173. package/dist/skills/loader.test.js.map +1 -1
  174. package/dist/store/index.d.ts +1 -0
  175. package/dist/store/index.d.ts.map +1 -1
  176. package/dist/store/index.js +1 -0
  177. package/dist/store/index.js.map +1 -1
  178. package/dist/store/run/checkpoint-disk.d.ts +28 -0
  179. package/dist/store/run/checkpoint-disk.d.ts.map +1 -0
  180. package/dist/store/run/checkpoint-disk.js +55 -0
  181. package/dist/store/run/checkpoint-disk.js.map +1 -0
  182. package/dist/streaming/coalesce.test.js.map +1 -1
  183. package/dist/tools/builtins/__tests__/payload-budget.test.js +48 -0
  184. package/dist/tools/builtins/__tests__/payload-budget.test.js.map +1 -1
  185. package/dist/tools/builtins/__tests__/read-file.test.js +9 -0
  186. package/dist/tools/builtins/__tests__/read-file.test.js.map +1 -1
  187. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  188. package/dist/tools/builtins/read-file.js +50 -2
  189. package/dist/tools/builtins/read-file.js.map +1 -1
  190. package/dist/tools/builtins/search-tools.d.ts.map +1 -1
  191. package/dist/tools/builtins/search-tools.js +32 -7
  192. package/dist/tools/builtins/search-tools.js.map +1 -1
  193. package/dist/tools/coordinator/__tests__/approve-plan.test.d.ts +2 -0
  194. package/dist/tools/coordinator/__tests__/approve-plan.test.d.ts.map +1 -0
  195. package/dist/tools/coordinator/__tests__/approve-plan.test.js +114 -0
  196. package/dist/tools/coordinator/__tests__/approve-plan.test.js.map +1 -0
  197. package/dist/tools/coordinator/__tests__/ask-user-question.test.d.ts +2 -0
  198. package/dist/tools/coordinator/__tests__/ask-user-question.test.d.ts.map +1 -0
  199. package/dist/tools/coordinator/__tests__/ask-user-question.test.js +309 -0
  200. package/dist/tools/coordinator/__tests__/ask-user-question.test.js.map +1 -0
  201. package/dist/tools/coordinator/index.d.ts +8 -0
  202. package/dist/tools/coordinator/index.d.ts.map +1 -1
  203. package/dist/tools/coordinator/index.js +195 -15
  204. package/dist/tools/coordinator/index.js.map +1 -1
  205. package/dist/types/agent/index.d.ts +1 -0
  206. package/dist/types/agent/index.d.ts.map +1 -1
  207. package/dist/types/agent/index.js +1 -0
  208. package/dist/types/agent/index.js.map +1 -1
  209. package/dist/types/agent/reactive.d.ts +15 -0
  210. package/dist/types/agent/reactive.d.ts.map +1 -1
  211. package/dist/types/agent/supervisor.d.ts +18 -0
  212. package/dist/types/agent/supervisor.d.ts.map +1 -1
  213. package/dist/types/agent/working-memory.d.ts +29 -0
  214. package/dist/types/agent/working-memory.d.ts.map +1 -0
  215. package/dist/types/agent/working-memory.js +2 -0
  216. package/dist/types/agent/working-memory.js.map +1 -0
  217. package/dist/types/common/index.d.ts +10 -0
  218. package/dist/types/common/index.d.ts.map +1 -1
  219. package/dist/types/common/index.js +18 -0
  220. package/dist/types/common/index.js.map +1 -1
  221. package/dist/types/common/usage-merge.test.d.ts +2 -0
  222. package/dist/types/common/usage-merge.test.d.ts.map +1 -0
  223. package/dist/types/common/usage-merge.test.js +48 -0
  224. package/dist/types/common/usage-merge.test.js.map +1 -0
  225. package/dist/types/connector/mcp.d.ts +9 -2
  226. package/dist/types/connector/mcp.d.ts.map +1 -1
  227. package/dist/types/hitl/index.d.ts +42 -0
  228. package/dist/types/hitl/index.d.ts.map +1 -1
  229. package/dist/types/hitl/index.js +11 -0
  230. package/dist/types/hitl/index.js.map +1 -1
  231. package/dist/types/provider/chat.d.ts +9 -0
  232. package/dist/types/provider/chat.d.ts.map +1 -1
  233. package/dist/types/provider/config.d.ts +18 -0
  234. package/dist/types/provider/config.d.ts.map +1 -1
  235. package/dist/types/provider/interface.d.ts +10 -0
  236. package/dist/types/provider/interface.d.ts.map +1 -1
  237. package/dist/types/run/checkpoint-store.d.ts +64 -0
  238. package/dist/types/run/checkpoint-store.d.ts.map +1 -0
  239. package/dist/types/run/checkpoint-store.js +12 -0
  240. package/dist/types/run/checkpoint-store.js.map +1 -0
  241. package/dist/types/run/config.d.ts +27 -0
  242. package/dist/types/run/config.d.ts.map +1 -1
  243. package/dist/types/run/events.d.ts +6 -0
  244. package/dist/types/run/events.d.ts.map +1 -1
  245. package/dist/types/run/events.js.map +1 -1
  246. package/dist/types/run/index.d.ts +1 -0
  247. package/dist/types/run/index.d.ts.map +1 -1
  248. package/dist/types/run/index.js +1 -0
  249. package/dist/types/run/index.js.map +1 -1
  250. package/dist/version.d.ts.map +1 -1
  251. package/dist/version.js +25 -4
  252. package/dist/version.js.map +1 -1
  253. package/package.json +1 -1
  254. package/src/agents/ReactiveAgent.ts +5 -0
  255. package/src/agents/SupervisorAgent.ts +56 -16
  256. package/src/agents/__tests__/supervisor-ledger.test.ts +185 -0
  257. package/src/bridge/a2a/mapper.ts +3 -0
  258. package/src/bridge/sse/mapper.ts +5 -0
  259. package/src/config/runtime.ts +9 -0
  260. package/src/connector/builtins/webhook.test.ts +21 -0
  261. package/src/connector/index.ts +1 -0
  262. package/src/connector/mcp/client.ts +4 -0
  263. package/src/connector/mcp/index.ts +1 -0
  264. package/src/connector/mcp/streamable-http.test.ts +169 -0
  265. package/src/connector/mcp/streamable-http.ts +152 -0
  266. package/src/{runtime/query → constants}/continuation.ts +5 -0
  267. package/src/constants/index.ts +1 -0
  268. package/src/manager/run/persistence.ts +34 -1
  269. package/src/persona/assembler.ts +18 -6
  270. package/src/provider/capabilities.ts +47 -0
  271. package/src/provider/collect.ts +4 -1
  272. package/src/provider/index.ts +5 -0
  273. package/src/public-runtime.ts +5 -0
  274. package/src/registry/tool/execute.test.ts +85 -10
  275. package/src/registry/tool/execute.ts +124 -21
  276. package/src/registry/toolset/catalog.test.ts +68 -0
  277. package/src/run/reporter.ts +9 -0
  278. package/src/runtime/query/__tests__/capability-negotiation.test.ts +248 -0
  279. package/src/runtime/query/__tests__/checkpoint-store.test.ts +322 -0
  280. package/src/runtime/query/__tests__/checkpoint.test.ts +15 -6
  281. package/src/runtime/query/__tests__/deferred-tools.test.ts +52 -5
  282. package/src/runtime/query/__tests__/long-document-flow.test.ts +180 -0
  283. package/src/runtime/query/__tests__/orphan-task-turn-end.test.ts +127 -0
  284. package/src/runtime/query/__tests__/prompt.test.ts +15 -11
  285. package/src/runtime/query/checkpoint.ts +23 -9
  286. package/src/runtime/query/context.ts +9 -0
  287. package/src/runtime/query/index.ts +148 -29
  288. package/src/runtime/query/iteration/index.ts +316 -831
  289. package/src/runtime/query/iteration/phases/checkpoint.ts +32 -2
  290. package/src/runtime/query/iteration/phases/compaction.ts +89 -3
  291. package/src/runtime/query/iteration/phases/context.ts +59 -3
  292. package/src/runtime/query/iteration/phases/hitl-abort-race.test.ts +86 -0
  293. package/src/runtime/query/iteration/phases/hitl-answer-question.test.ts +139 -0
  294. package/src/runtime/query/iteration/phases/tool-review.ts +7 -3
  295. package/src/runtime/query/iteration/phases/working-memory-compaction.test.ts +215 -0
  296. package/src/runtime/query/iteration/phases/working-memory.ts +86 -0
  297. package/src/runtime/query/iteration/stream-turn.ts +396 -0
  298. package/src/runtime/query/replay/list.ts +38 -4
  299. package/src/runtime/query/replay/prepare.ts +37 -4
  300. package/src/session/workspace/__tests__/shared-run.test.ts +1 -1
  301. package/src/session/workspace/shared-run.ts +1 -0
  302. package/src/skills/loader.test.ts +8 -8
  303. package/src/store/index.ts +1 -0
  304. package/src/store/run/checkpoint-disk.ts +67 -0
  305. package/src/streaming/coalesce.test.ts +3 -3
  306. package/src/tools/builtins/__tests__/payload-budget.test.ts +63 -0
  307. package/src/tools/builtins/__tests__/read-file.test.ts +12 -0
  308. package/src/tools/builtins/read-file.ts +50 -2
  309. package/src/tools/builtins/search-tools.ts +38 -7
  310. package/src/tools/coordinator/__tests__/approve-plan.test.ts +139 -0
  311. package/src/tools/coordinator/__tests__/ask-user-question.test.ts +370 -0
  312. package/src/tools/coordinator/index.ts +227 -17
  313. package/src/types/agent/index.ts +1 -0
  314. package/src/types/agent/reactive.ts +17 -0
  315. package/src/types/agent/supervisor.ts +20 -0
  316. package/src/types/agent/working-memory.ts +29 -0
  317. package/src/types/common/index.ts +19 -0
  318. package/src/types/common/usage-merge.test.ts +53 -0
  319. package/src/types/connector/mcp.ts +14 -2
  320. package/src/types/hitl/index.ts +52 -1
  321. package/src/types/provider/chat.ts +10 -0
  322. package/src/types/provider/config.ts +18 -0
  323. package/src/types/provider/interface.ts +11 -0
  324. package/src/types/run/checkpoint-store.ts +72 -0
  325. package/src/types/run/config.ts +30 -0
  326. package/src/types/run/events.ts +13 -0
  327. package/src/types/run/index.ts +1 -0
  328. package/src/version.ts +26 -4
  329. package/dist/runtime/query/continuation.d.ts.map +0 -1
  330. package/dist/runtime/query/continuation.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import { RunDiskStore } from '../../../store/run/disk.js'
2
2
  import type { RunId } from '../../../types/ids/index.js'
3
+ import type { CheckpointRunScope, CheckpointStore } from '../../../types/run/checkpoint-store.js'
3
4
  import type { CheckpointListEntry } from '../../../types/run/replay.js'
4
5
  import type { Logger } from '../../../utils/logger.js'
5
- import { CheckpointManager } from '../checkpoint.js'
6
+ import { toCheckpointListEntry } from '../checkpoint.js'
6
7
 
7
8
  export interface ListCheckpointsInput {
8
9
  /** Directory that contains `<runId>/` for the target run. */
@@ -10,6 +11,15 @@ export interface ListCheckpointsInput {
10
11
  /** Run whose checkpoints should be listed. */
11
12
  runId: RunId
12
13
  logger?: Logger
14
+ /**
15
+ * Optional store override (host-injected, e.g. Postgres). When set,
16
+ * `scope` is required — a scope-keyed backend cannot be addressed by
17
+ * `baseDir` — and `baseDir` is ignored. Absent ⇒ the disk layout under
18
+ * `baseDir` is read, exactly as before.
19
+ */
20
+ checkpointStore?: CheckpointStore
21
+ /** Run scope for `checkpointStore`. Required when it is set. */
22
+ scope?: CheckpointRunScope
13
23
  }
14
24
 
15
25
  /**
@@ -19,14 +29,38 @@ export interface ListCheckpointsInput {
19
29
  * pick a fork point — not the full `IterationCheckpoint` payload.
20
30
  *
21
31
  * Entries are returned in the order the underlying store returns them
22
- * (disk store sorts by `createdAt` ascending). Callers that want a
32
+ * (stores sort by `createdAt` ascending). Callers that want a
23
33
  * specific order should sort client-side.
24
34
  *
25
35
  * See ses_005-deterministic-replay/design.md §3.1.
26
36
  */
27
37
  export async function listCheckpoints(input: ListCheckpointsInput): Promise<CheckpointListEntry[]> {
38
+ const checkpoints = await listRawCheckpoints(input)
39
+ return checkpoints.map(toCheckpointListEntry)
40
+ }
41
+
42
+ async function listRawCheckpoints(input: ListCheckpointsInput) {
43
+ if (input.checkpointStore) {
44
+ return input.checkpointStore.listCheckpoints(requireScope(input.scope, 'listCheckpoints'))
45
+ }
28
46
  const store = new RunDiskStore({ baseDir: input.baseDir, logger: input.logger })
29
47
  await store.initRun(input.runId)
30
- const mgr = new CheckpointManager(store)
31
- return mgr.listEntries()
48
+ return store.listCheckpoints()
49
+ }
50
+
51
+ /**
52
+ * Guard shared by the replay entry points: an injected {@link
53
+ * CheckpointStore} is scope-keyed, so the caller must say which run —
54
+ * across the full five-layer attribution — it is asking about.
55
+ */
56
+ export function requireScope(
57
+ scope: CheckpointRunScope | undefined,
58
+ caller: string,
59
+ ): CheckpointRunScope {
60
+ if (!scope) {
61
+ throw new Error(
62
+ `${caller}: \`checkpointStore\` was provided without \`scope\` — an injected store is keyed by tenantId/projectId/sessionId/runId, not by baseDir.`,
63
+ )
64
+ }
65
+ return scope
32
66
  }
@@ -4,9 +4,11 @@ import { RunDiskStore } from '../../../store/run/disk.js'
4
4
  import type { CheckpointId, IterationCheckpoint } from '../../../types/hitl/index.js'
5
5
  import type { RunId } from '../../../types/ids/index.js'
6
6
  import type { Message } from '../../../types/message/index.js'
7
+ import type { CheckpointRunScope, CheckpointStore } from '../../../types/run/checkpoint-store.js'
7
8
  import type { Mutation, ReplayAttribution } from '../../../types/run/replay.js'
8
9
  import type { Logger } from '../../../utils/logger.js'
9
10
  import { projectEmergencyToCheckpoint } from '../checkpoint.js'
11
+ import { requireScope } from './list.js'
10
12
  import { applyMutations } from './mutate.js'
11
13
 
12
14
  export type CheckpointSelector = CheckpointId | 'latest' | 'emergency'
@@ -27,6 +29,15 @@ export interface PrepareReplayInput {
27
29
  */
28
30
  emergencyDir?: string
29
31
  logger?: Logger
32
+ /**
33
+ * Optional store override (host-injected, e.g. Postgres). When set,
34
+ * `scope` is required and `baseDir` is ignored for checkpoint reads.
35
+ * The `'emergency'` selector still reads the on-disk dump under
36
+ * `emergencyDir` — emergency saves are process-local by nature.
37
+ */
38
+ checkpointStore?: CheckpointStore
39
+ /** Run scope for `checkpointStore`. Required when it is set. */
40
+ scope?: CheckpointRunScope
30
41
  }
31
42
 
32
43
  export interface PreparedReplayState {
@@ -80,24 +91,46 @@ async function resolveCheckpoint(input: PrepareReplayInput): Promise<IterationCh
80
91
  if (input.fromCheckpoint === 'emergency') {
81
92
  return resolveEmergency(input)
82
93
  }
83
- const store = new RunDiskStore({ baseDir: input.baseDir, logger: input.logger })
84
- await store.initRun(input.runId)
94
+
95
+ const reader = await bindCheckpointReader(input)
85
96
 
86
97
  if (input.fromCheckpoint === 'latest') {
87
- const all = await store.listCheckpoints()
98
+ const all = await reader.list()
88
99
  if (all.length === 0) {
89
100
  throw new Error(`No checkpoints found for run ${input.runId} in ${input.baseDir}`)
90
101
  }
91
102
  return [...all].sort((a, b) => b.iteration - a.iteration)[0] as IterationCheckpoint
92
103
  }
93
104
 
94
- const checkpoint = await store.readCheckpoint(input.fromCheckpoint)
105
+ const checkpoint = await reader.read(input.fromCheckpoint)
95
106
  if (!checkpoint) {
96
107
  throw new Error(`Checkpoint ${input.fromCheckpoint} not found for run ${input.runId}`)
97
108
  }
98
109
  return checkpoint
99
110
  }
100
111
 
112
+ interface CheckpointReader {
113
+ list(): Promise<IterationCheckpoint[]>
114
+ read(id: CheckpointId): Promise<IterationCheckpoint | null>
115
+ }
116
+
117
+ async function bindCheckpointReader(input: PrepareReplayInput): Promise<CheckpointReader> {
118
+ if (input.checkpointStore) {
119
+ const store = input.checkpointStore
120
+ const scope = requireScope(input.scope, 'prepareReplayState')
121
+ return {
122
+ list: () => store.listCheckpoints(scope),
123
+ read: (id) => store.readCheckpoint(scope, id),
124
+ }
125
+ }
126
+ const store = new RunDiskStore({ baseDir: input.baseDir, logger: input.logger })
127
+ await store.initRun(input.runId)
128
+ return {
129
+ list: () => store.listCheckpoints(),
130
+ read: (id) => store.readCheckpoint(id),
131
+ }
132
+ }
133
+
101
134
  async function resolveEmergency(input: PrepareReplayInput): Promise<IterationCheckpoint> {
102
135
  if (!input.emergencyDir) {
103
136
  throw new Error(
@@ -148,7 +148,7 @@ describe('SharedRunWorkspace', () => {
148
148
  runtimeRoot: '/mnt/user-data/outputs/_work',
149
149
  })
150
150
 
151
- const big = '# Task Context\n\n' + 'A'.repeat(40_000)
151
+ const big = `# Task Context\n\n${'A'.repeat(40_000)}`
152
152
  const path = await workspace.writeTaskContext(big)
153
153
  expect(path).toBe('/mnt/user-data/outputs/_work/01_task_context.md')
154
154
  expect(workspace.refs().taskContextPath).toBe(path)
@@ -295,6 +295,7 @@ function ensureTrailingNewline(value: string): string {
295
295
  }
296
296
 
297
297
  async function writeJsonAtomic(path: string, value: unknown): Promise<void> {
298
+ await mkdir(dirnameFor(path), { recursive: true })
298
299
  const tmpPath = `${path}.${process.pid}.${Date.now()}.tmp`
299
300
  await writeFile(tmpPath, `${JSON.stringify(value, null, 2)}\n`, 'utf8')
300
301
  await rename(tmpPath, path)
@@ -16,11 +16,11 @@ describe('Agent Skills loader', () => {
16
16
  const root = await mkdtemp(join(tmpdir(), 'namzu-skills-'))
17
17
  const dir = await writeSkill(
18
18
  root,
19
- 'project-documents',
19
+ 'delivery-briefing',
20
20
  [
21
21
  '---',
22
- 'name: project-documents',
23
- 'description: Draft and edit grounded project documents.',
22
+ 'name: delivery-briefing',
23
+ 'description: Draft and edit grounded delivery briefings.',
24
24
  'license: MIT',
25
25
  'compatibility: Requires filesystem tools',
26
26
  'allowed-tools: read write edit',
@@ -36,8 +36,8 @@ describe('Agent Skills loader', () => {
36
36
  const result = await loadSkill(dir, 'metadata')
37
37
 
38
38
  expect(result.skill.metadata).toEqual({
39
- name: 'project-documents',
40
- description: 'Draft and edit grounded project documents.',
39
+ name: 'delivery-briefing',
40
+ description: 'Draft and edit grounded delivery briefings.',
41
41
  license: 'MIT',
42
42
  compatibility: 'Requires filesystem tools',
43
43
  allowedTools: 'read write edit',
@@ -53,11 +53,11 @@ describe('Agent Skills loader', () => {
53
53
  const root = await mkdtemp(join(tmpdir(), 'namzu-skills-'))
54
54
  const dir = await writeSkill(
55
55
  root,
56
- 'long-form-files',
56
+ 'structured-file-authoring',
57
57
  [
58
58
  '---',
59
- 'name: long-form-files',
60
- 'description: Create long files with bounded edit chunks.',
59
+ 'name: structured-file-authoring',
60
+ 'description: Create structured files with bounded edit chunks.',
61
61
  '---',
62
62
  'Use skeleton-first writes.',
63
63
  '',
@@ -2,6 +2,7 @@ export { InMemoryStore } from './InMemoryStore.js'
2
2
  export type { Identifiable, Timestamped } from './InMemoryStore.js'
3
3
 
4
4
  export { RunDiskStore } from './run/disk.js'
5
+ export { DiskCheckpointStore } from './run/checkpoint-disk.js'
5
6
 
6
7
  export { ActivityStore } from './activity/memory.js'
7
8
  export type { ActivityEvent, ActivityEventListener } from './activity/memory.js'
@@ -0,0 +1,67 @@
1
+ import type { CheckpointId, IterationCheckpoint } from '../../types/hitl/index.js'
2
+ import type { RunId } from '../../types/ids/index.js'
3
+ import type { CheckpointRunScope, CheckpointStore } from '../../types/run/checkpoint-store.js'
4
+ import type { RunStoreConfig } from '../../types/run/index.js'
5
+ import { RunDiskStore } from './disk.js'
6
+
7
+ /**
8
+ * Disk conformance layer for {@link CheckpointStore}: adapts the existing
9
+ * {@link RunDiskStore} checkpoint methods (which are bound to a single run
10
+ * directory via `initRun`) to the scope-keyed store contract.
11
+ *
12
+ * Path-addressed: `baseDir` already encodes project/session (it is the
13
+ * session's `runs/` directory), so only `scope.runId` / `scope.parentRunId`
14
+ * participate in directory resolution — `tenantId`/`projectId`/`sessionId`
15
+ * exist for backends that key by attribution instead of path.
16
+ *
17
+ * One `RunDiskStore` is bound (and its run directory created) per distinct
18
+ * `runId`, then cached, so repeated checkpoint operations against the same
19
+ * run don't re-run `initRun`.
20
+ */
21
+ export class DiskCheckpointStore implements CheckpointStore {
22
+ private readonly config: RunStoreConfig
23
+ private readonly bound = new Map<RunId, Promise<RunDiskStore>>()
24
+
25
+ constructor(config: RunStoreConfig) {
26
+ this.config = config
27
+ }
28
+
29
+ private bind(scope: CheckpointRunScope): Promise<RunDiskStore> {
30
+ const cached = this.bound.get(scope.runId)
31
+ if (cached) return cached
32
+ const promise = (async () => {
33
+ const store = new RunDiskStore(this.config)
34
+ await store.initRun(scope.runId, scope.parentRunId)
35
+ return store
36
+ })()
37
+ this.bound.set(scope.runId, promise)
38
+ // A failed bind must not poison the cache — the next call retries.
39
+ promise.catch(() => {
40
+ this.bound.delete(scope.runId)
41
+ })
42
+ return promise
43
+ }
44
+
45
+ async writeCheckpoint(scope: CheckpointRunScope, checkpoint: IterationCheckpoint): Promise<void> {
46
+ const store = await this.bind(scope)
47
+ await store.writeCheckpoint(checkpoint)
48
+ }
49
+
50
+ async readCheckpoint(
51
+ scope: CheckpointRunScope,
52
+ checkpointId: CheckpointId,
53
+ ): Promise<IterationCheckpoint | null> {
54
+ const store = await this.bind(scope)
55
+ return store.readCheckpoint(checkpointId)
56
+ }
57
+
58
+ async listCheckpoints(scope: CheckpointRunScope): Promise<IterationCheckpoint[]> {
59
+ const store = await this.bind(scope)
60
+ return store.listCheckpoints()
61
+ }
62
+
63
+ async deleteCheckpoint(scope: CheckpointRunScope, checkpointId: CheckpointId): Promise<void> {
64
+ const store = await this.bind(scope)
65
+ await store.deleteCheckpoint(checkpointId)
66
+ }
67
+ }
@@ -117,14 +117,14 @@ describe('coalesce()', () => {
117
117
  })
118
118
 
119
119
  it('emits new event after window expires', async () => {
120
- const events: RunEvent[] = [
120
+ const events: [RunEvent, RunEvent] = [
121
121
  { type: 'text_delta', runId: RID, iteration: 0, messageId: MID, text: 'a' },
122
122
  { type: 'text_delta', runId: RID, iteration: 0, messageId: MID, text: 'b' },
123
123
  ]
124
124
  const stream: AsyncIterable<RunEvent> = (async function* () {
125
- yield events[0]!
125
+ yield events[0]
126
126
  await new Promise((r) => setTimeout(r, 30))
127
- yield events[1]!
127
+ yield events[1]
128
128
  })()
129
129
  const result = await drain(coalesce(stream, { windowMs: 16 }))
130
130
  expect(result).toHaveLength(2)
@@ -1,4 +1,8 @@
1
+ import { mkdtempSync, readFileSync } from 'node:fs'
2
+ import { tmpdir } from 'node:os'
3
+ import { join } from 'node:path'
1
4
  import { describe, expect, it } from 'vitest'
5
+ import type { ToolContext } from '../../../types/tool/index.js'
2
6
  import { EditTool } from '../edit.js'
3
7
  import { getBuiltinTools } from '../index.js'
4
8
  import { WriteFileTool } from '../write-file.js'
@@ -26,4 +30,63 @@ describe('filesystem tool payload budgeting', () => {
26
30
  expect(names).toContain('edit')
27
31
  expect(names).not.toContain('append')
28
32
  })
33
+
34
+ it('assembles long documents with bounded write plus edit insert chunks', async () => {
35
+ const dir = mkdtempSync(join(tmpdir(), 'namzu-long-doc-'))
36
+ const ctx: ToolContext = {
37
+ runId: 'run_test' as ToolContext['runId'],
38
+ workingDirectory: dir,
39
+ abortSignal: new AbortController().signal,
40
+ env: {},
41
+ log: () => {},
42
+ }
43
+ const opening = '# Long document regression\n\n{{BODY}}\n'
44
+ const chunks = Array.from({ length: 6 }, (_, sectionIndex) => {
45
+ const lines = Array.from({ length: 45 }, (_, lineIndex) => {
46
+ const section = sectionIndex + 1
47
+ const line = lineIndex + 1
48
+ return `Section ${section}.${line}: this bounded paragraph proves long-form output grows through edit insertions rather than one oversized JSON tool argument.`
49
+ })
50
+ const chunk = [`## Section ${sectionIndex + 1}`, ...lines, ''].join('\n')
51
+ expect(chunk.length).toBeLessThan(12_000)
52
+ return chunk
53
+ })
54
+
55
+ const writeResult = await WriteFileTool.execute(
56
+ { path: 'outputs/regression-long-document.md', content: opening },
57
+ ctx,
58
+ )
59
+ expect(writeResult.success).toBe(true)
60
+
61
+ const firstEdit = await EditTool.execute(
62
+ {
63
+ path: 'outputs/regression-long-document.md',
64
+ oldStr: '{{BODY}}',
65
+ newStr: chunks[0],
66
+ replace_all: false,
67
+ },
68
+ ctx,
69
+ )
70
+ expect(firstEdit.success).toBe(true)
71
+
72
+ for (const chunk of chunks.slice(1)) {
73
+ const result = await EditTool.execute(
74
+ {
75
+ path: 'outputs/regression-long-document.md',
76
+ insertLine: 'end',
77
+ newStr: chunk,
78
+ replace_all: false,
79
+ },
80
+ ctx,
81
+ )
82
+ expect(result.success).toBe(true)
83
+ }
84
+
85
+ const final = readFileSync(join(dir, 'outputs/regression-long-document.md'), 'utf-8')
86
+ expect(final).not.toContain('{{BODY}}')
87
+ expect(final.split('\n').length).toBeGreaterThan(250)
88
+ expect(final).toContain('## Section 1')
89
+ expect(final).toContain('## Section 6')
90
+ expect(final).toContain('Section 6.45')
91
+ })
29
92
  })
@@ -28,4 +28,16 @@ describe('ReadFileTool', () => {
28
28
  expect(result.success).toBe(true)
29
29
  expect(result.output).toBe('2\ttwo\n3\tthree')
30
30
  })
31
+
32
+ it('guides binary Office documents through extractor tooling', async () => {
33
+ const dir = mkdtempSync(join(tmpdir(), 'namzu-read-'))
34
+ writeFileSync(join(dir, 'transcript.docx'), Buffer.from('PK\x03\x04binary-docx'))
35
+
36
+ const result = await ReadFileTool.execute({ path: 'transcript.docx' }, makeContext(dir))
37
+
38
+ expect(result.success).toBe(false)
39
+ expect(result.output).toContain('DOCX document package')
40
+ expect(result.output).toContain('python-docx')
41
+ expect(result.data).toMatchObject({ binary: true })
42
+ })
31
43
  })
@@ -1,5 +1,5 @@
1
1
  import { readFile } from 'node:fs/promises'
2
- import { resolve } from 'node:path'
2
+ import { extname, resolve } from 'node:path'
3
3
  import { z } from 'zod'
4
4
  import { defineTool } from '../defineTool.js'
5
5
 
@@ -35,6 +35,18 @@ export const ReadFileTool = defineTool({
35
35
  // Sandbox-aware: route through sandbox.readFile() when available
36
36
  if (context.sandbox) {
37
37
  const buffer = await context.sandbox.readFile(input.path)
38
+ const binaryGuidance = describeStructuredBinaryRead(input.path, buffer)
39
+ if (binaryGuidance) {
40
+ return {
41
+ success: false,
42
+ output: binaryGuidance,
43
+ data: {
44
+ path: input.path,
45
+ sandboxed: true,
46
+ binary: true,
47
+ },
48
+ }
49
+ }
38
50
  const content = buffer.toString('utf-8')
39
51
  const lines = content.split('\n')
40
52
 
@@ -58,7 +70,19 @@ export const ReadFileTool = defineTool({
58
70
  }
59
71
 
60
72
  const filePath = resolve(context.workingDirectory, input.path)
61
- const content = await readFile(filePath, 'utf-8')
73
+ const buffer = await readFile(filePath)
74
+ const binaryGuidance = describeStructuredBinaryRead(filePath, buffer)
75
+ if (binaryGuidance) {
76
+ return {
77
+ success: false,
78
+ output: binaryGuidance,
79
+ data: {
80
+ path: filePath,
81
+ binary: true,
82
+ },
83
+ }
84
+ }
85
+ const content = buffer.toString('utf-8')
62
86
  const lines = content.split('\n')
63
87
 
64
88
  const { start, end } = resolveReadWindow(input, lines.length)
@@ -80,6 +104,30 @@ export const ReadFileTool = defineTool({
80
104
  },
81
105
  })
82
106
 
107
+ function describeStructuredBinaryRead(path: string, buffer: Buffer): string | null {
108
+ const ext = extname(path).toLowerCase()
109
+ if (ext === '.docx') return buildStructuredBinaryGuidance(path, 'DOCX', 'python-docx')
110
+ if (ext === '.pptx') return buildStructuredBinaryGuidance(path, 'PPTX', 'python-pptx')
111
+ if (ext === '.xlsx') return buildStructuredBinaryGuidance(path, 'XLSX', 'openpyxl')
112
+ if (ext === '.pdf' || startsWithPdfHeader(buffer)) {
113
+ return buildStructuredBinaryGuidance(path, 'PDF', 'pdftotext or PyMuPDF')
114
+ }
115
+ return null
116
+ }
117
+
118
+ function startsWithPdfHeader(buffer: Buffer): boolean {
119
+ return buffer.length >= 4 && buffer.subarray(0, 4).toString('utf8') === '%PDF'
120
+ }
121
+
122
+ function buildStructuredBinaryGuidance(path: string, format: string, extractor: string): string {
123
+ return [
124
+ `The file "${path}" is a ${format} document package, not UTF-8 text.`,
125
+ 'Do not use the read/cat tools as evidence for this raw file.',
126
+ `Extract its text with shell/Python tooling already available in the sandbox (${extractor}), write the extracted text or summary under scratch, then read that text file.`,
127
+ 'If extraction fails, report the exact filename and extraction error instead of claiming the attachment is unavailable.',
128
+ ].join('\n')
129
+ }
130
+
83
131
  function resolveReadWindow(
84
132
  input: z.infer<typeof inputSchema>,
85
133
  totalLines: number,
@@ -1,10 +1,22 @@
1
1
  import { z } from 'zod'
2
+ import { toolDiscoveryHint } from '../../registry/tool/execute.js'
2
3
  import { defineTool } from '../defineTool.js'
3
4
 
4
5
  const inputSchema = z.object({
5
6
  query: z.string().describe('Tool name or capability keyword to search for'),
6
7
  })
7
8
 
9
+ // Activate only the best-ranked matches. Top-5 is the literature's sweet
10
+ // spot (retrieval at k=5 matches oracle toolsets) and bounds how much
11
+ // schema weight a single search can add to every subsequent iteration —
12
+ // each activation also busts the prompt-cache prefix once.
13
+ const ACTIVATION_TOP_K = 5
14
+
15
+ // Near-misses are reported name+hint WITHOUT activating, so a retrieval
16
+ // miss becomes one cheap re-query instead of a dead end (the fixed-top-k
17
+ // hard-tail failure mode: the right tool ranked 6th-10th).
18
+ const NEAR_MISS_LIMIT = 5
19
+
8
20
  export const SearchToolsTool = defineTool({
9
21
  name: 'search_tools',
10
22
  description:
@@ -28,27 +40,46 @@ export const SearchToolsTool = defineTool({
28
40
 
29
41
  const allowed =
30
42
  context.allowedTools && context.allowedTools.length > 0 ? new Set(context.allowedTools) : null
31
- const matches = context.toolRegistry
43
+ // `searchDeferred` returns a ranked list (score-descending), so slicing
44
+ // the head is a true top-k activation, not an arbitrary subset.
45
+ const ranked = context.toolRegistry
32
46
  .searchDeferred(input.query)
33
47
  .filter((tool) => !allowed || allowed.has(tool.name))
34
48
 
35
- if (matches.length === 0) {
49
+ if (ranked.length === 0) {
36
50
  return {
37
51
  success: true,
38
52
  output: `No deferred tools matching "${input.query}". All matching tools are already active.`,
39
53
  }
40
54
  }
41
55
 
42
- context.toolRegistry.activate(matches.map((t) => t.name))
56
+ const activated = ranked.slice(0, ACTIVATION_TOP_K)
57
+ const nearMisses = ranked.slice(ACTIVATION_TOP_K, ACTIVATION_TOP_K + NEAR_MISS_LIMIT)
58
+
59
+ context.toolRegistry.activate(activated.map((t) => t.name))
43
60
 
44
- const descriptions = matches.map((t) => `- ${t.name}: ${t.description}`).join('\n')
61
+ const descriptions = activated.map((t) => `- ${t.name}: ${t.description}`).join('\n')
62
+ const sections = [`Activated ${activated.length} tool(s):\n${descriptions}`]
63
+
64
+ if (nearMisses.length > 0) {
65
+ const hints = nearMisses
66
+ .map((t) => {
67
+ const hint = toolDiscoveryHint(t.description)
68
+ return hint.length > 0 ? `- ${t.name}: ${hint}` : `- ${t.name}`
69
+ })
70
+ .join('\n')
71
+ sections.push(
72
+ `Also matched but NOT loaded (search again with a more specific query, e.g. the tool name, to load one of these):\n${hints}`,
73
+ )
74
+ }
45
75
 
46
76
  return {
47
77
  success: true,
48
- output: `Activated ${matches.length} tool(s):\n${descriptions}`,
78
+ output: sections.join('\n\n'),
49
79
  data: {
50
- activated: matches.map((t) => t.name),
51
- count: matches.length,
80
+ activated: activated.map((t) => t.name),
81
+ count: activated.length,
82
+ nearMisses: nearMisses.map((t) => t.name),
52
83
  },
53
84
  }
54
85
  },