@namzu/sdk 51.0.0 → 52.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 (352) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/dist/agents/QueryAgent.d.ts.map +1 -1
  3. package/dist/agents/QueryAgent.js +2 -0
  4. package/dist/agents/QueryAgent.js.map +1 -1
  5. package/dist/agents/SupervisorAgent.d.ts +1 -1
  6. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  7. package/dist/agents/SupervisorAgent.js.map +1 -1
  8. package/dist/agents/examples/SupervisorAgent.d.ts +42 -0
  9. package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -1
  10. package/dist/agents/examples/SupervisorAgent.js +80 -4
  11. package/dist/agents/examples/SupervisorAgent.js.map +1 -1
  12. package/dist/agents/index.d.ts +1 -1
  13. package/dist/agents/index.d.ts.map +1 -1
  14. package/dist/agents/index.js.map +1 -1
  15. package/dist/authorization/protected-paths.d.ts +36 -0
  16. package/dist/authorization/protected-paths.d.ts.map +1 -0
  17. package/dist/authorization/protected-paths.js +107 -0
  18. package/dist/authorization/protected-paths.js.map +1 -0
  19. package/dist/authorization/readonly-commands.d.ts +39 -0
  20. package/dist/authorization/readonly-commands.d.ts.map +1 -0
  21. package/dist/authorization/readonly-commands.js +797 -0
  22. package/dist/authorization/readonly-commands.js.map +1 -0
  23. package/dist/authorization/readonly-flags.d.ts +19 -0
  24. package/dist/authorization/readonly-flags.d.ts.map +1 -0
  25. package/dist/authorization/readonly-flags.js +178 -0
  26. package/dist/authorization/readonly-flags.js.map +1 -0
  27. package/dist/authorization/removal.d.ts +52 -0
  28. package/dist/authorization/removal.d.ts.map +1 -0
  29. package/dist/authorization/removal.js +283 -0
  30. package/dist/authorization/removal.js.map +1 -0
  31. package/dist/authorization/shell-paths.d.ts +66 -0
  32. package/dist/authorization/shell-paths.d.ts.map +1 -0
  33. package/dist/authorization/shell-paths.js +697 -0
  34. package/dist/authorization/shell-paths.js.map +1 -0
  35. package/dist/bridge/acp/update.d.ts.map +1 -1
  36. package/dist/bridge/acp/update.js +1 -0
  37. package/dist/bridge/acp/update.js.map +1 -1
  38. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  39. package/dist/bridge/sse/mapper.js +1 -0
  40. package/dist/bridge/sse/mapper.js.map +1 -1
  41. package/dist/compaction/context-window.d.ts +24 -0
  42. package/dist/compaction/context-window.d.ts.map +1 -1
  43. package/dist/compaction/context-window.js +34 -0
  44. package/dist/compaction/context-window.js.map +1 -1
  45. package/dist/compaction/manual.d.ts.map +1 -1
  46. package/dist/compaction/manual.js +10 -2
  47. package/dist/compaction/manual.js.map +1 -1
  48. package/dist/compaction/plan.d.ts +4 -0
  49. package/dist/compaction/plan.d.ts.map +1 -1
  50. package/dist/compaction/plan.js +6 -2
  51. package/dist/compaction/plan.js.map +1 -1
  52. package/dist/compaction/verifier.d.ts +11 -1
  53. package/dist/compaction/verifier.d.ts.map +1 -1
  54. package/dist/compaction/verifier.js +19 -7
  55. package/dist/compaction/verifier.js.map +1 -1
  56. package/dist/config/runtime.d.ts +55 -7
  57. package/dist/config/runtime.d.ts.map +1 -1
  58. package/dist/config/runtime.js +23 -2
  59. package/dist/config/runtime.js.map +1 -1
  60. package/dist/connector/web/guarded-fetch.d.ts.map +1 -1
  61. package/dist/connector/web/guarded-fetch.js +24 -0
  62. package/dist/connector/web/guarded-fetch.js.map +1 -1
  63. package/dist/connector/web/index.d.ts +1 -1
  64. package/dist/connector/web/index.d.ts.map +1 -1
  65. package/dist/connector/web/page.d.ts +59 -0
  66. package/dist/connector/web/page.d.ts.map +1 -0
  67. package/dist/connector/web/page.js +112 -0
  68. package/dist/connector/web/page.js.map +1 -0
  69. package/dist/connector/web/types.d.ts +47 -0
  70. package/dist/connector/web/types.d.ts.map +1 -1
  71. package/dist/connector/web/types.js.map +1 -1
  72. package/dist/constants/continuation.d.ts +8 -0
  73. package/dist/constants/continuation.d.ts.map +1 -1
  74. package/dist/constants/continuation.js +8 -0
  75. package/dist/constants/continuation.js.map +1 -1
  76. package/dist/constants/plugin/index.d.ts +1 -1
  77. package/dist/constants/plugin/index.d.ts.map +1 -1
  78. package/dist/constants/plugin/index.js +1 -1
  79. package/dist/constants/plugin/index.js.map +1 -1
  80. package/dist/manager/agent/lifecycle.d.ts +7 -0
  81. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  82. package/dist/manager/agent/lifecycle.js +11 -2
  83. package/dist/manager/agent/lifecycle.js.map +1 -1
  84. package/dist/manager/session/turn-recorder.d.ts.map +1 -1
  85. package/dist/manager/session/turn-recorder.js +4 -2
  86. package/dist/manager/session/turn-recorder.js.map +1 -1
  87. package/dist/plugin/index.d.ts +1 -1
  88. package/dist/plugin/index.d.ts.map +1 -1
  89. package/dist/plugin/index.js +1 -1
  90. package/dist/plugin/index.js.map +1 -1
  91. package/dist/plugin/lifecycle.d.ts +6 -0
  92. package/dist/plugin/lifecycle.d.ts.map +1 -1
  93. package/dist/plugin/lifecycle.js +98 -114
  94. package/dist/plugin/lifecycle.js.map +1 -1
  95. package/dist/plugin/shell-hook.d.ts +90 -22
  96. package/dist/plugin/shell-hook.d.ts.map +1 -1
  97. package/dist/plugin/shell-hook.js +434 -41
  98. package/dist/plugin/shell-hook.js.map +1 -1
  99. package/dist/provider/errors.d.ts +10 -0
  100. package/dist/provider/errors.d.ts.map +1 -1
  101. package/dist/provider/errors.js +16 -0
  102. package/dist/provider/errors.js.map +1 -1
  103. package/dist/provider/retry.d.ts +27 -0
  104. package/dist/provider/retry.d.ts.map +1 -1
  105. package/dist/provider/retry.js +19 -3
  106. package/dist/provider/retry.js.map +1 -1
  107. package/dist/public-runtime.d.ts +4 -1
  108. package/dist/public-runtime.d.ts.map +1 -1
  109. package/dist/public-runtime.js +4 -1
  110. package/dist/public-runtime.js.map +1 -1
  111. package/dist/public-types.d.ts +2 -2
  112. package/dist/public-types.d.ts.map +1 -1
  113. package/dist/runtime/jobs/registry.d.ts +21 -0
  114. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  115. package/dist/runtime/jobs/registry.js +15 -2
  116. package/dist/runtime/jobs/registry.js.map +1 -1
  117. package/dist/runtime/query/executor/tool-call-admission.d.ts +10 -0
  118. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  119. package/dist/runtime/query/executor/tool-call-admission.js +74 -13
  120. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  121. package/dist/runtime/query/executor.d.ts +41 -2
  122. package/dist/runtime/query/executor.d.ts.map +1 -1
  123. package/dist/runtime/query/executor.js +190 -6
  124. package/dist/runtime/query/executor.js.map +1 -1
  125. package/dist/runtime/query/finalize-turn.d.ts +6 -0
  126. package/dist/runtime/query/finalize-turn.d.ts.map +1 -1
  127. package/dist/runtime/query/finalize-turn.js +1 -1
  128. package/dist/runtime/query/finalize-turn.js.map +1 -1
  129. package/dist/runtime/query/index.d.ts +29 -0
  130. package/dist/runtime/query/index.d.ts.map +1 -1
  131. package/dist/runtime/query/index.js +15 -3
  132. package/dist/runtime/query/index.js.map +1 -1
  133. package/dist/runtime/query/iteration/index.d.ts +31 -0
  134. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  135. package/dist/runtime/query/iteration/index.js +216 -7
  136. package/dist/runtime/query/iteration/index.js.map +1 -1
  137. package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts +58 -0
  138. package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts.map +1 -0
  139. package/dist/runtime/query/iteration/phases/compaction-breaker.js +91 -0
  140. package/dist/runtime/query/iteration/phases/compaction-breaker.js.map +1 -0
  141. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  142. package/dist/runtime/query/iteration/phases/compaction.js +89 -7
  143. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  144. package/dist/runtime/query/iteration/phases/context.d.ts +10 -0
  145. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  146. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  147. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  148. package/dist/runtime/query/iteration/phases/tool-review.js +165 -2
  149. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  150. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  151. package/dist/runtime/query/iteration/stream-turn.js +24 -1
  152. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  153. package/dist/runtime/query/path-escalation.d.ts +36 -0
  154. package/dist/runtime/query/path-escalation.d.ts.map +1 -0
  155. package/dist/runtime/query/path-escalation.js +184 -0
  156. package/dist/runtime/query/path-escalation.js.map +1 -0
  157. package/dist/runtime/query/plugin-hooks.d.ts.map +1 -1
  158. package/dist/runtime/query/plugin-hooks.js +8 -0
  159. package/dist/runtime/query/plugin-hooks.js.map +1 -1
  160. package/dist/runtime/query/reminders.d.ts +35 -0
  161. package/dist/runtime/query/reminders.d.ts.map +1 -0
  162. package/dist/runtime/query/reminders.js +7 -0
  163. package/dist/runtime/query/reminders.js.map +1 -0
  164. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  165. package/dist/runtime/query/resume-pending.js +26 -0
  166. package/dist/runtime/query/resume-pending.js.map +1 -1
  167. package/dist/runtime/query/review-policy.d.ts +26 -0
  168. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  169. package/dist/runtime/query/review-policy.js +79 -5
  170. package/dist/runtime/query/review-policy.js.map +1 -1
  171. package/dist/runtime/query/tool-output-budget.d.ts +46 -0
  172. package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
  173. package/dist/runtime/query/tool-output-budget.js +85 -1
  174. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  175. package/dist/runtime/query/tooling.d.ts +1 -0
  176. package/dist/runtime/query/tooling.d.ts.map +1 -1
  177. package/dist/runtime/query/tooling.js +5 -0
  178. package/dist/runtime/query/tooling.js.map +1 -1
  179. package/dist/session/paths.d.ts +5 -1
  180. package/dist/session/paths.d.ts.map +1 -1
  181. package/dist/session/paths.js +8 -0
  182. package/dist/session/paths.js.map +1 -1
  183. package/dist/store/memory/disk.d.ts.map +1 -1
  184. package/dist/store/memory/disk.js +2 -2
  185. package/dist/store/memory/disk.js.map +1 -1
  186. package/dist/store/memory/markdown.d.ts.map +1 -1
  187. package/dist/store/memory/markdown.js +2 -2
  188. package/dist/store/memory/markdown.js.map +1 -1
  189. package/dist/store/memory/naming.d.ts +9 -0
  190. package/dist/store/memory/naming.d.ts.map +1 -1
  191. package/dist/store/memory/naming.js +12 -0
  192. package/dist/store/memory/naming.js.map +1 -1
  193. package/dist/tools/builtins/bash.d.ts +30 -1
  194. package/dist/tools/builtins/bash.d.ts.map +1 -1
  195. package/dist/tools/builtins/bash.js +170 -26
  196. package/dist/tools/builtins/bash.js.map +1 -1
  197. package/dist/tools/builtins/content-fingerprint.d.ts +2 -0
  198. package/dist/tools/builtins/content-fingerprint.d.ts.map +1 -1
  199. package/dist/tools/builtins/content-fingerprint.js +4 -0
  200. package/dist/tools/builtins/content-fingerprint.js.map +1 -1
  201. package/dist/tools/builtins/edit.d.ts.map +1 -1
  202. package/dist/tools/builtins/edit.js +60 -18
  203. package/dist/tools/builtins/edit.js.map +1 -1
  204. package/dist/tools/builtins/grep.d.ts +8 -1
  205. package/dist/tools/builtins/grep.d.ts.map +1 -1
  206. package/dist/tools/builtins/grep.js +152 -33
  207. package/dist/tools/builtins/grep.js.map +1 -1
  208. package/dist/tools/builtins/read-file.d.ts +1 -0
  209. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  210. package/dist/tools/builtins/read-file.js +44 -5
  211. package/dist/tools/builtins/read-file.js.map +1 -1
  212. package/dist/tools/builtins/read-render.d.ts +52 -0
  213. package/dist/tools/builtins/read-render.d.ts.map +1 -1
  214. package/dist/tools/builtins/read-render.js +143 -0
  215. package/dist/tools/builtins/read-render.js.map +1 -1
  216. package/dist/tools/builtins/web.d.ts +13 -2
  217. package/dist/tools/builtins/web.d.ts.map +1 -1
  218. package/dist/tools/builtins/web.js +225 -32
  219. package/dist/tools/builtins/web.js.map +1 -1
  220. package/dist/tools/coordinator/ask-user-question.d.ts +2 -0
  221. package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
  222. package/dist/tools/coordinator/ask-user-question.js +256 -92
  223. package/dist/tools/coordinator/ask-user-question.js.map +1 -1
  224. package/dist/tools/coordinator/question-options.d.ts +1 -0
  225. package/dist/tools/coordinator/question-options.d.ts.map +1 -1
  226. package/dist/tools/coordinator/question-options.js +6 -1
  227. package/dist/tools/coordinator/question-options.js.map +1 -1
  228. package/dist/tools/defineTool.d.ts +4 -1
  229. package/dist/tools/defineTool.d.ts.map +1 -1
  230. package/dist/tools/defineTool.js +6 -1
  231. package/dist/tools/defineTool.js.map +1 -1
  232. package/dist/tools/paths.d.ts +6 -0
  233. package/dist/tools/paths.d.ts.map +1 -1
  234. package/dist/tools/paths.js +1 -1
  235. package/dist/tools/paths.js.map +1 -1
  236. package/dist/types/agent/query.d.ts +3 -0
  237. package/dist/types/agent/query.d.ts.map +1 -1
  238. package/dist/types/errors/catalog.js +1 -1
  239. package/dist/types/errors/catalog.js.map +1 -1
  240. package/dist/types/hitl/index.d.ts +104 -0
  241. package/dist/types/hitl/index.d.ts.map +1 -1
  242. package/dist/types/hitl/index.js.map +1 -1
  243. package/dist/types/message/index.d.ts +1 -1
  244. package/dist/types/message/index.d.ts.map +1 -1
  245. package/dist/types/message/index.js +2 -0
  246. package/dist/types/message/index.js.map +1 -1
  247. package/dist/types/plugin/index.d.ts +93 -19
  248. package/dist/types/plugin/index.d.ts.map +1 -1
  249. package/dist/types/plugin/index.js +3 -0
  250. package/dist/types/plugin/index.js.map +1 -1
  251. package/dist/types/provider/error.d.ts +6 -0
  252. package/dist/types/provider/error.d.ts.map +1 -1
  253. package/dist/types/provider/errors.d.ts +19 -0
  254. package/dist/types/provider/errors.d.ts.map +1 -1
  255. package/dist/types/provider/errors.js +39 -1
  256. package/dist/types/provider/errors.js.map +1 -1
  257. package/dist/types/provider/stream.d.ts +6 -0
  258. package/dist/types/provider/stream.d.ts.map +1 -1
  259. package/dist/types/session/events.d.ts +15 -2
  260. package/dist/types/session/events.d.ts.map +1 -1
  261. package/dist/types/session/events.js.map +1 -1
  262. package/dist/types/session/records.d.ts +9 -9
  263. package/dist/types/session/records.d.ts.map +1 -1
  264. package/dist/types/session/records.js +1 -0
  265. package/dist/types/session/records.js.map +1 -1
  266. package/dist/types/session/stop-reason.d.ts +5 -0
  267. package/dist/types/session/stop-reason.d.ts.map +1 -1
  268. package/dist/types/tool/index.d.ts +52 -0
  269. package/dist/types/tool/index.d.ts.map +1 -1
  270. package/dist/types/tool/index.js.map +1 -1
  271. package/dist/utils/backoff.d.ts +12 -0
  272. package/dist/utils/backoff.d.ts.map +1 -1
  273. package/dist/utils/backoff.js +15 -0
  274. package/dist/utils/backoff.js.map +1 -1
  275. package/package.json +4 -2
  276. package/src/agents/QueryAgent.ts +5 -1
  277. package/src/agents/SupervisorAgent.ts +1 -1
  278. package/src/agents/examples/SupervisorAgent.ts +217 -106
  279. package/src/agents/index.ts +1 -1
  280. package/src/authorization/protected-paths.ts +110 -0
  281. package/src/authorization/readonly-commands.ts +771 -0
  282. package/src/authorization/readonly-flags.ts +196 -0
  283. package/src/authorization/removal.ts +326 -0
  284. package/src/authorization/shell-paths.ts +927 -0
  285. package/src/bridge/acp/update.ts +1 -0
  286. package/src/bridge/sse/mapper.ts +1 -0
  287. package/src/compaction/context-window.ts +41 -0
  288. package/src/compaction/manual.ts +10 -2
  289. package/src/compaction/plan.ts +11 -2
  290. package/src/compaction/verifier.ts +28 -3
  291. package/src/config/runtime.ts +23 -2
  292. package/src/connector/web/guarded-fetch.ts +26 -0
  293. package/src/connector/web/index.ts +3 -0
  294. package/src/connector/web/page.ts +130 -0
  295. package/src/connector/web/types.ts +47 -0
  296. package/src/constants/continuation.ts +10 -0
  297. package/src/constants/plugin/index.ts +1 -1
  298. package/src/manager/agent/lifecycle.ts +12 -4
  299. package/src/manager/session/turn-recorder.ts +10 -2
  300. package/src/plugin/index.ts +1 -0
  301. package/src/plugin/lifecycle.ts +107 -119
  302. package/src/plugin/shell-hook.ts +477 -43
  303. package/src/provider/errors.ts +18 -0
  304. package/src/provider/retry.ts +53 -3
  305. package/src/public-runtime.ts +8 -0
  306. package/src/public-types.ts +4 -0
  307. package/src/runtime/jobs/registry.ts +39 -2
  308. package/src/runtime/query/executor/tool-call-admission.ts +79 -13
  309. package/src/runtime/query/executor.ts +242 -8
  310. package/src/runtime/query/finalize-turn.ts +7 -1
  311. package/src/runtime/query/index.ts +45 -3
  312. package/src/runtime/query/iteration/index.ts +251 -12
  313. package/src/runtime/query/iteration/phases/compaction-breaker.ts +106 -0
  314. package/src/runtime/query/iteration/phases/compaction.ts +99 -12
  315. package/src/runtime/query/iteration/phases/context.ts +11 -0
  316. package/src/runtime/query/iteration/phases/tool-review.ts +177 -2
  317. package/src/runtime/query/iteration/stream-turn.ts +24 -1
  318. package/src/runtime/query/path-escalation.ts +204 -0
  319. package/src/runtime/query/plugin-hooks.ts +8 -0
  320. package/src/runtime/query/reminders.ts +45 -0
  321. package/src/runtime/query/resume-pending.ts +27 -0
  322. package/src/runtime/query/review-policy.ts +106 -5
  323. package/src/runtime/query/tool-output-budget.ts +115 -1
  324. package/src/runtime/query/tooling.ts +6 -0
  325. package/src/session/paths.ts +11 -1
  326. package/src/store/memory/disk.ts +2 -1
  327. package/src/store/memory/markdown.ts +2 -1
  328. package/src/store/memory/naming.ts +13 -0
  329. package/src/tools/builtins/bash.ts +203 -34
  330. package/src/tools/builtins/content-fingerprint.ts +5 -0
  331. package/src/tools/builtins/edit.ts +69 -19
  332. package/src/tools/builtins/grep.ts +159 -38
  333. package/src/tools/builtins/read-file.ts +48 -5
  334. package/src/tools/builtins/read-render.ts +193 -0
  335. package/src/tools/builtins/web.ts +258 -33
  336. package/src/tools/coordinator/ask-user-question.ts +309 -103
  337. package/src/tools/coordinator/question-options.ts +8 -1
  338. package/src/tools/defineTool.ts +11 -2
  339. package/src/tools/paths.ts +1 -1
  340. package/src/types/agent/query.ts +3 -0
  341. package/src/types/errors/catalog.ts +1 -1
  342. package/src/types/hitl/index.ts +104 -0
  343. package/src/types/message/index.ts +2 -0
  344. package/src/types/plugin/index.ts +101 -18
  345. package/src/types/provider/error.ts +6 -0
  346. package/src/types/provider/errors.ts +49 -1
  347. package/src/types/provider/stream.ts +6 -0
  348. package/src/types/session/events.ts +15 -2
  349. package/src/types/session/records.ts +1 -0
  350. package/src/types/session/stop-reason.ts +5 -0
  351. package/src/types/tool/index.ts +53 -2
  352. package/src/utils/backoff.ts +21 -0
@@ -1,7 +1,7 @@
1
1
  import { SpanStatusCode } from '@opentelemetry/api';
2
2
  import { extractFromAssistantMessage, extractFromUserMessage, } from '../../../compaction/extractor.js';
3
3
  import { estimateMessageTokens } from '../../../compaction/token-estimate.js';
4
- import { AUTO_CONTINUATION_USER_MESSAGE } from '../../../constants/continuation.js';
4
+ import { AUTO_CONTINUATION_USER_MESSAGE, REASONING_CUT_USER_MESSAGE, } from '../../../constants/continuation.js';
5
5
  import { CHARS_PER_TOKEN } from '../../../constants/limits.js';
6
6
  import { DEFAULT_STRUCTURED_OUTPUT_RETRIES, STRUCTURED_OUTPUT_REPROMPT, } from '../../../constants/tools/index.js';
7
7
  import { withStreamedMessageIdentity } from '../../../manager/session/streamed-message-identity.js';
@@ -15,7 +15,7 @@ import { getTracer } from '../../../telemetry/runtime-accessors.js';
15
15
  import { STRUCTURED_OUTPUT_TOOL_NAME } from '../../../tools/builtins/structuredOutput.js';
16
16
  import { NamzuError } from '../../../types/errors/index.js';
17
17
  import { createAssistantMessage, createRuntimeContextMessage, createSystemMessage, } from '../../../types/message/index.js';
18
- import { classifyProviderError } from '../../../types/provider/errors.js';
18
+ import { classifyProviderError, readOutputOverflow } from '../../../types/provider/errors.js';
19
19
  import { toErrorMessage } from '../../../utils/error.js';
20
20
  import { stableDigest } from '../../../utils/hash.js';
21
21
  import { generateMessageId } from '../../../utils/id.js';
@@ -31,6 +31,7 @@ import { parseNativeCandidate } from './native-output.js';
31
31
  import { drainArrivedTaskCompletions, holdForOutstandingWork, settleOutstandingWork, } from './outstanding-work.js';
32
32
  import { runAdvisoryPhase } from './phases/advisory.js';
33
33
  import { runIterationCheckpoint } from './phases/checkpoint.js';
34
+ import { compactionBreaker } from './phases/compaction-breaker.js';
34
35
  import { activeContextWindow, measureContext, relieveOverflow, runCompactionCheck, } from './phases/compaction.js';
35
36
  import { runHandoffPause } from './phases/handoff.js';
36
37
  import { runPlanGate } from './phases/plan.js';
@@ -60,6 +61,10 @@ class AnswerReviewFailure extends NamzuError {
60
61
  * on the thing that actually went wrong.
61
62
  */
62
63
  const DEFAULT_ANSWER_REVIEW_LIMIT = 3;
64
+ /** Left unused when an output cap is shrunk to fit the window (reference: 1000). */
65
+ const OUTPUT_CAP_MARGIN_TOKENS = 1000;
66
+ /** A shrunk output cap below this is not worth a call (reference floor: 3000). */
67
+ const MIN_OUTPUT_CAP_TOKENS = 3000;
63
68
  // Ending a turn changes the available actions, not the strength of its evidence.
64
69
  // Use the same standard for warning closure and empty-completion recovery.
65
70
  const CLOSING_RESPONSE_GUIDANCE = 'Give a concise response using only what the available evidence supports. Attribute unverified statements to their source instead of presenting them as observed facts. If evidence is missing or conflicting, state what cannot be established. Do not claim unfinished work is complete. Do not request any more tool calls.';
@@ -113,6 +118,67 @@ export class IterationOrchestrator {
113
118
  * sets it.
114
119
  */
115
120
  stopDeferredForOutstandingWork = false;
121
+ /** Nudges sent since the model last finished a call without hitting its output cap. */
122
+ outputContinuations = 0;
123
+ /**
124
+ * `turn_end` (and, for a child, `subagent_stop`) fired when the model
125
+ * finished and no hook asked for more. `finalizeTurn` then does not fire
126
+ * them a second time.
127
+ */
128
+ turnEndFired = false;
129
+ /** A hook already kept this turn going once: it is asked again with `stop_hook_active`. */
130
+ stopHookActive = false;
131
+ get turnEndHooksFired() {
132
+ return this.turnEndFired;
133
+ }
134
+ /**
135
+ * Fire `turn_end` (and `subagent_stop` for a child) at the point the model
136
+ * has finished, and read the answer.
137
+ *
138
+ * A hook that answers `skip` is refusing to let the turn end: its reasons
139
+ * are returned, joined, as feedback for the model. A hook that asks for the
140
+ * turn to halt wins over any such feedback (`takeHalt`). With nothing asked,
141
+ * the events have fired for this turn and the finalizer does not repeat them.
142
+ */
143
+ async *askStopHooks() {
144
+ const manager = this.ctx.pluginManager;
145
+ if (!manager)
146
+ return undefined;
147
+ const recorder = this.ctx.recorder;
148
+ const feedback = [];
149
+ const ask = async (event, extra) => {
150
+ const results = await manager.executeHooks(event, {
151
+ sessionId: recorder.sessionId,
152
+ turnId: recorder.turnId,
153
+ ...extra,
154
+ ...(this.stopHookActive ? { stopHookActive: true } : {}),
155
+ signal: this.ctx.abortController.signal,
156
+ }, this.ctx.emitEvent);
157
+ applyLifecycleHookResults(event, results);
158
+ for (const result of results) {
159
+ if (result.action === 'skip')
160
+ feedback.push(result.reason);
161
+ if ((result.action === 'continue' || result.action === 'skip') && result.halt) {
162
+ this.ctx.toolExecutor.requestHalt?.(result.halt.reason);
163
+ }
164
+ }
165
+ };
166
+ await ask('turn_end', {});
167
+ yield* this.ctx.drainPending();
168
+ if (this.ctx.parentSessionId !== undefined) {
169
+ await ask('subagent_stop', {
170
+ parentSessionId: this.ctx.parentSessionId,
171
+ ...(this.ctx.parentTurnId !== undefined ? { parentTurnId: this.ctx.parentTurnId } : {}),
172
+ });
173
+ yield* this.ctx.drainPending();
174
+ }
175
+ if (feedback.length === 0) {
176
+ this.turnEndFired = true;
177
+ return undefined;
178
+ }
179
+ this.stopHookActive = true;
180
+ return feedback.join('\n');
181
+ }
116
182
  /** One current input, independent of the compactable history array. */
117
183
  latestUserMessage;
118
184
  initialDurableDelivered = false;
@@ -274,6 +340,9 @@ export class IterationOrchestrator {
274
340
  // obvious moves left. It is cleared by a turn that actually
275
341
  // succeeded, which is the evidence that the turn is no longer stuck.
276
342
  let overflowRelieved = false;
343
+ // The output cap a provider told us fits beside this prompt. One request's
344
+ // worth: it is cleared by a call that went through.
345
+ let outputCapOverride;
277
346
  // A `finally` rather than a line at each exit, for the reason written
278
347
  // beside `iterSpan.end()` below: this loop leaves by eight `break`s,
279
348
  // two `return`s and a `throw`, and a rule every future edit has to
@@ -446,12 +515,16 @@ export class IterationOrchestrator {
446
515
  applyLifecycleHookResults('iteration_start', hookResults);
447
516
  yield* this.ctx.drainPending();
448
517
  }
518
+ if (!forceFinalize)
519
+ await this.deliverReminders(iterationNum);
449
520
  // Re-pin the working-memory block from ground truth at the primacy
450
521
  // edge BEFORE compaction runs (so the refreshed slot is what
451
522
  // compaction preserves). No-op when no provider is configured.
452
523
  await refreshWorkingMemory(this.ctx);
453
524
  await runCompactionCheck(this.ctx);
454
525
  yield* this.ctx.drainPending();
526
+ if (this.stopForCompactionBreaker())
527
+ break;
455
528
  // Cache discipline: keep the tools param byte-stable even on the
456
529
  // forced-final iteration and forbid tool use via tool_choice
457
530
  // 'none' instead. Dropping the tools array would invalidate the
@@ -498,6 +571,8 @@ export class IterationOrchestrator {
498
571
  await runCompactionCheck(this.ctx);
499
572
  // Publish context edits before entering a possibly slow provider.
500
573
  yield* this.ctx.drainPending();
574
+ if (this.stopForCompactionBreaker())
575
+ break;
501
576
  const stepAllowedTools = step.allowedTools ?? this.ctx.allowedTools;
502
577
  const deferredMcpContext = deferredMcpHints?.forNames(stepAllowedTools) ?? '';
503
578
  const contextText = [
@@ -660,7 +735,7 @@ export class IterationOrchestrator {
660
735
  messages: Object.freeze(messages.map((m) => Object.freeze({ ...m }))),
661
736
  toolNames: Object.freeze(llmTools.map((t) => t.function.name)),
662
737
  temperature: step.temperature ?? turnConfig.temperature,
663
- maxTokens: step.maxResponseTokens ?? turnConfig.maxResponseTokens,
738
+ maxTokens: outputCapOverride ?? step.maxResponseTokens ?? turnConfig.maxResponseTokens,
664
739
  }),
665
740
  }, this.ctx.emitEvent);
666
741
  applyLifecycleHookResults('pre_llm_call', hookResults);
@@ -726,7 +801,7 @@ export class IterationOrchestrator {
726
801
  ? step.toolChoice
727
802
  : undefined,
728
803
  temperature: step.temperature ?? turnConfig.temperature,
729
- maxTokens: step.maxResponseTokens ?? turnConfig.maxResponseTokens,
804
+ maxTokens: outputCapOverride ?? step.maxResponseTokens ?? turnConfig.maxResponseTokens,
730
805
  cacheControl: { type: 'auto' },
731
806
  ...(turnConfig.thinking ? { thinking: turnConfig.thinking } : {}),
732
807
  ...(turnConfig.effort ? { effort: turnConfig.effort } : {}),
@@ -785,6 +860,9 @@ export class IterationOrchestrator {
785
860
  // The turn went through, so the turn is not sitting on an
786
861
  // irreducible prompt any more. Re-arm relief for the next one.
787
862
  overflowRelieved = false;
863
+ outputCapOverride = undefined;
864
+ if (response.finishReason !== 'length')
865
+ this.outputContinuations = 0;
788
866
  if (this.ctx.pluginManager) {
789
867
  const hookResults = await this.ctx.pluginManager.executeHooks('post_llm_call', {
790
868
  sessionId: recorder.sessionId,
@@ -1055,16 +1133,43 @@ export class IterationOrchestrator {
1055
1133
  // it has no room left to continue into, and the
1056
1134
  // continuation would only send a longer prompt into
1057
1135
  // the same full window. The reply stands as it is.
1136
+ const cutDuringReasoning = !hasContent &&
1137
+ (response.message.toolCalls?.length ?? 0) === 0 &&
1138
+ (response.message.reasoning?.length ?? 0) > 0;
1058
1139
  if (!forceFinalize &&
1059
1140
  response.finishReason === 'length' &&
1060
1141
  response.finishDetail !== 'context_window' &&
1061
- hasContent) {
1062
- this.ctx.log.info('LLM hit max_tokens mid-text — auto-continuing', {
1142
+ (hasContent || cutDuringReasoning)) {
1143
+ // A host that opted in gets a cap on the nudges: a model that
1144
+ // overruns its output limit every time would otherwise spend the
1145
+ // whole turn on it. Past the cap the turn stops, and says why.
1146
+ const cap = this.ctx.maxOutputContinuations;
1147
+ if (cap !== undefined && this.outputContinuations >= cap) {
1148
+ this.ctx.log.warn('LLM kept hitting max_tokens — stopping the turn', {
1149
+ [NAMZU.TURN_ID]: recorder.turnId,
1150
+ [NAMZU.ITERATION]: iterationNum,
1151
+ 'namzu.runtime.output_continuations': this.outputContinuations,
1152
+ });
1153
+ recorder.setLastError(`The reply was cut off at the output limit ${cap + 1} times in a row. Ask for a smaller piece of the work, or raise the output limit.`);
1154
+ recorder.setStopReason('output_limit');
1155
+ await this.ctx.emitEvent({
1156
+ type: 'iteration_completed',
1157
+ turnId: recorder.turnId,
1158
+ iteration: iterationNum,
1159
+ hasToolCalls: false,
1160
+ });
1161
+ yield* this.ctx.drainPending();
1162
+ break;
1163
+ }
1164
+ this.outputContinuations++;
1165
+ this.ctx.log.info(cutDuringReasoning
1166
+ ? 'LLM hit max_tokens while reasoning — nudging to answer briefly'
1167
+ : 'LLM hit max_tokens mid-text — auto-continuing', {
1063
1168
  [NAMZU.TURN_ID]: recorder.turnId,
1064
1169
  [NAMZU.ITERATION]: iterationNum,
1065
1170
  [GENAI.USAGE_OUTPUT_TOKENS]: response.usage.completionTokens,
1066
1171
  });
1067
- recorder.pushMessage(createRuntimeContextMessage(AUTO_CONTINUATION_USER_MESSAGE, 'auto-continuation'));
1172
+ recorder.pushMessage(createRuntimeContextMessage(cutDuringReasoning ? REASONING_CUT_USER_MESSAGE : AUTO_CONTINUATION_USER_MESSAGE, 'auto-continuation'));
1068
1173
  await this.ctx.emitEvent({
1069
1174
  type: 'iteration_completed',
1070
1175
  turnId: recorder.turnId,
@@ -1206,6 +1311,22 @@ export class IterationOrchestrator {
1206
1311
  // also settle as `end_turn`, and there the deferred predicate
1207
1312
  // is not why the turn ended: those decided the answer
1208
1313
  // themselves.
1314
+ // The model is done and has no tool calls. A `turn_end` (or
1315
+ // `subagent_stop`) hook may refuse to let it be: its reason goes
1316
+ // back to the model and the turn goes on.
1317
+ if (!forceFinalize && closingStopReason === undefined) {
1318
+ const feedback = yield* this.askStopHooks();
1319
+ const stoppedByHook = this.ctx.toolExecutor.takeHalt?.();
1320
+ if (stoppedByHook !== undefined) {
1321
+ recorder.setLastError(`Stopped by a hook: ${stoppedByHook}`);
1322
+ recorder.setStopReason('stop_condition');
1323
+ break;
1324
+ }
1325
+ if (feedback !== undefined) {
1326
+ recorder.pushMessage(createRuntimeContextMessage(`A hook asked for more before this turn ends:\n${feedback}`, 'hook-feedback'));
1327
+ continue;
1328
+ }
1329
+ }
1209
1330
  recorder.setStopReason(closingStopReason ??
1210
1331
  (stopWasDeferredForOutstandingWork ? 'stop_condition' : 'end_turn'));
1211
1332
  break;
@@ -1240,6 +1361,27 @@ export class IterationOrchestrator {
1240
1361
  if ((yield* runHandoffPause(this.ctx, iterationNum, reviewOutcome.results)) === 'stop') {
1241
1362
  return;
1242
1363
  }
1364
+ // A hook asked for the turn to stop once this step's calls were
1365
+ // answered. Every `tool_use` has its `tool_result` by now, so the
1366
+ // transcript is whole; what is left is to end the turn and say why.
1367
+ const hookHalt = this.ctx.toolExecutor.takeHalt?.();
1368
+ if (hookHalt !== undefined) {
1369
+ this.ctx.log.info('A hook stopped the turn', {
1370
+ [NAMZU.TURN_ID]: recorder.turnId,
1371
+ [NAMZU.ITERATION]: iterationNum,
1372
+ 'namzu.hook.reason': hookHalt,
1373
+ });
1374
+ recorder.setLastError(`Stopped by a hook: ${hookHalt}`);
1375
+ recorder.setStopReason('stop_condition');
1376
+ await this.ctx.emitEvent({
1377
+ type: 'iteration_completed',
1378
+ turnId: recorder.turnId,
1379
+ iteration: iterationNum,
1380
+ hasToolCalls: true,
1381
+ });
1382
+ yield* this.ctx.drainPending();
1383
+ break;
1384
+ }
1243
1385
  if (reviewOutcome.decision === 'rejected') {
1244
1386
  continue;
1245
1387
  }
@@ -1541,6 +1683,29 @@ export class IterationOrchestrator {
1541
1683
  // actually shed something. A second overflow after a successful
1542
1684
  // compaction means the prompt is irreducible, and looping on it
1543
1685
  // would burn the budget to arrive at the same error.
1686
+ // The prompt fit and only the requested output did not: ask for what
1687
+ // room is left (less a margin) and send it again, once. A reply that
1688
+ // would be too small to be useful, or a cap that is not smaller than
1689
+ // the one already tried, is not retried: the same failure would follow.
1690
+ const outputOverflow = err instanceof AnswerReviewFailure ? undefined : readOutputOverflow(err);
1691
+ if (outputOverflow) {
1692
+ const room = Math.max(0, outputOverflow.contextLimit - outputOverflow.inputTokens - OUTPUT_CAP_MARGIN_TOKENS);
1693
+ if (room >= MIN_OUTPUT_CAP_TOKENS &&
1694
+ (outputCapOverride === undefined || room < outputCapOverride)) {
1695
+ outputCapOverride = room;
1696
+ this.ctx.log.info('Output cap does not fit beside the prompt — retrying with less', {
1697
+ [NAMZU.TURN_ID]: recorder.turnId,
1698
+ [NAMZU.ITERATION]: iterationNum,
1699
+ 'namzu.runtime.input_tokens': outputOverflow.inputTokens,
1700
+ 'namzu.runtime.context_limit': outputOverflow.contextLimit,
1701
+ 'namzu.runtime.adjusted_max_tokens': room,
1702
+ });
1703
+ if (iterationActivity) {
1704
+ this.ctx.activityStore.complete(iterationActivity.id);
1705
+ }
1706
+ continue;
1707
+ }
1708
+ }
1544
1709
  if (!overflowRelieved &&
1545
1710
  !(err instanceof AnswerReviewFailure) &&
1546
1711
  classifyProviderError(err, this.ctx.provider.id).code === 'context_length_exceeded') {
@@ -1639,6 +1804,41 @@ export class IterationOrchestrator {
1639
1804
  extractFromUserMessage(manager, message.content, !manager.getState().task);
1640
1805
  }
1641
1806
  }
1807
+ /**
1808
+ * Ask the host's reminder source (`QueryParams.reminders`) what the model
1809
+ * should be told before this request, and append each text as a hidden
1810
+ * user-role message. The start of a request is a provider-valid boundary:
1811
+ * the history ends in the operator's message or in a finished tool batch.
1812
+ * A source that throws has nothing to say; it never fails the turn.
1813
+ */
1814
+ async deliverReminders(iteration) {
1815
+ const source = this.ctx.reminders;
1816
+ if (!source)
1817
+ return;
1818
+ const { recorder } = this.ctx;
1819
+ let texts;
1820
+ try {
1821
+ texts = await source({
1822
+ sessionId: recorder.sessionId,
1823
+ turnId: recorder.turnId,
1824
+ iteration,
1825
+ messages: recorder.messages,
1826
+ });
1827
+ }
1828
+ catch (error) {
1829
+ this.ctx.log.warn('A reminder source threw; the request goes without its reminders', {
1830
+ [NAMZU.TURN_ID]: recorder.turnId,
1831
+ [NAMZU.ITERATION]: iteration,
1832
+ 'exception.message': error instanceof Error ? error.message : String(error),
1833
+ });
1834
+ return;
1835
+ }
1836
+ for (const text of texts ?? []) {
1837
+ if (text.trim().length === 0)
1838
+ continue;
1839
+ recorder.pushMessage(createRuntimeContextMessage(text, 'reminder'));
1840
+ }
1841
+ }
1642
1842
  async deliverInbound() {
1643
1843
  const queued = this.ctx.inboundMessages?.() ?? [];
1644
1844
  for (const message of queued) {
@@ -1756,6 +1956,15 @@ export class IterationOrchestrator {
1756
1956
  recorder.setStopReason('structured_output_failed');
1757
1957
  return true;
1758
1958
  }
1959
+ /** The compaction circuit breaker asked for the turn to stop (opt-in; see `compactionConfig.circuitBreaker`). */
1960
+ stopForCompactionBreaker() {
1961
+ const reason = compactionBreaker(this.ctx)?.stop;
1962
+ if (reason === undefined)
1963
+ return false;
1964
+ this.ctx.recorder.setLastError(reason);
1965
+ this.ctx.recorder.setStopReason('error');
1966
+ return true;
1967
+ }
1759
1968
  async recordToolStructuredFailure(results, iteration) {
1760
1969
  if (!this.needsStructuredOutput() ||
1761
1970
  this.ctx.structuredOutput?.mode === 'native' ||