@namzu/sdk 36.0.0 → 38.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 (412) hide show
  1. package/CHANGELOG.md +244 -0
  2. package/README.md +68 -41
  3. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  4. package/dist/bridge/a2a/mapper.js +4 -0
  5. package/dist/bridge/a2a/mapper.js.map +1 -1
  6. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  7. package/dist/bridge/sse/mapper.js +16 -1
  8. package/dist/bridge/sse/mapper.js.map +1 -1
  9. package/dist/compaction/extractor.d.ts +1 -1
  10. package/dist/compaction/extractor.d.ts.map +1 -1
  11. package/dist/compaction/extractor.js +15 -7
  12. package/dist/compaction/extractor.js.map +1 -1
  13. package/dist/compaction/manager.d.ts +2 -0
  14. package/dist/compaction/manager.d.ts.map +1 -1
  15. package/dist/compaction/manager.js +12 -1
  16. package/dist/compaction/manager.js.map +1 -1
  17. package/dist/compaction/verifier.d.ts.map +1 -1
  18. package/dist/compaction/verifier.js +82 -15
  19. package/dist/compaction/verifier.js.map +1 -1
  20. package/dist/config/runtime.d.ts +16 -6
  21. package/dist/config/runtime.d.ts.map +1 -1
  22. package/dist/config/runtime.js +2 -0
  23. package/dist/config/runtime.js.map +1 -1
  24. package/dist/contracts/api.d.ts +1 -1
  25. package/dist/contracts/api.d.ts.map +1 -1
  26. package/dist/contracts/schemas.d.ts +10 -10
  27. package/dist/eval/harness-verification.d.ts +63 -0
  28. package/dist/eval/harness-verification.d.ts.map +1 -0
  29. package/dist/eval/harness-verification.js +165 -0
  30. package/dist/eval/harness-verification.js.map +1 -0
  31. package/dist/eval/index.d.ts +2 -0
  32. package/dist/eval/index.d.ts.map +1 -1
  33. package/dist/eval/index.js +1 -0
  34. package/dist/eval/index.js.map +1 -1
  35. package/dist/execution/code-runtime/json-value.d.ts +10 -0
  36. package/dist/execution/code-runtime/json-value.d.ts.map +1 -0
  37. package/dist/execution/code-runtime/json-value.js +89 -0
  38. package/dist/execution/code-runtime/json-value.js.map +1 -0
  39. package/dist/execution/code-runtime/worker-program.d.ts +8 -0
  40. package/dist/execution/code-runtime/worker-program.d.ts.map +1 -0
  41. package/dist/execution/code-runtime/worker-program.js +240 -0
  42. package/dist/execution/code-runtime/worker-program.js.map +1 -0
  43. package/dist/execution/code-runtime/worker.d.ts +22 -0
  44. package/dist/execution/code-runtime/worker.d.ts.map +1 -1
  45. package/dist/execution/code-runtime/worker.js +148 -111
  46. package/dist/execution/code-runtime/worker.js.map +1 -1
  47. package/dist/manager/agent/lifecycle.d.ts +12 -0
  48. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  49. package/dist/manager/agent/lifecycle.js +316 -46
  50. package/dist/manager/agent/lifecycle.js.map +1 -1
  51. package/dist/manager/run/persistence.d.ts +2 -0
  52. package/dist/manager/run/persistence.d.ts.map +1 -1
  53. package/dist/manager/run/persistence.js +6 -0
  54. package/dist/manager/run/persistence.js.map +1 -1
  55. package/dist/prompt/coding-agent-doctrine.d.ts +2 -2
  56. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  57. package/dist/prompt/coding-agent-doctrine.js +11 -5
  58. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  59. package/dist/provider/capabilities.d.ts +5 -1
  60. package/dist/provider/capabilities.d.ts.map +1 -1
  61. package/dist/provider/capabilities.js +24 -0
  62. package/dist/provider/capabilities.js.map +1 -1
  63. package/dist/provider/fallback.d.ts.map +1 -1
  64. package/dist/provider/fallback.js +6 -2
  65. package/dist/provider/fallback.js.map +1 -1
  66. package/dist/public-runtime.d.ts +4 -1
  67. package/dist/public-runtime.d.ts.map +1 -1
  68. package/dist/public-runtime.js +3 -1
  69. package/dist/public-runtime.js.map +1 -1
  70. package/dist/public-tools.d.ts +2 -1
  71. package/dist/public-tools.d.ts.map +1 -1
  72. package/dist/public-tools.js +2 -1
  73. package/dist/public-tools.js.map +1 -1
  74. package/dist/public-types.d.ts +2 -0
  75. package/dist/public-types.d.ts.map +1 -1
  76. package/dist/registry/tool/execute.d.ts +3 -0
  77. package/dist/registry/tool/execute.d.ts.map +1 -1
  78. package/dist/registry/tool/execute.js +11 -80
  79. package/dist/registry/tool/execute.js.map +1 -1
  80. package/dist/run/command-gate.d.ts.map +1 -1
  81. package/dist/run/command-gate.js +65 -12
  82. package/dist/run/command-gate.js.map +1 -1
  83. package/dist/run/index.d.ts +2 -0
  84. package/dist/run/index.d.ts.map +1 -1
  85. package/dist/run/index.js +1 -0
  86. package/dist/run/index.js.map +1 -1
  87. package/dist/run/memory-promoter.d.ts +3 -35
  88. package/dist/run/memory-promoter.d.ts.map +1 -1
  89. package/dist/run/memory-promoter.js +32 -40
  90. package/dist/run/memory-promoter.js.map +1 -1
  91. package/dist/run/memory-recall.d.ts +25 -0
  92. package/dist/run/memory-recall.d.ts.map +1 -0
  93. package/dist/run/memory-recall.js +228 -0
  94. package/dist/run/memory-recall.js.map +1 -0
  95. package/dist/run/reporter.d.ts.map +1 -1
  96. package/dist/run/reporter.js +2 -0
  97. package/dist/run/reporter.js.map +1 -1
  98. package/dist/run/token-budget.d.ts +12 -4
  99. package/dist/run/token-budget.d.ts.map +1 -1
  100. package/dist/run/token-budget.js +49 -14
  101. package/dist/run/token-budget.js.map +1 -1
  102. package/dist/run/workspace-fingerprint.d.ts +10 -3
  103. package/dist/run/workspace-fingerprint.d.ts.map +1 -1
  104. package/dist/run/workspace-fingerprint.js +17 -8
  105. package/dist/run/workspace-fingerprint.js.map +1 -1
  106. package/dist/runtime/query/checkpoint.d.ts +14 -0
  107. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  108. package/dist/runtime/query/checkpoint.js +82 -1
  109. package/dist/runtime/query/checkpoint.js.map +1 -1
  110. package/dist/runtime/query/executor.d.ts +8 -3
  111. package/dist/runtime/query/executor.d.ts.map +1 -1
  112. package/dist/runtime/query/executor.js +94 -30
  113. package/dist/runtime/query/executor.js.map +1 -1
  114. package/dist/runtime/query/index.d.ts +7 -8
  115. package/dist/runtime/query/index.d.ts.map +1 -1
  116. package/dist/runtime/query/index.js +55 -7
  117. package/dist/runtime/query/index.js.map +1 -1
  118. package/dist/runtime/query/iteration/index.d.ts +12 -0
  119. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  120. package/dist/runtime/query/iteration/index.js +348 -38
  121. package/dist/runtime/query/iteration/index.js.map +1 -1
  122. package/dist/runtime/query/iteration/native-output.d.ts +10 -0
  123. package/dist/runtime/query/iteration/native-output.d.ts.map +1 -0
  124. package/dist/runtime/query/iteration/native-output.js +32 -0
  125. package/dist/runtime/query/iteration/native-output.js.map +1 -0
  126. package/dist/runtime/query/iteration/phases/advisory.d.ts.map +1 -1
  127. package/dist/runtime/query/iteration/phases/advisory.js +18 -13
  128. package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
  129. package/dist/runtime/query/iteration/phases/compaction.d.ts +2 -0
  130. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  131. package/dist/runtime/query/iteration/phases/compaction.js +32 -11
  132. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  133. package/dist/runtime/query/iteration/phases/context.d.ts +9 -0
  134. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  135. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  136. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  137. package/dist/runtime/query/iteration/phases/tool-review.js +1 -1
  138. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  139. package/dist/runtime/query/iteration/phases/working-memory.d.ts +1 -1
  140. package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -1
  141. package/dist/runtime/query/iteration/phases/working-memory.js +23 -6
  142. package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -1
  143. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  144. package/dist/runtime/query/iteration/stream-turn.js +12 -0
  145. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  146. package/dist/runtime/query/observation-context.d.ts +10 -0
  147. package/dist/runtime/query/observation-context.d.ts.map +1 -0
  148. package/dist/runtime/query/observation-context.js +84 -0
  149. package/dist/runtime/query/observation-context.js.map +1 -0
  150. package/dist/runtime/query/request-context.d.ts +30 -0
  151. package/dist/runtime/query/request-context.d.ts.map +1 -0
  152. package/dist/runtime/query/request-context.js +76 -0
  153. package/dist/runtime/query/request-context.js.map +1 -0
  154. package/dist/runtime/query/request-rich-content.d.ts.map +1 -1
  155. package/dist/runtime/query/request-rich-content.js +6 -3
  156. package/dist/runtime/query/request-rich-content.js.map +1 -1
  157. package/dist/runtime/query/review-policy.d.ts +3 -0
  158. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  159. package/dist/runtime/query/review-policy.js +4 -1
  160. package/dist/runtime/query/review-policy.js.map +1 -1
  161. package/dist/runtime/query/steering.d.ts +6 -2
  162. package/dist/runtime/query/steering.d.ts.map +1 -1
  163. package/dist/runtime/query/steering.js +17 -2
  164. package/dist/runtime/query/steering.js.map +1 -1
  165. package/dist/runtime/query/tool-call-budget.d.ts +19 -0
  166. package/dist/runtime/query/tool-call-budget.d.ts.map +1 -0
  167. package/dist/runtime/query/tool-call-budget.js +110 -0
  168. package/dist/runtime/query/tool-call-budget.js.map +1 -0
  169. package/dist/runtime/query/tooling.d.ts +3 -0
  170. package/dist/runtime/query/tooling.d.ts.map +1 -1
  171. package/dist/runtime/query/tooling.js +5 -0
  172. package/dist/runtime/query/tooling.js.map +1 -1
  173. package/dist/sandbox/file-walk-program.d.ts.map +1 -1
  174. package/dist/sandbox/file-walk-program.js +8 -0
  175. package/dist/sandbox/file-walk-program.js.map +1 -1
  176. package/dist/sandbox/file-walk.d.ts.map +1 -1
  177. package/dist/sandbox/file-walk.js +9 -0
  178. package/dist/sandbox/file-walk.js.map +1 -1
  179. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  180. package/dist/scheduler/completion-inbox.js +3 -0
  181. package/dist/scheduler/completion-inbox.js.map +1 -1
  182. package/dist/scheduler/local.d.ts.map +1 -1
  183. package/dist/scheduler/local.js +1 -0
  184. package/dist/scheduler/local.js.map +1 -1
  185. package/dist/session/handoff/capacity.d.ts +2 -2
  186. package/dist/session/handoff/capacity.d.ts.map +1 -1
  187. package/dist/session/handoff/capacity.js +3 -2
  188. package/dist/session/handoff/capacity.js.map +1 -1
  189. package/dist/store/memory/disk.d.ts +6 -2
  190. package/dist/store/memory/disk.d.ts.map +1 -1
  191. package/dist/store/memory/disk.js +42 -25
  192. package/dist/store/memory/disk.js.map +1 -1
  193. package/dist/store/memory/index.d.ts +4 -0
  194. package/dist/store/memory/index.d.ts.map +1 -1
  195. package/dist/store/memory/index.js +55 -19
  196. package/dist/store/memory/index.js.map +1 -1
  197. package/dist/store/memory/memory.d.ts +3 -2
  198. package/dist/store/memory/memory.d.ts.map +1 -1
  199. package/dist/store/memory/memory.js +11 -2
  200. package/dist/store/memory/memory.js.map +1 -1
  201. package/dist/store/memory/operation-lock.d.ts +11 -0
  202. package/dist/store/memory/operation-lock.d.ts.map +1 -0
  203. package/dist/store/memory/operation-lock.js +94 -0
  204. package/dist/store/memory/operation-lock.js.map +1 -0
  205. package/dist/store/run/token-budget-disk.js +3 -0
  206. package/dist/store/run/token-budget-disk.js.map +1 -1
  207. package/dist/tools/builtins/computer-use.d.ts.map +1 -1
  208. package/dist/tools/builtins/computer-use.js +60 -10
  209. package/dist/tools/builtins/computer-use.js.map +1 -1
  210. package/dist/tools/builtins/edit.d.ts.map +1 -1
  211. package/dist/tools/builtins/edit.js +12 -26
  212. package/dist/tools/builtins/edit.js.map +1 -1
  213. package/dist/tools/builtins/file-write-result.d.ts +4 -0
  214. package/dist/tools/builtins/file-write-result.d.ts.map +1 -0
  215. package/dist/tools/builtins/file-write-result.js +72 -0
  216. package/dist/tools/builtins/file-write-result.js.map +1 -0
  217. package/dist/tools/builtins/glob.d.ts.map +1 -1
  218. package/dist/tools/builtins/glob.js +8 -1
  219. package/dist/tools/builtins/glob.js.map +1 -1
  220. package/dist/tools/builtins/grep.d.ts.map +1 -1
  221. package/dist/tools/builtins/grep.js +10 -0
  222. package/dist/tools/builtins/grep.js.map +1 -1
  223. package/dist/tools/builtins/job.d.ts.map +1 -1
  224. package/dist/tools/builtins/job.js +6 -0
  225. package/dist/tools/builtins/job.js.map +1 -1
  226. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  227. package/dist/tools/builtins/read-file.js +10 -0
  228. package/dist/tools/builtins/read-file.js.map +1 -1
  229. package/dist/tools/builtins/run-code.d.ts +6 -0
  230. package/dist/tools/builtins/run-code.d.ts.map +1 -1
  231. package/dist/tools/builtins/run-code.js +15 -4
  232. package/dist/tools/builtins/run-code.js.map +1 -1
  233. package/dist/tools/builtins/search-tools.d.ts.map +1 -1
  234. package/dist/tools/builtins/search-tools.js +14 -2
  235. package/dist/tools/builtins/search-tools.js.map +1 -1
  236. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  237. package/dist/tools/builtins/write-file.js +30 -44
  238. package/dist/tools/builtins/write-file.js.map +1 -1
  239. package/dist/tools/defineTool.d.ts +2 -0
  240. package/dist/tools/defineTool.d.ts.map +1 -1
  241. package/dist/tools/defineTool.js +3 -0
  242. package/dist/tools/defineTool.js.map +1 -1
  243. package/dist/tools/file-read-tracker.d.ts +4 -0
  244. package/dist/tools/file-read-tracker.d.ts.map +1 -0
  245. package/dist/tools/file-read-tracker.js +16 -0
  246. package/dist/tools/file-read-tracker.js.map +1 -0
  247. package/dist/tools/memory/delete.d.ts +4 -0
  248. package/dist/tools/memory/delete.d.ts.map +1 -0
  249. package/dist/tools/memory/delete.js +26 -0
  250. package/dist/tools/memory/delete.js.map +1 -0
  251. package/dist/tools/memory/index.d.ts +2 -0
  252. package/dist/tools/memory/index.d.ts.map +1 -1
  253. package/dist/tools/memory/index.js +6 -0
  254. package/dist/tools/memory/index.js.map +1 -1
  255. package/dist/tools/memory/save.d.ts.map +1 -1
  256. package/dist/tools/memory/save.js +3 -2
  257. package/dist/tools/memory/save.js.map +1 -1
  258. package/dist/tools/memory/search.d.ts.map +1 -1
  259. package/dist/tools/memory/search.js +12 -5
  260. package/dist/tools/memory/search.js.map +1 -1
  261. package/dist/tools/memory/update.d.ts +4 -0
  262. package/dist/tools/memory/update.d.ts.map +1 -0
  263. package/dist/tools/memory/update.js +47 -0
  264. package/dist/tools/memory/update.js.map +1 -0
  265. package/dist/tools/task/list.js +2 -2
  266. package/dist/tools/task/list.js.map +1 -1
  267. package/dist/types/agent/scheduler.d.ts +5 -0
  268. package/dist/types/agent/scheduler.d.ts.map +1 -1
  269. package/dist/types/agent/task.d.ts +10 -0
  270. package/dist/types/agent/task.d.ts.map +1 -1
  271. package/dist/types/computer-use/index.d.ts +6 -0
  272. package/dist/types/computer-use/index.d.ts.map +1 -1
  273. package/dist/types/computer-use/index.js.map +1 -1
  274. package/dist/types/errors/catalog.js +1 -1
  275. package/dist/types/errors/catalog.js.map +1 -1
  276. package/dist/types/hitl/index.d.ts +11 -1
  277. package/dist/types/hitl/index.d.ts.map +1 -1
  278. package/dist/types/hitl/index.js.map +1 -1
  279. package/dist/types/memory/index.d.ts +14 -1
  280. package/dist/types/memory/index.d.ts.map +1 -1
  281. package/dist/types/plugin/index.d.ts +7 -0
  282. package/dist/types/plugin/index.d.ts.map +1 -1
  283. package/dist/types/plugin/index.js.map +1 -1
  284. package/dist/types/project/entity.d.ts +1 -0
  285. package/dist/types/project/entity.d.ts.map +1 -1
  286. package/dist/types/provider/chat.d.ts +4 -0
  287. package/dist/types/provider/chat.d.ts.map +1 -1
  288. package/dist/types/provider/config.d.ts +4 -0
  289. package/dist/types/provider/config.d.ts.map +1 -1
  290. package/dist/types/provider/model.d.ts +4 -0
  291. package/dist/types/provider/model.d.ts.map +1 -1
  292. package/dist/types/provider/stream.d.ts +6 -0
  293. package/dist/types/provider/stream.d.ts.map +1 -1
  294. package/dist/types/run/answer-review.d.ts +2 -0
  295. package/dist/types/run/answer-review.d.ts.map +1 -1
  296. package/dist/types/run/config.d.ts +2 -0
  297. package/dist/types/run/config.d.ts.map +1 -1
  298. package/dist/types/run/events.d.ts +19 -0
  299. package/dist/types/run/events.d.ts.map +1 -1
  300. package/dist/types/run/events.js.map +1 -1
  301. package/dist/types/run/prepare-step.d.ts +19 -1
  302. package/dist/types/run/prepare-step.d.ts.map +1 -1
  303. package/dist/types/sandbox/index.d.ts +1 -0
  304. package/dist/types/sandbox/index.d.ts.map +1 -1
  305. package/dist/types/sandbox/index.js.map +1 -1
  306. package/dist/types/structured-output/index.d.ts +8 -2
  307. package/dist/types/structured-output/index.d.ts.map +1 -1
  308. package/dist/types/tool/index.d.ts +15 -0
  309. package/dist/types/tool/index.d.ts.map +1 -1
  310. package/dist/types/tool/index.js.map +1 -1
  311. package/dist/types/tool/presentation.d.ts +4 -0
  312. package/dist/types/tool/presentation.d.ts.map +1 -1
  313. package/dist/utils/json-snapshot.d.ts +3 -0
  314. package/dist/utils/json-snapshot.d.ts.map +1 -0
  315. package/dist/utils/json-snapshot.js +79 -0
  316. package/dist/utils/json-snapshot.js.map +1 -0
  317. package/package.json +4 -2
  318. package/src/bridge/a2a/mapper.ts +4 -0
  319. package/src/bridge/sse/mapper.ts +16 -1
  320. package/src/compaction/extractor.ts +21 -8
  321. package/src/compaction/manager.ts +11 -1
  322. package/src/compaction/verifier.ts +80 -18
  323. package/src/config/runtime.ts +2 -0
  324. package/src/contracts/api.ts +1 -0
  325. package/src/eval/harness-verification.ts +270 -0
  326. package/src/eval/index.ts +10 -0
  327. package/src/execution/code-runtime/json-value.ts +82 -0
  328. package/src/execution/code-runtime/worker-program.ts +239 -0
  329. package/src/execution/code-runtime/worker.ts +164 -111
  330. package/src/manager/agent/lifecycle.ts +352 -54
  331. package/src/manager/run/persistence.ts +7 -0
  332. package/src/prompt/coding-agent-doctrine.ts +11 -5
  333. package/src/provider/capabilities.ts +41 -1
  334. package/src/provider/fallback.ts +9 -2
  335. package/src/public-runtime.ts +6 -0
  336. package/src/public-tools.ts +7 -1
  337. package/src/public-types.ts +7 -0
  338. package/src/registry/tool/execute.ts +17 -79
  339. package/src/run/command-gate.ts +61 -13
  340. package/src/run/index.ts +2 -0
  341. package/src/run/memory-promoter.ts +32 -40
  342. package/src/run/memory-recall.ts +254 -0
  343. package/src/run/reporter.ts +2 -0
  344. package/src/run/token-budget.ts +55 -14
  345. package/src/run/workspace-fingerprint.ts +17 -8
  346. package/src/runtime/query/checkpoint.ts +96 -2
  347. package/src/runtime/query/executor.ts +100 -29
  348. package/src/runtime/query/index.ts +76 -16
  349. package/src/runtime/query/iteration/index.ts +405 -46
  350. package/src/runtime/query/iteration/native-output.ts +35 -0
  351. package/src/runtime/query/iteration/phases/advisory.ts +21 -11
  352. package/src/runtime/query/iteration/phases/compaction.ts +36 -14
  353. package/src/runtime/query/iteration/phases/context.ts +9 -0
  354. package/src/runtime/query/iteration/phases/tool-review.ts +5 -1
  355. package/src/runtime/query/iteration/phases/working-memory.ts +23 -5
  356. package/src/runtime/query/iteration/stream-turn.ts +15 -0
  357. package/src/runtime/query/observation-context.ts +86 -0
  358. package/src/runtime/query/request-context.ts +103 -0
  359. package/src/runtime/query/request-rich-content.ts +8 -3
  360. package/src/runtime/query/review-policy.ts +7 -1
  361. package/src/runtime/query/steering.ts +19 -2
  362. package/src/runtime/query/tool-call-budget.ts +115 -0
  363. package/src/runtime/query/tooling.ts +8 -0
  364. package/src/sandbox/file-walk-program.ts +8 -0
  365. package/src/sandbox/file-walk.ts +9 -0
  366. package/src/scheduler/completion-inbox.ts +3 -0
  367. package/src/scheduler/local.ts +1 -0
  368. package/src/session/handoff/capacity.ts +7 -3
  369. package/src/store/memory/disk.ts +52 -30
  370. package/src/store/memory/index.ts +75 -27
  371. package/src/store/memory/memory.ts +18 -6
  372. package/src/store/memory/operation-lock.ts +99 -0
  373. package/src/store/run/token-budget-disk.ts +3 -0
  374. package/src/tools/builtins/computer-use.ts +61 -7
  375. package/src/tools/builtins/edit.ts +12 -27
  376. package/src/tools/builtins/file-write-result.ts +84 -0
  377. package/src/tools/builtins/glob.ts +7 -1
  378. package/src/tools/builtins/grep.ts +10 -0
  379. package/src/tools/builtins/job.ts +8 -0
  380. package/src/tools/builtins/read-file.ts +10 -0
  381. package/src/tools/builtins/run-code.ts +24 -5
  382. package/src/tools/builtins/search-tools.ts +18 -3
  383. package/src/tools/builtins/write-file.ts +39 -44
  384. package/src/tools/defineTool.ts +5 -0
  385. package/src/tools/file-read-tracker.ts +16 -0
  386. package/src/tools/memory/delete.ts +29 -0
  387. package/src/tools/memory/index.ts +6 -0
  388. package/src/tools/memory/save.ts +4 -2
  389. package/src/tools/memory/search.ts +12 -5
  390. package/src/tools/memory/update.ts +50 -0
  391. package/src/tools/task/list.ts +2 -2
  392. package/src/types/agent/scheduler.ts +6 -0
  393. package/src/types/agent/task.ts +13 -0
  394. package/src/types/computer-use/index.ts +6 -0
  395. package/src/types/errors/catalog.ts +1 -1
  396. package/src/types/hitl/index.ts +11 -1
  397. package/src/types/memory/index.ts +16 -1
  398. package/src/types/plugin/index.ts +10 -0
  399. package/src/types/project/entity.ts +1 -0
  400. package/src/types/provider/chat.ts +2 -0
  401. package/src/types/provider/config.ts +4 -0
  402. package/src/types/provider/model.ts +4 -0
  403. package/src/types/provider/stream.ts +7 -0
  404. package/src/types/run/answer-review.ts +2 -0
  405. package/src/types/run/config.ts +2 -0
  406. package/src/types/run/events.ts +20 -0
  407. package/src/types/run/prepare-step.ts +19 -1
  408. package/src/types/sandbox/index.ts +1 -0
  409. package/src/types/structured-output/index.ts +15 -2
  410. package/src/types/tool/index.ts +16 -0
  411. package/src/types/tool/presentation.ts +4 -0
  412. package/src/utils/json-snapshot.ts +76 -0
@@ -1,6 +1,10 @@
1
1
  import { type Span, SpanStatusCode } from '@opentelemetry/api'
2
2
  import { resolveContextWindow } from '../../../compaction/context-window.js'
3
- import { extractFromAssistantMessage } from '../../../compaction/extractor.js'
3
+ import {
4
+ extractFromAssistantMessage,
5
+ extractFromUserMessage,
6
+ } from '../../../compaction/extractor.js'
7
+ import { estimateMessageTokens } from '../../../compaction/token-estimate.js'
4
8
  import { AUTO_CONTINUATION_USER_MESSAGE } from '../../../constants/continuation.js'
5
9
  import {
6
10
  DEFAULT_STRUCTURED_OUTPUT_RETRIES,
@@ -9,6 +13,7 @@ import {
9
13
  import { renderSkillsSection } from '../../../persona/assembler.js'
10
14
  import { resolveProviderCapabilities } from '../../../provider/capabilities.js'
11
15
  import { collectChatCompletion } from '../../../provider/collect-chat-completion.js'
16
+ import { renderToolSchema } from '../../../registry/tool/schema.js'
12
17
  import { formatCompletionNotification } from '../../../scheduler/completion-inbox.js'
13
18
  import {
14
19
  GENAI,
@@ -24,6 +29,7 @@ import { NamzuError } from '../../../types/errors/index.js'
24
29
  import type { MessageId } from '../../../types/ids/index.js'
25
30
  import {
26
31
  type Message,
32
+ type UserMessage,
27
33
  createAssistantMessage,
28
34
  createRuntimeContextMessage,
29
35
  createSystemMessage,
@@ -33,6 +39,7 @@ import { classifyProviderError } from '../../../types/provider/errors.js'
33
39
  import type { ChatCompletionResponse } from '../../../types/provider/index.js'
34
40
  import type { AnswerReview } from '../../../types/run/answer-review.js'
35
41
  import type {
42
+ PrepareStepContext,
36
43
  PrepareStepResult,
37
44
  RunEvent,
38
45
  StepFailure,
@@ -47,17 +54,29 @@ import { toErrorMessage } from '../../../utils/error.js'
47
54
  import { stableDigest } from '../../../utils/hash.js'
48
55
  import { generateMessageId } from '../../../utils/id.js'
49
56
  import type { ToolCallOutcome } from '../executor.js'
57
+ import { projectObservationContext } from '../observation-context.js'
50
58
  import { applyLifecycleHookResults } from '../plugin-hooks.js'
59
+ import {
60
+ type RequestContextSnapshot,
61
+ diffRequestContext,
62
+ snapshotRequestContext,
63
+ } from '../request-context.js'
51
64
  import {
52
65
  DEFAULT_MAX_REQUEST_RICH_CONTENT_BYTES,
53
66
  type RequestImageIdentity,
54
67
  markProviderRejectedImage,
55
68
  projectRequestRichContent,
56
69
  } from '../request-rich-content.js'
57
- import { formatSteeringNote } from '../steering.js'
70
+ import { formatSteeringNote, isOperatorUserMessage } from '../steering.js'
71
+ import { parseNativeCandidate } from './native-output.js'
58
72
  import { runAdvisoryPhase } from './phases/advisory.js'
59
73
  import { runIterationCheckpoint } from './phases/checkpoint.js'
60
- import { measureContext, relieveOverflow, runCompactionCheck } from './phases/compaction.js'
74
+ import {
75
+ activeContextWindow,
76
+ measureContext,
77
+ relieveOverflow,
78
+ runCompactionCheck,
79
+ } from './phases/compaction.js'
61
80
  import type { IterationContext } from './phases/index.js'
62
81
  import { runPlanGate } from './phases/plan.js'
63
82
  import { runToolReview } from './phases/tool-review.js'
@@ -151,6 +170,14 @@ export class IterationOrchestrator {
151
170
  * one process must not suppress each other's first envelope.
152
171
  */
153
172
  private lastEnvelopeKey: string | undefined
173
+ private previousRequestContext: RequestContextSnapshot | undefined
174
+
175
+ private projectObservations(messages: Message[]): Message[] {
176
+ const config = this.ctx.compactionConfig
177
+ return config && config.strategy !== 'disabled' && config.deduplicateObservations !== false
178
+ ? projectObservationContext(messages, this.ctx.tools, config.preserveToolResultsFrom)
179
+ : messages
180
+ }
154
181
  /** Rich tool blocks already reported; durable history is scanned every turn. */
155
182
  private readonly warnedRichToolResults = new Set<string>()
156
183
  /**
@@ -168,9 +195,34 @@ export class IterationOrchestrator {
168
195
  * sets it.
169
196
  */
170
197
  private stopDeferredForOutstandingWork = false
198
+ /** One current input, independent of the compactable history array. */
199
+ private latestUserMessage: UserMessage | undefined
171
200
 
172
201
  constructor(ctx: IterationContext) {
173
- this.ctx = ctx
202
+ this.ctx = {
203
+ ...ctx,
204
+ onSteeringDelivered: (text) => {
205
+ this.rememberUserMessage(createRuntimeContextMessage(text, 'steering'))
206
+ },
207
+ }
208
+ ctx.checkpointMgr.setLatestUserMessageSource(() => this.latestUserMessage)
209
+ ctx.checkpointMgr.setStructuredReviewAttemptsSource?.(() => this.structuredReviewAttempts)
210
+ ctx.checkpointMgr.setNativeStructuredAttemptsSource?.(() => this.nativeStructuredAttempts)
211
+ if (ctx.structuredOutput?.mode === 'native') {
212
+ const limit = ctx.structuredOutput.maxRetries
213
+ if (limit !== undefined && (!Number.isSafeInteger(limit) || limit < 0))
214
+ throw new RangeError(
215
+ 'Native structuredOutput.maxRetries must be a nonnegative safe integer',
216
+ )
217
+ }
218
+ if (
219
+ ctx.structuredOutput?.mode !== undefined &&
220
+ !['tool', 'native'].includes(ctx.structuredOutput.mode)
221
+ )
222
+ throw new RangeError('Unknown structuredOutput.mode')
223
+ const maxReviews = ctx.structuredOutput?.maxReviews
224
+ if (maxReviews !== undefined && (!Number.isSafeInteger(maxReviews) || maxReviews < 0))
225
+ throw new RangeError('structuredOutput.maxReviews must be a nonnegative safe integer')
174
226
  }
175
227
 
176
228
  /**
@@ -252,6 +304,17 @@ export class IterationOrchestrator {
252
304
  const { runConfig, runMgr } = this.ctx
253
305
  const { model } = runConfig
254
306
  const tracer = getTracer()
307
+ // Resume hydration happens after construction, before the loop starts.
308
+ this.latestUserMessage = this.ctx.checkpointMgr.restoredLatestUserMessage
309
+ this.structuredReviewAttempts = this.ctx.checkpointMgr.restoredStructuredReviewAttempts ?? 0
310
+ this.nativeStructuredAttempts = this.ctx.checkpointMgr.restoredNativeStructuredAttempts ?? 0
311
+ if (!this.latestUserMessage) {
312
+ for (const message of runMgr.messages) this.rememberUserMessage(message, false)
313
+ }
314
+ // The restored field can outlive the historical message it describes.
315
+ // Only known post-checkpoint arrivals may supersede it, never an old
316
+ // retained user turn encountered while scanning restored history.
317
+ for (const message of this.ctx.resumedInput ?? []) this.rememberUserMessage(message)
255
318
 
256
319
  // One context-overflow relief per *stuck point*, not per run.
257
320
  //
@@ -278,6 +341,26 @@ export class IterationOrchestrator {
278
341
  // no post-loop block reaches.
279
342
  try {
280
343
  while (true) {
344
+ if (this.ctx.abortController.signal.aborted) {
345
+ runMgr.setStopReason('cancelled')
346
+ runMgr.markCancelled()
347
+ break
348
+ }
349
+ if (
350
+ this.ctx.structuredOutput?.mode === 'native' &&
351
+ this.nativeStructuredAttempts > this.structuredOutputRetryLimit()
352
+ ) {
353
+ runMgr.setStopReason('structured_output_failed')
354
+ break
355
+ }
356
+ if (
357
+ this.ctx.structuredOutput?.review &&
358
+ this.structuredReviewAttempts >
359
+ (this.ctx.structuredOutput.maxReviews ?? DEFAULT_ANSWER_REVIEW_LIMIT)
360
+ ) {
361
+ runMgr.setStopReason('answer_rejected')
362
+ break
363
+ }
281
364
  // Read AND clear, in that order, in this one place.
282
365
  //
283
366
  // The flag is set by the previous iteration and read by this
@@ -325,6 +408,14 @@ export class IterationOrchestrator {
325
408
  // run and been paid for; this is the seam a host with a live
326
409
  // rate limit or a revoked tenant actually needs.
327
410
  const veto = await this.beforeStep(runMgr.currentIteration + 1)
411
+ // The hook may settle because its run signal was aborted. Stop
412
+ // before interpreting that settlement as a policy refusal or
413
+ // counting an iteration that will never reach the provider.
414
+ if (this.ctx.abortController.signal.aborted) {
415
+ runMgr.setStopReason('cancelled')
416
+ runMgr.markCancelled()
417
+ break
418
+ }
328
419
  if (veto) {
329
420
  // Namespaced. The un-namespaced keys elsewhere in this file are
330
421
  // the frozen inventory LOG-22 exists to drain; a new call site
@@ -431,10 +522,6 @@ export class IterationOrchestrator {
431
522
  // compaction preserves). No-op when no provider is configured.
432
523
  await refreshWorkingMemory(this.ctx)
433
524
  await runCompactionCheck(this.ctx)
434
- // A context edit is a host-visible state transition, not a prelude
435
- // whose events may wait behind the next network call. In particular,
436
- // a slow or failing provider must not leave the host displaying the
437
- // pre-compaction context after Run.messages already shrank.
438
525
  yield* this.ctx.drainPending()
439
526
 
440
527
  // Cache discipline: keep the tools param byte-stable even on the
@@ -452,10 +539,25 @@ export class IterationOrchestrator {
452
539
  // Shape this step before calling the model. `stopWhen` decides
453
540
  // whether to keep going; this decides HOW. No-op when the host
454
541
  // supplied no hook.
542
+ const contextModelBeforePreparation = this.ctx.contextModel ?? model
455
543
  const step = await this.prepareStep(iterationNum)
544
+ stepModel = step.model ?? model
545
+ await this.selectContextModel(stepModel)
546
+ // Preserve post-compaction preparation/recall semantics. A changed
547
+ // model needs a second check against its own window; never replay
548
+ // host preparation effects merely to rebuild its request guidance.
549
+ if (stepModel !== contextModelBeforePreparation) await runCompactionCheck(this.ctx)
550
+ // Publish context edits before entering a possibly slow provider.
551
+ yield* this.ctx.drainPending()
456
552
 
457
553
  const stepAllowedTools = step.allowedTools ?? this.ctx.allowedTools
458
- const llmTools = this.ctx.tools.toLLMTools(stepAllowedTools)
554
+ const llmTools = this.ctx.tools
555
+ .toLLMTools(stepAllowedTools)
556
+ .filter(
557
+ (tool) =>
558
+ this.ctx.structuredOutput?.mode !== 'native' ||
559
+ tool.function.name !== STRUCTURED_OUTPUT_TOOL_NAME,
560
+ )
459
561
  // The same list the request was built from now also bounds what
460
562
  // may run. Narrowing only the request left the restriction
461
563
  // presentational — the model was shown fewer tools and could
@@ -526,7 +628,7 @@ export class IterationOrchestrator {
526
628
  ? [...baseMessages, createSystemMessage(stepPreamble)]
527
629
  : [...baseMessages]
528
630
  const messages = projectRequestRichContent(
529
- requestHistory,
631
+ this.projectObservations(requestHistory),
530
632
  this.ctx.runConfig.maxRequestRichContentBytes ?? DEFAULT_MAX_REQUEST_RICH_CONTENT_BYTES,
531
633
  )
532
634
  await this.reportUnsupportedToolResults(messages)
@@ -576,6 +678,16 @@ export class IterationOrchestrator {
576
678
  }
577
679
 
578
680
  if (this.ctx.pluginManager) {
681
+ const snapshot = snapshotRequestContext(messages)
682
+ const context = Object.freeze({
683
+ snapshot,
684
+ ...(this.previousRequestContext
685
+ ? {
686
+ change: diffRequestContext(this.previousRequestContext, snapshot),
687
+ }
688
+ : {}),
689
+ })
690
+ this.previousRequestContext = snapshot
579
691
  const hookResults = await this.ctx.pluginManager.executeHooks(
580
692
  'pre_llm_call',
581
693
  {
@@ -585,6 +697,7 @@ export class IterationOrchestrator {
585
697
  // Built inside the guard: a run with no plugins installed
586
698
  // pays nothing for a projection nobody reads.
587
699
  request: Object.freeze({
700
+ context,
588
701
  model: stepModel,
589
702
  // Copied per turn, not handed over live: these are the
590
703
  // run's own message objects, and a hook writing into
@@ -632,6 +745,18 @@ export class IterationOrchestrator {
632
745
  this.ctx.provider,
633
746
  {
634
747
  model: stepModel,
748
+ ...(this.ctx.structuredOutput?.mode === 'native'
749
+ ? {
750
+ responseFormat: {
751
+ type: 'json_schema' as const,
752
+ json_schema: {
753
+ name: 'structured_output',
754
+ schema: renderToolSchema(this.ctx.structuredOutput.schema),
755
+ strict: true,
756
+ },
757
+ },
758
+ }
759
+ : {}),
635
760
  providerRoute: requestedRoute,
636
761
  messages,
637
762
  tools: llmTools.length > 0 ? llmTools : undefined,
@@ -652,6 +777,7 @@ export class IterationOrchestrator {
652
777
  cacheControl: { type: 'auto' },
653
778
  ...(runConfig.thinking ? { thinking: runConfig.thinking } : {}),
654
779
  ...(runConfig.effort ? { effort: runConfig.effort } : {}),
780
+ ...(!forceFinalize && runConfig.webSearch ? { webSearch: runConfig.webSearch } : {}),
655
781
  // Thread the run abort into the model call so a Stop tears the
656
782
  // in-flight turn down (provider passes it to fetch; the consumer
657
783
  // also races it). Inert when never aborted.
@@ -771,11 +897,7 @@ export class IterationOrchestrator {
771
897
  const contextFigures = this.ctx.compactionConfig
772
898
  ? (() => {
773
899
  const measured = measureContext(this.ctx)
774
- const window = resolveContextWindow(
775
- this.ctx.compactionConfig?.contextWindowTokens,
776
- runConfig.model,
777
- this.ctx.providerContextWindow,
778
- )
900
+ const window = activeContextWindow(this.ctx)
779
901
  return {
780
902
  contextTokens: measured.tokens,
781
903
  contextMeasuredBy: measured.source,
@@ -932,6 +1054,70 @@ export class IterationOrchestrator {
932
1054
  costBefore,
933
1055
  })
934
1056
 
1057
+ if (this.ctx.structuredOutput?.mode === 'native') {
1058
+ const candidate = await parseNativeCandidate(
1059
+ this.ctx.structuredOutput.schema,
1060
+ response,
1061
+ this.ctx.abortController.signal,
1062
+ )
1063
+ let outcome: 'accepted' | 'retry' | 'exhausted' | 'cancelled'
1064
+ if (candidate.success) outcome = await this.reviewStructuredOutput(candidate.value)
1065
+ else {
1066
+ this.nativeStructuredAttempts++
1067
+ runMgr.pushMessage(
1068
+ createRuntimeContextMessage(
1069
+ 'Return a complete JSON value matching the supplied response schema. Do not continue a partial JSON fragment.',
1070
+ 'structured-output',
1071
+ ),
1072
+ )
1073
+ const checkpoint = await this.ctx.checkpointMgr.create(runMgr, iterationNum)
1074
+ await this.ctx.emitEvent({
1075
+ type: 'checkpoint_created',
1076
+ runId: runMgr.id,
1077
+ checkpointId: checkpoint.id,
1078
+ iteration: iterationNum,
1079
+ })
1080
+ outcome =
1081
+ this.nativeStructuredAttempts > this.structuredOutputRetryLimit()
1082
+ ? 'exhausted'
1083
+ : 'retry'
1084
+ }
1085
+ await this.ctx.emitEvent({
1086
+ type: 'iteration_completed',
1087
+ runId: runMgr.id,
1088
+ iteration: iterationNum,
1089
+ hasToolCalls: false,
1090
+ })
1091
+ yield* this.ctx.drainPending()
1092
+ if (this.ctx.abortController.signal.aborted || outcome === 'cancelled') {
1093
+ runMgr.setStopReason('cancelled')
1094
+ runMgr.markCancelled()
1095
+ break
1096
+ }
1097
+ if (outcome === 'accepted') {
1098
+ if (!forceFinalize) {
1099
+ const changed = yield* this.holdForOutstandingWork(iterationNum, false)
1100
+ const inbound = this.deliverInbound()
1101
+ if (changed || inbound > 0) continue
1102
+ }
1103
+ if (this.ctx.abortController.signal.aborted) {
1104
+ runMgr.setStopReason('cancelled')
1105
+ runMgr.markCancelled()
1106
+ break
1107
+ }
1108
+ this.publishStructuredOutput()
1109
+ runMgr.setStopReason('end_turn')
1110
+ break
1111
+ }
1112
+ if (outcome === 'exhausted') {
1113
+ runMgr.setStopReason(
1114
+ candidate.success ? 'answer_rejected' : 'structured_output_failed',
1115
+ )
1116
+ break
1117
+ }
1118
+ continue
1119
+ }
1120
+
935
1121
  const hasContent =
936
1122
  response.message.content !== null && response.message.content.length > 0
937
1123
 
@@ -1022,6 +1208,11 @@ export class IterationOrchestrator {
1022
1208
  // a loud stop rather than a loop.
1023
1209
  if (!forceFinalize && this.ctx.reviewAnswer) {
1024
1210
  const review = await this.reviewAnswer(response.message.content ?? '')
1211
+ if (this.ctx.abortController.signal.aborted) {
1212
+ runMgr.setStopReason('cancelled')
1213
+ runMgr.markCancelled()
1214
+ break
1215
+ }
1025
1216
  if (review && !review.accept) {
1026
1217
  const attempt = ++this.answerReviewAttempts
1027
1218
  const limit = this.ctx.maxAnswerReviews ?? DEFAULT_ANSWER_REVIEW_LIMIT
@@ -1159,12 +1350,39 @@ export class IterationOrchestrator {
1159
1350
  // run ends here rather than paying for another turn whose only
1160
1351
  // job would be to restate it — unless it shared its turn with
1161
1352
  // other calls, which relays instead. See the method.
1162
- if (this.captureStructuredOutput(reviewOutcome.results, response)) {
1353
+ const structuredOutcome = await this.captureStructuredOutput(
1354
+ reviewOutcome.results,
1355
+ response,
1356
+ )
1357
+ if (
1358
+ structuredOutcome === 'retry' ||
1359
+ structuredOutcome === 'exhausted' ||
1360
+ structuredOutcome === 'cancelled'
1361
+ ) {
1362
+ await this.ctx.emitEvent({
1363
+ type: 'iteration_completed',
1364
+ runId: runMgr.id,
1365
+ iteration: iterationNum,
1366
+ hasToolCalls: true,
1367
+ })
1368
+ yield* this.ctx.drainPending()
1369
+ if (this.ctx.abortController.signal.aborted) {
1370
+ runMgr.setStopReason('cancelled')
1371
+ runMgr.markCancelled()
1372
+ break
1373
+ }
1374
+ if (structuredOutcome === 'retry') continue
1375
+ runMgr.setStopReason(
1376
+ structuredOutcome === 'cancelled' ? 'cancelled' : 'answer_rejected',
1377
+ )
1378
+ if (structuredOutcome === 'cancelled') runMgr.markCancelled()
1379
+ break
1380
+ }
1381
+ if (structuredOutcome === 'accepted') {
1163
1382
  this.ctx.log.info('Structured output produced — ending run', {
1164
1383
  [NAMZU.RUN_ID]: runMgr.id,
1165
1384
  [NAMZU.ITERATION]: iterationNum,
1166
1385
  })
1167
- runMgr.setStopReason('end_turn')
1168
1386
  await this.ctx.emitEvent({
1169
1387
  type: 'iteration_completed',
1170
1388
  runId: runMgr.id,
@@ -1172,6 +1390,13 @@ export class IterationOrchestrator {
1172
1390
  hasToolCalls: true,
1173
1391
  })
1174
1392
  yield* this.ctx.drainPending()
1393
+ if (this.ctx.abortController.signal.aborted) {
1394
+ runMgr.setStopReason('cancelled')
1395
+ runMgr.markCancelled()
1396
+ break
1397
+ }
1398
+ this.publishStructuredOutput()
1399
+ runMgr.setStopReason('end_turn')
1175
1400
  break
1176
1401
  }
1177
1402
 
@@ -1603,19 +1828,51 @@ export class IterationOrchestrator {
1603
1828
  * message becomes the reason, so an operator is not left with a run
1604
1829
  * that stopped and no account of it.
1605
1830
  */
1831
+ private stepContext(stepNumber: number, prepared: PrepareStepResult): PrepareStepContext {
1832
+ const model = prepared.model ?? this.ctx.runConfig.model
1833
+ const window = resolveContextWindow(
1834
+ this.ctx.compactionConfig?.contextWindowTokens,
1835
+ model,
1836
+ model === this.ctx.runConfig.model
1837
+ ? this.ctx.providerContextWindow
1838
+ : model === this.ctx.contextModel
1839
+ ? this.ctx.activeProviderContextWindow
1840
+ : undefined,
1841
+ )
1842
+ const skills = prepared.skills ? renderSkillsSection([...prepared.skills]) : null
1843
+ const preamble = [prepared.system, skills].filter(Boolean).join('\n\n')
1844
+ const preparedTokens = preamble ? estimateMessageTokens(createSystemMessage(preamble)) : 0
1845
+ const responseReserve = Math.min(
1846
+ prepared.maxResponseTokens ??
1847
+ this.ctx.runConfig.maxResponseTokens ??
1848
+ Math.floor(window.tokens / 4),
1849
+ Math.floor(window.tokens / 4),
1850
+ )
1851
+ return {
1852
+ runId: this.ctx.runMgr.id,
1853
+ stepNumber,
1854
+ messages: this.ctx.runMgr.messages,
1855
+ ...(this.latestUserMessage ? { latestUserMessage: this.latestUserMessage } : {}),
1856
+ signal: this.ctx.abortController.signal,
1857
+ contextBudget: {
1858
+ windowTokens: window.tokens,
1859
+ remainingTokens: Math.max(
1860
+ 0,
1861
+ Math.floor(
1862
+ window.tokens - measureContext(this.ctx).tokens - preparedTokens - responseReserve,
1863
+ ),
1864
+ ),
1865
+ },
1866
+ steps: this.steps,
1867
+ prepared,
1868
+ }
1869
+ }
1870
+
1606
1871
  private async beforeStep(stepNumber: number): Promise<StepVeto | undefined> {
1607
1872
  const configured = this.ctx.beforeStep
1608
1873
  if (!configured) return undefined
1609
1874
  try {
1610
- return (
1611
- (await configured({
1612
- runId: this.ctx.runMgr.id,
1613
- stepNumber,
1614
- messages: this.ctx.runMgr.messages,
1615
- steps: this.steps,
1616
- prepared: {},
1617
- })) ?? undefined
1618
- )
1875
+ return (await configured(this.stepContext(stepNumber, {}))) ?? undefined
1619
1876
  } catch (err) {
1620
1877
  return { reason: `beforeStep threw: ${toErrorMessage(err)}` }
1621
1878
  }
@@ -1641,14 +1898,9 @@ export class IterationOrchestrator {
1641
1898
  let result: PrepareStepResult = {}
1642
1899
  for (const stage of stages) {
1643
1900
  try {
1644
- const decided = await stage({
1645
- runId: this.ctx.runMgr.id,
1646
- stepNumber,
1647
- messages: this.ctx.runMgr.messages,
1648
- steps: this.steps,
1649
- prepared: result,
1650
- })
1901
+ const decided = await stage(this.stepContext(stepNumber, result))
1651
1902
  if (decided) result = { ...result, ...decided }
1903
+ await this.selectContextModel(result.model ?? this.ctx.runConfig.model)
1652
1904
  } catch (err) {
1653
1905
  // Skipped, and the rest still run: one broken concern must
1654
1906
  // not silently disable the others it was declared beside.
@@ -1710,6 +1962,18 @@ export class IterationOrchestrator {
1710
1962
  return prepared
1711
1963
  }
1712
1964
 
1965
+ private async selectContextModel(model: string | undefined): Promise<void> {
1966
+ if (model !== (this.ctx.contextModel ?? this.ctx.runConfig.model)) {
1967
+ // A measurement from another tokenizer cannot price the new request.
1968
+ this.ctx.runMgr.clearLastPromptTokens()
1969
+ }
1970
+ this.ctx.contextModel = model
1971
+ this.ctx.activeProviderContextWindow =
1972
+ model && model !== this.ctx.runConfig.model && !this.ctx.compactionConfig?.contextWindowTokens
1973
+ ? await this.ctx.resolveModelContextWindow?.(model)
1974
+ : undefined
1975
+ }
1976
+
1713
1977
  /** Steps completed so far, exposed on the returned `Run`. */
1714
1978
  private readonly steps: StepResult[] = []
1715
1979
 
@@ -1738,18 +2002,33 @@ export class IterationOrchestrator {
1738
2002
  * empty drain must change nothing at all: a `continue` on nothing queued
1739
2003
  * spends an iteration and a model call to say the same thing again.
1740
2004
  */
2005
+ private rememberUserMessage(message: Message, arriving = true): void {
2006
+ if (!isOperatorUserMessage(message)) return
2007
+ this.latestUserMessage = message
2008
+ // The hook field alone does not reach the model. Preserve arrivals in
2009
+ // the compaction state too, before their original message or attached
2010
+ // tool result can be shed. Initial history was already extracted at seed.
2011
+ const manager = this.ctx.workingStateManager
2012
+ if (arriving && manager) {
2013
+ extractFromUserMessage(manager, message.content, !manager.getState().task)
2014
+ }
2015
+ }
2016
+
1741
2017
  private deliverInbound(): number {
1742
2018
  const queued = this.ctx.inboundMessages?.() ?? []
1743
- for (const message of queued) this.ctx.runMgr.pushMessage(message)
2019
+ for (const message of queued) {
2020
+ this.ctx.runMgr.pushMessage(message)
2021
+ this.rememberUserMessage(message)
2022
+ }
1744
2023
 
1745
2024
  // The steering channel's remainder. `attachSteering` already took
1746
2025
  // what it could carry on a tool result; anything still pending is
1747
2026
  // guidance from a turn that had no result to attach it to.
1748
2027
  const stranded = this.ctx.steering?.drain()
1749
2028
  if (stranded) {
1750
- this.ctx.runMgr.pushMessage(
1751
- createRuntimeContextMessage(formatSteeringNote(stranded), 'steering'),
1752
- )
2029
+ const message = createRuntimeContextMessage(formatSteeringNote(stranded), 'steering')
2030
+ this.ctx.runMgr.pushMessage(message)
2031
+ this.rememberUserMessage(createRuntimeContextMessage(stranded, 'steering'))
1753
2032
  }
1754
2033
 
1755
2034
  return queued.length + (stranded ? 1 : 0)
@@ -1856,7 +2135,10 @@ export class IterationOrchestrator {
1856
2135
 
1857
2136
  /** Turns spent asking the model again for a valid structured output. */
1858
2137
  private structuredOutputAttempts = 0
2138
+ private nativeStructuredAttempts = 0
1859
2139
  private structuredOutputDone = false
2140
+ private pendingStructuredOutput: unknown
2141
+ private structuredReviewAttempts = 0
1860
2142
 
1861
2143
  private structuredOutputRetryLimit(): number {
1862
2144
  return this.ctx.structuredOutput?.maxRetries ?? DEFAULT_STRUCTURED_OUTPUT_RETRIES
@@ -1883,6 +2165,7 @@ export class IterationOrchestrator {
1883
2165
  results: readonly ToolCallOutcome[],
1884
2166
  response: ChatCompletionResponse,
1885
2167
  ): ToolCallOutcome | undefined {
2168
+ if (this.ctx.structuredOutput?.mode === 'native') return undefined
1886
2169
  const terminal = results.filter((r) => this.ctx.tools.get(r.toolName)?.terminal === true)
1887
2170
  if (terminal.length === 0) return undefined
1888
2171
 
@@ -1951,13 +2234,14 @@ export class IterationOrchestrator {
1951
2234
  * doing work, and it is the bound the neighbour relies on for the
1952
2235
  * identical pathology.
1953
2236
  */
1954
- private captureStructuredOutput(
2237
+ private async captureStructuredOutput(
1955
2238
  results: readonly ToolCallOutcome[],
1956
2239
  response: ChatCompletionResponse,
1957
- ): boolean {
1958
- if (!this.needsStructuredOutput()) return false
2240
+ ): Promise<'absent' | 'accepted' | 'retry' | 'exhausted' | 'cancelled'> {
2241
+ if (!this.needsStructuredOutput() || this.ctx.structuredOutput?.mode === 'native')
2242
+ return 'absent'
1959
2243
  const hit = results.find((r) => r.toolName === STRUCTURED_OUTPUT_TOOL_NAME && !r.isError)
1960
- if (!hit) return false
2244
+ if (!hit) return 'absent'
1961
2245
 
1962
2246
  const callCount = response.message.toolCalls?.length ?? 0
1963
2247
  if (callCount > 1) {
@@ -1965,18 +2249,90 @@ export class IterationOrchestrator {
1965
2249
  [NAMZU.RUN_ID]: this.ctx.runMgr.id,
1966
2250
  'namzu.runtime.calls_in_turn': callCount,
1967
2251
  })
1968
- return false
2252
+ return 'absent'
1969
2253
  }
1970
2254
 
2255
+ let parsed: unknown
1971
2256
  try {
1972
- this.ctx.runMgr.setStructuredOutput(JSON.parse(hit.output))
2257
+ parsed = JSON.parse(hit.output)
1973
2258
  } catch {
1974
2259
  // The tool serializes its own validated input, so this is
1975
2260
  // unreachable in practice; keep the raw text rather than losing it.
1976
- this.ctx.runMgr.setStructuredOutput(hit.output)
2261
+ if (this.ctx.structuredOutput?.review)
2262
+ throw new Error(
2263
+ 'Structured review requires an intact JSON tool result; check tool-output limits and result transformations',
2264
+ )
2265
+ parsed = hit.output
1977
2266
  }
2267
+ return this.reviewStructuredOutput(parsed)
2268
+ }
2269
+
2270
+ private publishStructuredOutput(): void {
2271
+ this.ctx.runMgr.setStructuredOutput(this.pendingStructuredOutput)
1978
2272
  this.structuredOutputDone = true
1979
- return true
2273
+ }
2274
+
2275
+ private async reviewStructuredOutput(
2276
+ parsed: unknown,
2277
+ ): Promise<'accepted' | 'retry' | 'exhausted' | 'cancelled'> {
2278
+ if (this.ctx.abortController.signal.aborted) return 'cancelled'
2279
+ const reviewer = this.ctx.structuredOutput?.review
2280
+ if (reviewer) {
2281
+ const signal = this.ctx.abortController.signal
2282
+ if (signal.aborted) return 'cancelled'
2283
+ let onAbort: () => void = () => {}
2284
+ const aborted = new Promise<never>((_resolve, reject) => {
2285
+ onAbort = () => reject(signal.reason ?? new Error('Structured review cancelled'))
2286
+ signal.addEventListener('abort', onAbort, { once: true })
2287
+ })
2288
+ let verdict: AnswerReview
2289
+ try {
2290
+ verdict = await Promise.race([
2291
+ Promise.resolve().then(() =>
2292
+ reviewer(structuredClone(parsed), {
2293
+ runId: this.ctx.runMgr.id,
2294
+ iteration: this.ctx.runMgr.currentIteration,
2295
+ signal,
2296
+ messages: this.ctx.runMgr.messages,
2297
+ }),
2298
+ ),
2299
+ aborted,
2300
+ ])
2301
+ } catch (error) {
2302
+ if (signal.aborted) return 'cancelled'
2303
+ throw error
2304
+ } finally {
2305
+ signal.removeEventListener('abort', onAbort)
2306
+ }
2307
+ if (signal.aborted) return 'cancelled'
2308
+ if (!verdict || typeof verdict.accept !== 'boolean')
2309
+ throw new Error('Structured reviewer returned an invalid verdict')
2310
+ if (!verdict.accept) {
2311
+ if (typeof verdict.feedback !== 'string' || verdict.feedback.trim().length === 0)
2312
+ throw new Error('Structured reviewer rejection requires feedback')
2313
+ this.structuredReviewAttempts++
2314
+ this.ctx.runMgr.pushMessage(createRuntimeContextMessage(verdict.feedback, 'answer-review'))
2315
+ // Persist both the feedback and its consumed allowance before the
2316
+ // next request. This checkpoint is not an approval/park boundary.
2317
+ const checkpoint = await this.ctx.checkpointMgr.create(
2318
+ this.ctx.runMgr,
2319
+ this.ctx.runMgr.currentIteration,
2320
+ )
2321
+ await this.ctx.emitEvent({
2322
+ type: 'checkpoint_created',
2323
+ runId: this.ctx.runMgr.id,
2324
+ checkpointId: checkpoint.id,
2325
+ iteration: this.ctx.runMgr.currentIteration,
2326
+ })
2327
+ if (signal.aborted) return 'cancelled'
2328
+ return this.structuredReviewAttempts >
2329
+ (this.ctx.structuredOutput?.maxReviews ?? DEFAULT_ANSWER_REVIEW_LIMIT)
2330
+ ? 'exhausted'
2331
+ : 'retry'
2332
+ }
2333
+ }
2334
+ this.pendingStructuredOutput = parsed
2335
+ return 'accepted'
1980
2336
  }
1981
2337
 
1982
2338
  /**
@@ -1997,6 +2353,7 @@ export class IterationOrchestrator {
1997
2353
  return await this.ctx.reviewAnswer(answer, {
1998
2354
  runId: this.ctx.runMgr.id,
1999
2355
  iteration: this.ctx.runMgr.currentIteration,
2356
+ signal: this.ctx.abortController.signal,
2000
2357
  messages: this.ctx.runMgr.messages,
2001
2358
  })
2002
2359
  } catch (err) {
@@ -2059,6 +2416,8 @@ export class IterationOrchestrator {
2059
2416
  model: string,
2060
2417
  reason: StopReason,
2061
2418
  ): Promise<StopReason | undefined> {
2419
+ if (this.ctx.structuredOutput?.mode === 'native') return 'structured_output_failed'
2420
+
2062
2421
  const lastAssistant = [...this.ctx.runMgr.messages]
2063
2422
  .reverse()
2064
2423
  .find((m) => m.role === 'assistant')
@@ -2091,7 +2450,7 @@ export class IterationOrchestrator {
2091
2450
  ),
2092
2451
  ]
2093
2452
  const finalMessages = projectRequestRichContent(
2094
- finalHistory,
2453
+ this.projectObservations(finalHistory),
2095
2454
  this.ctx.runConfig.maxRequestRichContentBytes ?? DEFAULT_MAX_REQUEST_RICH_CONTENT_BYTES,
2096
2455
  )
2097
2456
  await this.reportUnsupportedToolResults(finalMessages)