@namzu/cli 26.3.0 → 27.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 (321) hide show
  1. package/CHANGELOG.md +214 -0
  2. package/README.md +49 -34
  3. package/dist/bin.js +7 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/checkpoints/store.d.ts +17 -4
  6. package/dist/checkpoints/store.d.ts.map +1 -1
  7. package/dist/checkpoints/store.js +20 -5
  8. package/dist/checkpoints/store.js.map +1 -1
  9. package/dist/cli.js +2 -2
  10. package/dist/cli.js.map +1 -1
  11. package/dist/commands/acp.d.ts +23 -1
  12. package/dist/commands/acp.d.ts.map +1 -1
  13. package/dist/commands/acp.js +41 -2
  14. package/dist/commands/acp.js.map +1 -1
  15. package/dist/commands/drain.d.ts +69 -2
  16. package/dist/commands/drain.d.ts.map +1 -1
  17. package/dist/commands/drain.js +214 -134
  18. package/dist/commands/drain.js.map +1 -1
  19. package/dist/commands/eval.js +1 -1
  20. package/dist/commands/eval.js.map +1 -1
  21. package/dist/commands/provider-wait.d.ts +5 -5
  22. package/dist/commands/provider-wait.d.ts.map +1 -1
  23. package/dist/commands/provider-wait.js +2 -2
  24. package/dist/commands/resident.d.ts.map +1 -1
  25. package/dist/commands/resident.js +2 -1
  26. package/dist/commands/resident.js.map +1 -1
  27. package/dist/commands/run-flags.d.ts +7 -7
  28. package/dist/commands/run-flags.js +4 -4
  29. package/dist/commands/run-stream.d.ts +16 -12
  30. package/dist/commands/run-stream.d.ts.map +1 -1
  31. package/dist/commands/run-stream.js +142 -98
  32. package/dist/commands/run-stream.js.map +1 -1
  33. package/dist/commands/run.d.ts +6 -4
  34. package/dist/commands/run.d.ts.map +1 -1
  35. package/dist/commands/run.js +129 -45
  36. package/dist/commands/run.js.map +1 -1
  37. package/dist/commands/serve.js +2 -2
  38. package/dist/commands/serve.js.map +1 -1
  39. package/dist/commands/state.js +8 -8
  40. package/dist/commands/state.js.map +1 -1
  41. package/dist/config/load.d.ts +1 -1
  42. package/dist/config/load.d.ts.map +1 -1
  43. package/dist/config/load.js +17 -5
  44. package/dist/config/load.js.map +1 -1
  45. package/dist/config/run-limits.d.ts +20 -8
  46. package/dist/config/run-limits.d.ts.map +1 -1
  47. package/dist/config/run-limits.js +28 -46
  48. package/dist/config/run-limits.js.map +1 -1
  49. package/dist/config/schema.d.ts +44 -19
  50. package/dist/config/schema.d.ts.map +1 -1
  51. package/dist/config/schema.js.map +1 -1
  52. package/dist/config/tool-result-screens.js +1 -1
  53. package/dist/context/directories.d.ts +37 -0
  54. package/dist/context/directories.d.ts.map +1 -0
  55. package/dist/context/directories.js +69 -0
  56. package/dist/context/directories.js.map +1 -0
  57. package/dist/context/environment.d.ts +55 -0
  58. package/dist/context/environment.d.ts.map +1 -1
  59. package/dist/context/environment.js +96 -0
  60. package/dist/context/environment.js.map +1 -1
  61. package/dist/context/project-tracker.d.ts +3 -3
  62. package/dist/context/project-tracker.d.ts.map +1 -1
  63. package/dist/context/project-tracker.js +3 -3
  64. package/dist/context/project-tracker.js.map +1 -1
  65. package/dist/context/project.d.ts +1 -1
  66. package/dist/context/project.js +1 -1
  67. package/dist/context/sandbox.d.ts +22 -3
  68. package/dist/context/sandbox.d.ts.map +1 -1
  69. package/dist/context/sandbox.js +42 -4
  70. package/dist/context/sandbox.js.map +1 -1
  71. package/dist/doctor/checks/chain.d.ts +1 -1
  72. package/dist/doctor/checks/chain.js +5 -5
  73. package/dist/doctor/checks/chain.js.map +1 -1
  74. package/dist/doctor/checks/invariants.d.ts +2 -2
  75. package/dist/doctor/checks/invariants.js +5 -5
  76. package/dist/doctor/checks/invariants.js.map +1 -1
  77. package/dist/doctor/checks/logging.js +1 -1
  78. package/dist/doctor/checks/logging.js.map +1 -1
  79. package/dist/doctor/checks/sandbox.js +1 -1
  80. package/dist/doctor/checks/sandbox.js.map +1 -1
  81. package/dist/doctor/checks/session-export.d.ts +1 -1
  82. package/dist/doctor/checks/session-export.js +2 -2
  83. package/dist/doctor/checks/session-export.js.map +1 -1
  84. package/dist/doctor/checks/telemetry.d.ts +1 -1
  85. package/dist/doctor/checks/telemetry.js +1 -1
  86. package/dist/doctor/registry.js +2 -2
  87. package/dist/doctor/registry.js.map +1 -1
  88. package/dist/exit-codes.d.ts +2 -2
  89. package/dist/exit-codes.js +2 -2
  90. package/dist/integrations/mcp/servers.d.ts +1 -1
  91. package/dist/integrations/providers/chain-capabilities.d.ts +6 -6
  92. package/dist/integrations/providers/chain-capabilities.js +8 -8
  93. package/dist/integrations/providers/chain-capabilities.js.map +1 -1
  94. package/dist/integrations/providers/register.d.ts +1 -1
  95. package/dist/integrations/providers/register.js +1 -1
  96. package/dist/integrations/providers/registry.d.ts +1 -1
  97. package/dist/integrations/resident/inspection.d.ts +4 -1
  98. package/dist/integrations/resident/inspection.d.ts.map +1 -1
  99. package/dist/integrations/resident/inspection.js +53 -34
  100. package/dist/integrations/resident/inspection.js.map +1 -1
  101. package/dist/integrations/resident/learning-storage.d.ts +7 -2
  102. package/dist/integrations/resident/learning-storage.d.ts.map +1 -1
  103. package/dist/integrations/resident/learning-storage.js +12 -8
  104. package/dist/integrations/resident/learning-storage.js.map +1 -1
  105. package/dist/integrations/resident/runner-store.d.ts +1 -1
  106. package/dist/integrations/resident/runner-store.d.ts.map +1 -1
  107. package/dist/integrations/resident/runner-store.js +5 -2
  108. package/dist/integrations/resident/runner-store.js.map +1 -1
  109. package/dist/integrations/resident/runner-worker.js +1 -0
  110. package/dist/integrations/resident/runner-worker.js.map +1 -1
  111. package/dist/integrations/resident/session-log-reads.d.ts +37 -0
  112. package/dist/integrations/resident/session-log-reads.d.ts.map +1 -0
  113. package/dist/integrations/resident/session-log-reads.js +125 -0
  114. package/dist/integrations/resident/session-log-reads.js.map +1 -0
  115. package/dist/integrations/resident/session-step.d.ts +2 -0
  116. package/dist/integrations/resident/session-step.d.ts.map +1 -1
  117. package/dist/integrations/resident/session-step.js +15 -13
  118. package/dist/integrations/resident/session-step.js.map +1 -1
  119. package/dist/integrations/resident/storage.d.ts +23 -1
  120. package/dist/integrations/resident/storage.d.ts.map +1 -1
  121. package/dist/integrations/resident/storage.js +60 -17
  122. package/dist/integrations/resident/storage.js.map +1 -1
  123. package/dist/integrations/resident/tool-evidence.d.ts +4 -2
  124. package/dist/integrations/resident/tool-evidence.d.ts.map +1 -1
  125. package/dist/integrations/resident/tool-evidence.js +36 -30
  126. package/dist/integrations/resident/tool-evidence.js.map +1 -1
  127. package/dist/integrations/resident/verification.d.ts +2 -2
  128. package/dist/integrations/resident/verification.d.ts.map +1 -1
  129. package/dist/integrations/resident/verification.js +4 -4
  130. package/dist/integrations/resident/verification.js.map +1 -1
  131. package/dist/integrations/sessions/checkpoint-view.d.ts +13 -0
  132. package/dist/integrations/sessions/checkpoint-view.d.ts.map +1 -0
  133. package/dist/integrations/sessions/checkpoint-view.js +48 -0
  134. package/dist/integrations/sessions/checkpoint-view.js.map +1 -0
  135. package/dist/integrations/sessions/context-inventory.js +1 -1
  136. package/dist/integrations/sessions/context-inventory.js.map +1 -1
  137. package/dist/integrations/sessions/conversation-search.d.ts +16 -20
  138. package/dist/integrations/sessions/conversation-search.d.ts.map +1 -1
  139. package/dist/integrations/sessions/conversation-search.js +305 -731
  140. package/dist/integrations/sessions/conversation-search.js.map +1 -1
  141. package/dist/integrations/sessions/evidence-page-validation.d.ts +4 -4
  142. package/dist/integrations/sessions/evidence-page-validation.d.ts.map +1 -1
  143. package/dist/integrations/sessions/evidence-page-validation.js +1 -1
  144. package/dist/integrations/sessions/evidence-page-validation.js.map +1 -1
  145. package/dist/integrations/sessions/evidence-recall.d.ts +40 -2
  146. package/dist/integrations/sessions/evidence-recall.d.ts.map +1 -1
  147. package/dist/integrations/sessions/evidence-recall.js +41 -97
  148. package/dist/integrations/sessions/evidence-recall.js.map +1 -1
  149. package/dist/integrations/sessions/store.d.ts +153 -85
  150. package/dist/integrations/sessions/store.d.ts.map +1 -1
  151. package/dist/integrations/sessions/store.js +414 -484
  152. package/dist/integrations/sessions/store.js.map +1 -1
  153. package/dist/integrations/sessions/task-context.d.ts +15 -2
  154. package/dist/integrations/sessions/task-context.d.ts.map +1 -1
  155. package/dist/integrations/sessions/task-context.js +34 -11
  156. package/dist/integrations/sessions/task-context.js.map +1 -1
  157. package/dist/integrations/sessions/transcript-export.d.ts +13 -6
  158. package/dist/integrations/sessions/transcript-export.d.ts.map +1 -1
  159. package/dist/integrations/sessions/transcript-export.js +148 -263
  160. package/dist/integrations/sessions/transcript-export.js.map +1 -1
  161. package/dist/integrations/state/home.d.ts +4 -16
  162. package/dist/integrations/state/home.d.ts.map +1 -1
  163. package/dist/integrations/state/home.js +6 -42
  164. package/dist/integrations/state/home.js.map +1 -1
  165. package/dist/integrations/state/project.d.ts +6 -7
  166. package/dist/integrations/state/project.d.ts.map +1 -1
  167. package/dist/integrations/state/project.js +7 -9
  168. package/dist/integrations/state/project.js.map +1 -1
  169. package/dist/integrations/state/report.d.ts +27 -41
  170. package/dist/integrations/state/report.d.ts.map +1 -1
  171. package/dist/integrations/state/report.js +172 -464
  172. package/dist/integrations/state/report.js.map +1 -1
  173. package/dist/integrations/state/retention.d.ts +18 -0
  174. package/dist/integrations/state/retention.d.ts.map +1 -0
  175. package/dist/integrations/state/retention.js +18 -0
  176. package/dist/integrations/state/retention.js.map +1 -0
  177. package/dist/integrations/subagents/activity.d.ts +36 -31
  178. package/dist/integrations/subagents/activity.d.ts.map +1 -1
  179. package/dist/integrations/subagents/activity.js +27 -23
  180. package/dist/integrations/subagents/activity.js.map +1 -1
  181. package/dist/integrations/subagents/batches.d.ts +91 -0
  182. package/dist/integrations/subagents/batches.d.ts.map +1 -0
  183. package/dist/integrations/subagents/batches.js +172 -0
  184. package/dist/integrations/subagents/batches.js.map +1 -0
  185. package/dist/integrations/subagents/parent.d.ts +26 -11
  186. package/dist/integrations/subagents/parent.d.ts.map +1 -1
  187. package/dist/integrations/subagents/parent.js +13 -28
  188. package/dist/integrations/subagents/parent.js.map +1 -1
  189. package/dist/integrations/subagents/policy.d.ts +2 -2
  190. package/dist/integrations/subagents/policy.d.ts.map +1 -1
  191. package/dist/integrations/subagents/policy.js +2 -2
  192. package/dist/integrations/subagents/policy.js.map +1 -1
  193. package/dist/integrations/subagents/replay.d.ts +91 -26
  194. package/dist/integrations/subagents/replay.d.ts.map +1 -1
  195. package/dist/integrations/subagents/replay.js +216 -114
  196. package/dist/integrations/subagents/replay.js.map +1 -1
  197. package/dist/integrations/subagents/runtime.d.ts +50 -26
  198. package/dist/integrations/subagents/runtime.d.ts.map +1 -1
  199. package/dist/integrations/subagents/runtime.js +132 -126
  200. package/dist/integrations/subagents/runtime.js.map +1 -1
  201. package/dist/integrations/subagents/saved-agents.d.ts +57 -0
  202. package/dist/integrations/subagents/saved-agents.d.ts.map +1 -0
  203. package/dist/integrations/subagents/saved-agents.js +102 -0
  204. package/dist/integrations/subagents/saved-agents.js.map +1 -0
  205. package/dist/integrations/subagents/slash.d.ts +55 -0
  206. package/dist/integrations/subagents/slash.d.ts.map +1 -0
  207. package/dist/integrations/subagents/slash.js +45 -0
  208. package/dist/integrations/subagents/slash.js.map +1 -0
  209. package/dist/integrations/telemetry/session-export.d.ts +6 -6
  210. package/dist/integrations/telemetry/session-export.d.ts.map +1 -1
  211. package/dist/integrations/telemetry/session-export.js +2 -2
  212. package/dist/memory/presentation.d.ts +11 -0
  213. package/dist/memory/presentation.d.ts.map +1 -1
  214. package/dist/memory/presentation.js +25 -0
  215. package/dist/memory/presentation.js.map +1 -1
  216. package/dist/memory/store.d.ts +13 -7
  217. package/dist/memory/store.d.ts.map +1 -1
  218. package/dist/memory/store.js +37 -11
  219. package/dist/memory/store.js.map +1 -1
  220. package/dist/memory/typed.d.ts +116 -0
  221. package/dist/memory/typed.d.ts.map +1 -0
  222. package/dist/memory/typed.js +336 -0
  223. package/dist/memory/typed.js.map +1 -0
  224. package/dist/permissions/checks.d.ts +1 -1
  225. package/dist/permissions/checks.js +1 -1
  226. package/dist/permissions/headless-trust.d.ts +2 -2
  227. package/dist/permissions/headless-trust.d.ts.map +1 -1
  228. package/dist/permissions/headless-trust.js +3 -3
  229. package/dist/permissions/headless-trust.js.map +1 -1
  230. package/dist/permissions/mode.d.ts +4 -4
  231. package/dist/permissions/mode.js +1 -1
  232. package/dist/permissions/rules.d.ts +1 -1
  233. package/dist/permissions/rules.js +1 -1
  234. package/dist/termination.d.ts +75 -0
  235. package/dist/termination.d.ts.map +1 -0
  236. package/dist/termination.js +143 -0
  237. package/dist/termination.js.map +1 -0
  238. package/dist/tui/AgentExplorer.d.ts +2 -2
  239. package/dist/tui/AgentExplorer.js +4 -4
  240. package/dist/tui/AgentExplorer.js.map +1 -1
  241. package/dist/tui/App.d.ts +9 -1
  242. package/dist/tui/App.d.ts.map +1 -1
  243. package/dist/tui/App.js +452 -303
  244. package/dist/tui/App.js.map +1 -1
  245. package/dist/tui/LiveActivity.d.ts +1 -1
  246. package/dist/tui/LiveActivity.d.ts.map +1 -1
  247. package/dist/tui/PermissionOverlay.d.ts +8 -0
  248. package/dist/tui/PermissionOverlay.d.ts.map +1 -1
  249. package/dist/tui/PermissionOverlay.js +25 -2
  250. package/dist/tui/PermissionOverlay.js.map +1 -1
  251. package/dist/tui/Picker.js +1 -1
  252. package/dist/tui/agent.d.ts +208 -132
  253. package/dist/tui/agent.d.ts.map +1 -1
  254. package/dist/tui/agent.js +523 -313
  255. package/dist/tui/agent.js.map +1 -1
  256. package/dist/tui/conversation-evidence-view.js +3 -3
  257. package/dist/tui/conversation-evidence-view.js.map +1 -1
  258. package/dist/tui/conversation-history.d.ts +4 -21
  259. package/dist/tui/conversation-history.d.ts.map +1 -1
  260. package/dist/tui/conversation-history.js +4 -28
  261. package/dist/tui/conversation-history.js.map +1 -1
  262. package/dist/tui/index.d.ts.map +1 -1
  263. package/dist/tui/index.js +27 -1
  264. package/dist/tui/index.js.map +1 -1
  265. package/dist/tui/log-pane.js +1 -1
  266. package/dist/tui/markdownParser.d.ts +1 -1
  267. package/dist/tui/markdownParser.js +1 -1
  268. package/dist/tui/permission-review.d.ts +16 -0
  269. package/dist/tui/permission-review.d.ts.map +1 -1
  270. package/dist/tui/permission-review.js +25 -2
  271. package/dist/tui/permission-review.js.map +1 -1
  272. package/dist/tui/slashCommands.d.ts +29 -40
  273. package/dist/tui/slashCommands.d.ts.map +1 -1
  274. package/dist/tui/slashCommands.js +70 -61
  275. package/dist/tui/slashCommands.js.map +1 -1
  276. package/dist/tui/{run-interruption.d.ts → turn-interruption.d.ts} +4 -4
  277. package/dist/tui/turn-interruption.d.ts.map +1 -0
  278. package/dist/tui/{run-interruption.js → turn-interruption.js} +20 -20
  279. package/dist/tui/turn-interruption.js.map +1 -0
  280. package/dist/tui/turn-limits-settings.d.ts +39 -0
  281. package/dist/tui/turn-limits-settings.d.ts.map +1 -0
  282. package/dist/tui/{run-limits-settings.js → turn-limits-settings.js} +18 -18
  283. package/dist/tui/turn-limits-settings.js.map +1 -0
  284. package/dist/tui/types.d.ts +3 -3
  285. package/dist/tui/types.d.ts.map +1 -1
  286. package/dist/user-commands/store.d.ts +1 -1
  287. package/dist/user-commands/store.js +1 -1
  288. package/package.json +7 -7
  289. package/dist/integrations/sessions/compaction-evidence.d.ts +0 -5
  290. package/dist/integrations/sessions/compaction-evidence.d.ts.map +0 -1
  291. package/dist/integrations/sessions/compaction-evidence.js +0 -59
  292. package/dist/integrations/sessions/compaction-evidence.js.map +0 -1
  293. package/dist/integrations/sessions/database.d.ts +0 -5
  294. package/dist/integrations/sessions/database.d.ts.map +0 -1
  295. package/dist/integrations/sessions/database.js +0 -34
  296. package/dist/integrations/sessions/database.js.map +0 -1
  297. package/dist/integrations/sessions/paths.d.ts +0 -7
  298. package/dist/integrations/sessions/paths.d.ts.map +0 -1
  299. package/dist/integrations/sessions/paths.js +0 -14
  300. package/dist/integrations/sessions/paths.js.map +0 -1
  301. package/dist/integrations/sessions/run-discovery.d.ts +0 -24
  302. package/dist/integrations/sessions/run-discovery.d.ts.map +0 -1
  303. package/dist/integrations/sessions/run-discovery.js +0 -142
  304. package/dist/integrations/sessions/run-discovery.js.map +0 -1
  305. package/dist/integrations/sessions/turn-evidence.d.ts +0 -129
  306. package/dist/integrations/sessions/turn-evidence.d.ts.map +0 -1
  307. package/dist/integrations/sessions/turn-evidence.js +0 -517
  308. package/dist/integrations/sessions/turn-evidence.js.map +0 -1
  309. package/dist/integrations/subagents/history.d.ts +0 -26
  310. package/dist/integrations/subagents/history.d.ts.map +0 -1
  311. package/dist/integrations/subagents/history.js +0 -76
  312. package/dist/integrations/subagents/history.js.map +0 -1
  313. package/dist/integrations/subagents/runs.d.ts +0 -72
  314. package/dist/integrations/subagents/runs.d.ts.map +0 -1
  315. package/dist/integrations/subagents/runs.js +0 -155
  316. package/dist/integrations/subagents/runs.js.map +0 -1
  317. package/dist/tui/run-interruption.d.ts.map +0 -1
  318. package/dist/tui/run-interruption.js.map +0 -1
  319. package/dist/tui/run-limits-settings.d.ts +0 -39
  320. package/dist/tui/run-limits-settings.d.ts.map +0 -1
  321. package/dist/tui/run-limits-settings.js.map +0 -1
@@ -5,20 +5,24 @@
5
5
  * pre-registered definition needed. Omit `role` for a general-purpose one.
6
6
  * The call waits for a final result unless background execution is requested
7
7
  * or operator input releases the wait.
8
- * The child then stays owned by the parent run, and its completion reaches the
8
+ * The child then stays owned by the parent turn, and its completion reaches the
9
9
  * same query's inbox. Headless callers also support explicit background work.
10
10
  *
11
11
  * The runtime is fully self-contained: a dedicated in-memory session/thread
12
12
  * store backs the AgentManager, so sub-agent bookkeeping never touches the
13
- * CLI's on-disk `/resume` conversation store. A separate session-scoped
14
- * receipt archive preserves observed outcomes without restoring execution authority.
13
+ * CLI's `/resume` conversation store. Each child is a child session whose log
14
+ * the SDK writes under the parent's `<session-id>/subagents/`, and the parent's
15
+ * log records its spawn and its ending; the saved-agents reader
16
+ * (`saved-agents.ts`) reads those records back as evidence, never as execution
17
+ * authority.
15
18
  */
16
- import { AgentManager, AgentRegistry, CompletionInbox, DefaultCapacityValidator, EXPLORE_AGENT_DESCRIPTION, EXPLORE_AGENT_ID, EXPLORE_AGENT_PROMPT, InMemorySessionStore, InMemoryTopicStore, LocalTaskScheduler, ReactiveAgent, RunCancelled, SessionSummaryMaterializer, TopicArchivedError, TopicManager, WorkspaceBackendRegistry, asRunId, asTaskId, defineTool, filterReadOnlyTools, filterToolsNamed, generateSummaryId, isTerminalAgentTaskState, mcpJsonSchemaToZod, openTokenBudget, requireOpenProject, } from '@namzu/sdk';
17
- import { resolveRunGuards } from '../../config/run-limits.js';
19
+ import { AgentManager, AgentRegistry, CompletionInbox, DefaultCapacityValidator, DiskSessionTokenBudgetStore, EXPLORE_AGENT_DESCRIPTION, EXPLORE_AGENT_ID, EXPLORE_AGENT_PROMPT, InMemorySessionStore, InMemorySessionTokenBudgetStore, InMemoryTopicStore, LocalTaskScheduler, ReactiveAgent, SessionSummaryMaterializer, TopicArchivedError, TopicManager, TurnCancelled, WorkspaceBackendRegistry, asTaskId, asTurnId, defineTool, filterReadOnlyTools, filterToolsNamed, generateSummaryId, isTerminalAgentTaskState, mcpJsonSchemaToZod, openSessionTokenBudget, requireOpenProject, } from '@namzu/sdk';
20
+ import { resolveTurnGuards } from '../../config/run-limits.js';
18
21
  import { NAMZU_WORKING_DOCTRINE } from '../../context/doctrine.js';
22
+ import { CLI_CHECKPOINT_RETENTION } from '../state/retention.js';
19
23
  import { MAX_AGENT_ACTIVITY_LABEL_CODE_UNITS, MAX_AGENT_PHASE_ORDER, MAX_NARRATION_CODE_UNITS, MAX_RETAINED_NARRATION, SubagentActivityMonitor, } from './activity.js';
20
- import { DelegationHistory, HISTORY_GUIDANCE } from './history.js';
21
- import { CLI_INTERACTIVE_RUN_TIMEOUT_MS } from './policy.js';
24
+ import { CLI_INTERACTIVE_TURN_TIMEOUT_MS } from './policy.js';
25
+ import { SAVED_AGENTS_GUIDANCE } from './saved-agents.js';
22
26
  /**
23
27
  * The parent's narration tool, named once.
24
28
  *
@@ -69,12 +73,12 @@ const SUBAGENT_PROMPT = [
69
73
  '- If you need to research and have no web tool available, say so plainly and answer from your own knowledge with that caveat — do not invent sources, data, or URLs.',
70
74
  '- Do not invent command output or results. If you cannot complete the task, say what blocked you.',
71
75
  '',
72
- // The same working rules the parent runs under. A delegated task edits the
76
+ // The same working rules the parent sessions under. A delegated task edits the
73
77
  // same repository, and a child that reads a file before editing it while
74
78
  // the parent does not is the same defect in the other direction.
75
79
  NAMZU_WORKING_DOCTRINE,
76
80
  ].join('\n');
77
- /** Recheck the invoking run before admitting work through a retained gateway. */
81
+ /** Recheck the invoking turn before admitting work through a retained gateway. */
78
82
  class ParentTaskScheduler extends LocalTaskScheduler {
79
83
  validateParent;
80
84
  constructor(manager, context, onEvent, validateParent) {
@@ -106,22 +110,22 @@ class ParentTaskScheduler extends LocalTaskScheduler {
106
110
  async waitForTask(taskId) {
107
111
  const task = this.getTask(taskId);
108
112
  if (!task)
109
- throw new Error(`Task ${taskId} does not belong to this parent run`);
113
+ throw new Error(`Task ${taskId} does not belong to this parent turn`);
110
114
  if (isTerminalAgentTaskState(task.state))
111
115
  return task;
112
116
  return super.waitForTask(taskId);
113
117
  }
114
118
  async continueTask(taskId, message) {
115
119
  if (!this.owns(taskId))
116
- throw new Error(`Task ${taskId} does not belong to this parent run`);
120
+ throw new Error(`Task ${taskId} does not belong to this parent turn`);
117
121
  await this.validateParent();
118
122
  await super.continueTask(taskId, message);
119
123
  }
120
124
  }
121
- /** A delegated run may never inherit the SDK's headless auto-approval fallback. */
125
+ /** A delegated child may never inherit the SDK's headless auto-approval fallback. */
122
126
  const refuseUnownedChildReview = async () => ({
123
127
  action: 'abort',
124
- reason: 'The parent run no longer owns an interactive review channel for this sub-agent.',
128
+ reason: 'The parent turn no longer owns an interactive review channel for this sub-agent.',
125
129
  });
126
130
  /**
127
131
  * Stand up the AgentManager + gateway + `Agent` tool. Returns the tool to
@@ -147,10 +151,18 @@ export async function createSubagentRuntime(opts) {
147
151
  .join('; ');
148
152
  const parents = new Map();
149
153
  const sessions = new Map();
154
+ // A ledger this runtime keeps for itself, when neither a shared store nor a
155
+ // project layout was given. Process-local: it bounds the children of one
156
+ // root turn, and the parent's own spend is counted wherever the parent
157
+ // keeps its ledger.
158
+ const tokenBudgetStore = opts.tokenBudgetStore ??
159
+ (opts.paths
160
+ ? new DiskSessionTokenBudgetStore({ paths: opts.paths })
161
+ : new InMemorySessionTokenBudgetStore());
150
162
  let closed = false;
151
163
  const sessionKey = ({ project, sessionId }) => JSON.stringify([project.tenantId, project.id, sessionId]);
152
- const resolveParent = async (runId) => {
153
- const parent = structuredClone(await opts.resolveParent(runId));
164
+ const resolveParent = async (turnId) => {
165
+ const parent = structuredClone(await opts.resolveParent(turnId));
154
166
  const { project, topic } = parent;
155
167
  if (topic.projectId !== project.id || topic.tenantId !== project.tenantId) {
156
168
  throw new Error('Delegation parent topic does not belong to its project and tenant');
@@ -174,7 +186,7 @@ export async function createSubagentRuntime(opts) {
174
186
  }, tenantId);
175
187
  await store.updateSession({ ...session, status: 'active' }, tenantId);
176
188
  const manager = new AgentManager(registry, {
177
- childTimeoutMs: opts.timeoutMs ?? CLI_INTERACTIVE_RUN_TIMEOUT_MS,
189
+ childTimeoutMs: opts.timeoutMs ?? CLI_INTERACTIVE_TURN_TIMEOUT_MS,
178
190
  capacityBehavior: 'queue',
179
191
  }, {
180
192
  sessionStore: store,
@@ -195,7 +207,7 @@ export async function createSubagentRuntime(opts) {
195
207
  };
196
208
  const refreshLimits = async (shared, parent) => {
197
209
  if (shared.topicId !== parent.topic.id)
198
- throw new Error('Delegation parent changed its topic while runs are active');
210
+ throw new Error('Delegation parent changed its topic while turns are active');
199
211
  // A slow metadata read must not overwrite a newer project snapshot.
200
212
  const updatedAt = parent.project.updatedAt.getTime();
201
213
  if (updatedAt < shared.projectUpdatedAt)
@@ -234,24 +246,23 @@ export async function createSubagentRuntime(opts) {
234
246
  throw error;
235
247
  }
236
248
  };
237
- const gatewayForRun = async (runId) => {
249
+ const gatewayForTurn = async (turnId) => {
238
250
  if (closed)
239
251
  throw new Error('Sub-agent runtime is closed');
240
- let pending = parents.get(runId);
252
+ let pending = parents.get(turnId);
241
253
  if (!pending) {
242
254
  pending = (async () => {
243
- const parent = await resolveParent(runId);
244
- const budget = await openTokenBudget({
245
- scope: {
246
- tenantId: parent.project.tenantId,
247
- projectId: parent.project.id,
248
- sessionId: parent.sessionId,
249
- runId,
250
- },
251
- limit: resolveRunGuards(opts, opts.resolveLimits?.(runId)).tokenBudget,
252
- pathBuilder: opts.pathBuilder,
253
- workingDirectory: opts.cwd,
255
+ const parent = await resolveParent(turnId);
256
+ // The invoking turn is the root of this delegation tree, so its
257
+ // ledger is keyed `(parent session, invoking turn)` — the ledger the
258
+ // parent's own `query()` opened for this turn when it shares the
259
+ // store. Every child spends from an account reserved under it.
260
+ const budget = await openSessionTokenBudget({
261
+ store: tokenBudgetStore,
262
+ scope: { rootSessionId: parent.sessionId, rootTurnId: turnId },
263
+ limit: resolveTurnGuards(opts, opts.resolveLimits?.(turnId)).tokenBudget,
254
264
  });
265
+ budget.bindTurn(parent.sessionId, turnId);
255
266
  const lease = await acquireSession(parent);
256
267
  const { manager } = lease.shared;
257
268
  const parentAbortController = new AbortController();
@@ -260,12 +271,13 @@ export async function createSubagentRuntime(opts) {
260
271
  if (closed ||
261
272
  released ||
262
273
  parentAbortController.signal.aborted ||
263
- parents.get(runId) !== pending) {
264
- throw new Error(`Parent run ${runId} was released`);
274
+ parents.get(turnId) !== pending) {
275
+ throw new Error(`Parent turn ${turnId} was released`);
265
276
  }
266
277
  };
267
278
  const taskContext = {
268
- parentRunId: runId,
279
+ parentSessionId: parent.sessionId,
280
+ parentTurnId: turnId,
269
281
  parentAgentId: 'namzu',
270
282
  parentAbortController,
271
283
  depth: 0,
@@ -282,10 +294,10 @@ export async function createSubagentRuntime(opts) {
282
294
  };
283
295
  const gateway = new ParentTaskScheduler(manager, taskContext, opts.onEvent, async () => {
284
296
  assertOwned();
285
- const current = await resolveParent(runId);
297
+ const current = await resolveParent(turnId);
286
298
  assertOwned();
287
299
  if (sessionKey(current) !== sessionKey(parent))
288
- throw new Error('Delegation run changed its parent scope');
300
+ throw new Error('Delegation turn changed its parent scope');
289
301
  await refreshLimits(lease.shared, current);
290
302
  assertOwned();
291
303
  });
@@ -298,8 +310,13 @@ export async function createSubagentRuntime(opts) {
298
310
  if (released)
299
311
  return;
300
312
  released = true;
301
- parentAbortController.abort(new RunCancelled('parent'));
302
- manager.cancelAll(runId, 'parent');
313
+ parentAbortController.abort(new TurnCancelled('parent'));
314
+ // Only this turn's children. The manager is shared by every
315
+ // turn of the session, and `cancelAll` would reach them all.
316
+ for (const task of manager.listByParent(parent.sessionId)) {
317
+ if (task.context.parentTurnId === turnId)
318
+ manager.cancel(task.taskId, 'parent');
319
+ }
303
320
  completionInbox.close();
304
321
  lease.release();
305
322
  },
@@ -310,32 +327,32 @@ export async function createSubagentRuntime(opts) {
310
327
  }
311
328
  return runtime;
312
329
  })();
313
- parents.set(runId, pending);
330
+ parents.set(turnId, pending);
314
331
  }
315
332
  try {
316
333
  const runtime = await pending;
317
- if (closed || parents.get(runId) !== pending)
318
- throw new Error(`Parent run ${runId} was released`);
334
+ if (closed || parents.get(turnId) !== pending)
335
+ throw new Error(`Parent turn ${turnId} was released`);
319
336
  return runtime.gateway;
320
337
  }
321
338
  catch (error) {
322
- if (parents.get(runId) === pending)
323
- parents.delete(runId);
339
+ if (parents.get(turnId) === pending)
340
+ parents.delete(turnId);
324
341
  throw error;
325
342
  }
326
343
  };
327
- const releaseRun = async (runId) => {
328
- const pending = parents.get(runId);
344
+ const releaseTurn = async (turnId) => {
345
+ const pending = parents.get(turnId);
329
346
  if (!pending)
330
347
  return;
331
- parents.delete(runId);
348
+ parents.delete(turnId);
332
349
  await pending.then((runtime) => runtime.close(), () => undefined);
333
350
  };
334
- const completionInboxForRun = async (runId) => {
335
- await gatewayForRun(runId);
336
- const pending = parents.get(runId);
351
+ const completionInboxForTurn = async (turnId) => {
352
+ await gatewayForTurn(turnId);
353
+ const pending = parents.get(turnId);
337
354
  if (!pending)
338
- throw new Error(`Parent run ${runId} was released`);
355
+ throw new Error(`Parent turn ${turnId} was released`);
339
356
  return (await pending).completionInbox;
340
357
  };
341
358
  const activity = new SubagentActivityMonitor();
@@ -428,7 +445,7 @@ export async function createSubagentRuntime(opts) {
428
445
  readOnly: false,
429
446
  destructive: false,
430
447
  concurrencySafe: true,
431
- timeoutMs: opts.resolveLimits ? 0 : (opts.timeoutMs ?? CLI_INTERACTIVE_RUN_TIMEOUT_MS),
448
+ timeoutMs: opts.resolveLimits ? 0 : (opts.timeoutMs ?? CLI_INTERACTIVE_TURN_TIMEOUT_MS),
432
449
  async execute(input, context) {
433
450
  const { description, prompt, subagent_type, role, workflow, phase, phase_order, phase_detail, run_in_background, model: requestedModel, provider: requestedProvider, effort: requestedEffort, } = input;
434
451
  if (!requestedModel && (requestedProvider || requestedEffort))
@@ -469,25 +486,25 @@ export async function createSubagentRuntime(opts) {
469
486
  prompt,
470
487
  batchId: context.toolBatchId,
471
488
  toolUseId: context.toolUseId,
472
- workflowId: String(context.runId),
489
+ workflowId: String(context.turnId),
473
490
  workflow,
474
491
  phase,
475
492
  phaseOrder: phase_order,
476
493
  phaseDetail: phase_detail,
477
494
  });
478
- // The child is a separate run, but its human authority belongs to the
495
+ // The child is a separate session, but its human authority belongs to the
479
496
  // parent turn that invoked Agent. `drainQuery` deliberately auto-approves
480
497
  // when a handler is omitted for headless SDK callers; omission here would
481
498
  // therefore turn a missing/stale parent mapping into permission to mutate
482
499
  // the real project. Always install a handler, and abort if ownership can no
483
500
  // longer be proved.
484
- const resumeHandler = opts.resolveResumeHandler?.(context.runId) ?? refuseUnownedChildReview;
501
+ const resumeHandler = opts.resolveResumeHandler?.(context.turnId) ?? refuseUnownedChildReview;
485
502
  const configOverrides = {
486
- ...resolveRunGuards(opts, opts.resolveLimits?.(context.runId)),
503
+ ...resolveTurnGuards(opts, opts.resolveLimits?.(context.turnId)),
487
504
  ...(selection ? { model: selection.model, effort: selection.effort } : {}),
488
505
  ...(Object.keys(context.env ?? {}).length > 0 ? { env: context.env } : {}),
489
- // The parent run's tool-result screens, so a sub-agent judges a
490
- // connected answer the way the run that asked for the work
506
+ // The parent turn's tool-result screens, so a sub-agent judges a
507
+ // connected answer the way the turn that asked for the work
491
508
  // does. Without it the child's executor installs the shipped
492
509
  // default, and `toolResultScreens: []` — the operator's off
493
510
  // switch — would hold for the parent and not for anything it
@@ -507,32 +524,19 @@ export async function createSubagentRuntime(opts) {
507
524
  registry.unregister(agentId);
508
525
  };
509
526
  try {
510
- const completionInbox = await completionInboxForRun(context.runId);
511
- const parent = await resolveParent(context.runId);
512
- const history = opts.historyRoot
513
- ? new DelegationHistory(opts.historyRoot, parent.sessionId)
514
- : undefined;
515
- const save = (handle, terminal) => {
516
- history?.write({
517
- taskId: handle.taskId,
518
- parentRunId: context.runId,
519
- description,
520
- status: terminal ? agentTaskOutcome(handle) : 'unresolved',
521
- ...(terminal ? { output: String(completedAgentResult(handle).output ?? '') } : {}),
522
- });
523
- };
527
+ const completionInbox = await completionInboxForTurn(context.turnId);
528
+ // Nothing is saved here: the SDK records the child's spawn and its
529
+ // ending in the parent's log, and the child's own log beside it.
524
530
  const outcome = await runBlockingAgentTask({
525
- gateway: await gatewayForRun(context.runId),
531
+ gateway: await gatewayForTurn(context.turnId),
526
532
  signal: context.abortSignal,
527
- waitForInbound: opts.resolveWaitForInbound?.(context.runId),
533
+ waitForInbound: opts.resolveWaitForInbound?.(context.turnId),
528
534
  background: run_in_background === true,
529
535
  completionInbox,
530
- onCreated: (handle) => {
531
- save(handle, false);
536
+ onCreated: () => {
532
537
  taskOwnsCleanup = true;
533
538
  },
534
539
  onSettled: (completed) => {
535
- save(completed, true);
536
540
  tracker.settle(completed);
537
541
  },
538
542
  onFailed: (error) => tracker.fail(error),
@@ -551,7 +555,7 @@ export async function createSubagentRuntime(opts) {
551
555
  ...(phase ? { phase } : {}),
552
556
  ...(phase_detail ? { phaseDetail: phase_detail } : {}),
553
557
  ...(phase_order !== undefined ? { phaseOrder: phase_order } : {}),
554
- // Hang the child run off THIS tool's span, so the delegation
558
+ // Hang the child session off THIS tool's span, so the delegation
555
559
  // shows up inside the turn that asked for it. Without it a
556
560
  // sub-agent opens its OWN root trace, and the one structure
557
561
  // a delegation trace exists to record — who dispatched whom
@@ -589,10 +593,10 @@ export async function createSubagentRuntime(opts) {
589
593
  });
590
594
  const agentTaskListTool = defineTool({
591
595
  name: 'agent_task_list',
592
- description: 'List the agent invocations launched by this run and their current status, without waiting or starting work. Use this for agent progress questions. task_list contains planning items, not agent invocations. Use wait_for_task with a live ID for its result. Set history: true to inspect saved receipts from this conversation, optionally task_id for one saved result; archives do not prove liveness.',
596
+ description: 'List the agent invocations launched by this turn and their current status, without waiting or starting work. Use this for agent progress questions. task_list contains planning items, not agent invocations. Use wait_for_task with a live ID for its result. Set history: true to inspect agents saved from earlier turns of this conversation, optionally session_id for one saved result; saved agents are not live.',
593
597
  inputSchema: mcpJsonSchemaToZod({
594
598
  type: 'object',
595
- properties: { history: { type: 'boolean' }, task_id: { type: 'string' } },
599
+ properties: { history: { type: 'boolean' }, session_id: { type: 'string' } },
596
600
  additionalProperties: false,
597
601
  }),
598
602
  category: 'custom',
@@ -602,28 +606,27 @@ export async function createSubagentRuntime(opts) {
602
606
  concurrencySafe: true,
603
607
  async execute(input, context) {
604
608
  const request = input;
605
- if (request.history || request.task_id) {
606
- if (!opts.historyRoot)
609
+ if (request.history || request.session_id) {
610
+ if (!opts.savedAgents)
607
611
  return {
608
612
  success: false,
609
613
  output: 'Saved delegation history is unavailable in this host.',
610
614
  };
611
- const parent = await resolveParent(context.runId);
612
- const history = new DelegationHistory(opts.historyRoot, parent.sessionId);
613
- const saved = request.task_id
614
- ? { tasks: [history.read(request.task_id)], omitted: 0 }
615
- : history.list();
616
- const tasks = saved.tasks.map(({ output, ...row }) => request.task_id ? { ...row, output } : row);
615
+ const parent = await resolveParent(context.turnId);
616
+ const history = opts.savedAgents(parent.sessionId);
617
+ const saved = request.session_id
618
+ ? { agents: [await history.read(request.session_id)], omitted: 0 }
619
+ : await history.list();
617
620
  return {
618
621
  success: true,
619
622
  output: JSON.stringify({
620
- ...saved,
621
- tasks,
622
- guidance: HISTORY_GUIDANCE,
623
+ agents: saved.agents,
624
+ omitted: saved.omitted,
625
+ guidance: SAVED_AGENTS_GUIDANCE,
623
626
  }),
624
627
  };
625
628
  }
626
- const gateway = await gatewayForRun(context.runId);
629
+ const gateway = await gatewayForTurn(context.turnId);
627
630
  const tasks = gateway.listTasks();
628
631
  const labels = new Map(activity.getSnapshot().map((entry) => [entry.taskId, entry.description]));
629
632
  const shown = tasks.slice(-40).map((task) => ({
@@ -651,7 +654,7 @@ export async function createSubagentRuntime(opts) {
651
654
  });
652
655
  const waitForTaskTool = defineTool({
653
656
  name: 'wait_for_task',
654
- description: 'Wait for a task this run already launched, or retrieve its complete result after a task notification. This does not start new work. Operator input releases the wait while the task continues.',
657
+ description: 'Wait for a task this turn already launched, or retrieve its complete result after a task notification. This does not start new work. Operator input releases the wait while the task continues.',
655
658
  inputSchema: mcpJsonSchemaToZod({
656
659
  type: 'object',
657
660
  properties: {
@@ -667,9 +670,9 @@ export async function createSubagentRuntime(opts) {
667
670
  readOnly: true,
668
671
  destructive: false,
669
672
  concurrencySafe: true,
670
- timeoutMs: opts.resolveLimits ? 0 : (opts.timeoutMs ?? CLI_INTERACTIVE_RUN_TIMEOUT_MS),
673
+ timeoutMs: opts.resolveLimits ? 0 : (opts.timeoutMs ?? CLI_INTERACTIVE_TURN_TIMEOUT_MS),
671
674
  async execute(input, context) {
672
- const gateway = await gatewayForRun(context.runId);
675
+ const gateway = await gatewayForTurn(context.turnId);
673
676
  let taskId;
674
677
  try {
675
678
  taskId = asTaskId(input.task_id);
@@ -686,14 +689,14 @@ export async function createSubagentRuntime(opts) {
686
689
  return {
687
690
  success: false,
688
691
  output: '',
689
- error: `Task ${taskId} does not belong to this parent run.`,
692
+ error: `Task ${taskId} does not belong to this parent turn.`,
690
693
  };
691
694
  const outcome = await runBlockingAgentTask({
692
695
  gateway,
693
696
  task,
694
697
  signal: context.abortSignal,
695
- completionInbox: await completionInboxForRun(context.runId),
696
- waitForInbound: opts.resolveWaitForInbound?.(context.runId),
698
+ completionInbox: await completionInboxForTurn(context.turnId),
699
+ waitForInbound: opts.resolveWaitForInbound?.(context.turnId),
697
700
  onCreated: () => { },
698
701
  onSettled: () => { },
699
702
  onFailed: () => { },
@@ -715,7 +718,7 @@ export async function createSubagentRuntime(opts) {
715
718
  });
716
719
  const sendMessageTool = defineTool({
717
720
  name: 'send_message',
718
- description: 'Queue a correction or additional context for a running or queued sub-agent task owned by this run. The child receives it at its next request boundary; acceptance is not delivery. This does not start new work or restart finished tasks.',
721
+ description: 'Queue a correction or additional context for a running or queued sub-agent task owned by this turn. The child receives it at its next request boundary; acceptance is not delivery. This does not start new work or restart finished tasks.',
719
722
  inputSchema: mcpJsonSchemaToZod({
720
723
  type: 'object',
721
724
  properties: {
@@ -748,13 +751,13 @@ export async function createSubagentRuntime(opts) {
748
751
  error: 'Message must not be blank.',
749
752
  };
750
753
  const taskId = asTaskId(task_id);
751
- const gateway = await gatewayForRun(context.runId);
754
+ const gateway = await gatewayForTurn(context.turnId);
752
755
  const task = gateway.getTask(taskId);
753
756
  if (!task)
754
757
  return {
755
758
  success: false,
756
759
  output: '',
757
- error: `Task ${taskId} does not belong to this parent run.`,
760
+ error: `Task ${taskId} does not belong to this parent turn.`,
758
761
  };
759
762
  if (isTerminalAgentTaskState(task.state))
760
763
  return {
@@ -777,7 +780,7 @@ export async function createSubagentRuntime(opts) {
777
780
  });
778
781
  const cancelAgentTool = defineTool({
779
782
  name: 'cancel_agent',
780
- description: 'Request cancellation of one running or queued agent task owned by this run. Other agents and the parent continue. Acceptance is not proof of termination; check agent_task_list or wait_for_task for the terminal outcome. Does not restart finished tasks.',
783
+ description: 'Request cancellation of one running or queued agent task owned by this turn. Other agents and the parent continue. Acceptance is not proof of termination; check agent_task_list or wait_for_task for the terminal outcome. Does not restart finished tasks.',
781
784
  inputSchema: mcpJsonSchemaToZod({
782
785
  type: 'object',
783
786
  properties: {
@@ -797,13 +800,13 @@ export async function createSubagentRuntime(opts) {
797
800
  async execute(input, context) {
798
801
  context.abortSignal.throwIfAborted();
799
802
  const taskId = asTaskId(input.task_id);
800
- const gateway = await gatewayForRun(context.runId);
803
+ const gateway = await gatewayForTurn(context.turnId);
801
804
  const task = gateway.getTask(taskId);
802
805
  if (!task)
803
806
  return {
804
807
  success: false,
805
808
  output: '',
806
- error: `Task ${taskId} does not belong to this parent run.`,
809
+ error: `Task ${taskId} does not belong to this parent turn.`,
807
810
  };
808
811
  if (isTerminalAgentTaskState(task.state))
809
812
  return {
@@ -855,7 +858,7 @@ export async function createSubagentRuntime(opts) {
855
858
  // for the operator who would otherwise be asked to approve being shown
856
859
  // it — a consent dialog per line of commentary is a tool nobody would
857
860
  // call. This is not a claim that the line is ephemeral: the kernel
858
- // records THIS call in the run's transcript and checkpoints exactly as
861
+ // records THIS call in the session log and checkpoints exactly as
859
862
  // it records every other, so the text comes back into the model's own
860
863
  // history on a resume even though the band it was shown in does not.
861
864
  // Narration's parent-only boundary does not rest on this flag either:
@@ -901,7 +904,7 @@ export async function createSubagentRuntime(opts) {
901
904
  if (closePromise)
902
905
  return closePromise;
903
906
  closed = true;
904
- closePromise = Promise.all([...parents.keys()].map(releaseRun)).then(() => activity.close());
907
+ closePromise = Promise.all([...parents.keys()].map(releaseTurn)).then(() => activity.close());
905
908
  return closePromise;
906
909
  };
907
910
  const listModels = opts.listModels;
@@ -934,9 +937,9 @@ export async function createSubagentRuntime(opts) {
934
937
  return {
935
938
  cancelAgentTool,
936
939
  modelCatalogueTool,
937
- gatewayForRun,
938
- completionInboxForRun,
939
- releaseRun,
940
+ gatewayForTurn,
941
+ completionInboxForTurn,
942
+ releaseTurn,
940
943
  agentTool,
941
944
  waitForTaskTool,
942
945
  agentTaskListTool,
@@ -1042,24 +1045,24 @@ async function runBlockingAgentTask(input) {
1042
1045
  }
1043
1046
  }
1044
1047
  function agentTaskOutcome(task) {
1045
- const run = task.result;
1046
- if (run?.status && run.status !== 'completed')
1047
- return run.status;
1048
- if (task.state === 'completed' && run?.stopReason && run.stopReason !== 'end_turn')
1048
+ const result = task.result;
1049
+ if (result?.status && result.status !== 'completed')
1050
+ return result.status;
1051
+ if (task.state === 'completed' && result?.stopReason && result.stopReason !== 'end_turn')
1049
1052
  return 'incomplete';
1050
1053
  return task.state;
1051
1054
  }
1052
1055
  /** Lifecycle completion is not proof the requested task finished successfully. */
1053
1056
  function completedAgentResult(completed) {
1054
- const run = completed.result;
1057
+ const turn = completed.result;
1055
1058
  const status = agentTaskOutcome(completed);
1056
1059
  const succeeded = status === 'completed';
1057
- const value = run?.structuredOutput ?? run?.result;
1060
+ const value = turn?.structuredOutput ?? turn?.result;
1058
1061
  let resultText = typeof value === 'string' ? value : value === undefined ? '' : JSON.stringify(value);
1059
- if (!resultText && run?.stopReason && run.stopReason !== 'end_turn') {
1060
- // A hard limit can stop between tool rounds without setting Run.result.
1062
+ if (!resultText && turn?.stopReason && turn.stopReason !== 'end_turn') {
1063
+ // A hard limit can stop between tool rounds without setting Turn.result.
1061
1064
  // Keep the child's last visible statement, never its reasoning or tool data.
1062
- const partial = [...run.messages]
1065
+ const partial = [...turn.messages]
1063
1066
  .reverse()
1064
1067
  .find((message) => message.role === 'assistant' &&
1065
1068
  typeof message.content === 'string' &&
@@ -1067,8 +1070,8 @@ function completedAgentResult(completed) {
1067
1070
  if (typeof partial === 'string')
1068
1071
  resultText = partial;
1069
1072
  }
1070
- const stopNote = run?.stopReason && run.stopReason !== 'end_turn'
1071
- ? `Sub-agent run ended with stop reason "${run.stopReason}". Output may be partial; this does not establish task completion.\n\n`
1073
+ const stopNote = turn?.stopReason && turn.stopReason !== 'end_turn'
1074
+ ? `Sub-agent turn ended with stop reason "${turn.stopReason}". Output may be partial; this does not establish task completion.\n\n`
1072
1075
  : '';
1073
1076
  // ToolResult.data is host metadata, not necessarily model-visible content.
1074
1077
  // Keep the handle and terminal status separate from arbitrary child output
@@ -1079,14 +1082,14 @@ function completedAgentResult(completed) {
1079
1082
  output,
1080
1083
  ...(!succeeded
1081
1084
  ? {
1082
- error: `Sub-agent ${completed.agentId} ${status}: ${run?.lastError ?? ''}\n${output}`,
1085
+ error: `Sub-agent ${completed.agentId} ${status}: ${turn?.lastError ?? ''}\n${output}`,
1083
1086
  }
1084
1087
  : {}),
1085
1088
  data: {
1086
1089
  task_id: completed.taskId,
1087
1090
  state: completed.state,
1088
1091
  status,
1089
- ...(run?.stopReason ? { stop_reason: run.stopReason } : {}),
1092
+ ...(turn?.stopReason ? { stop_reason: turn.stopReason } : {}),
1090
1093
  },
1091
1094
  };
1092
1095
  }
@@ -1125,17 +1128,17 @@ model = opts.model, selection) {
1125
1128
  // erased Agent<BaseAgentConfig,…>. configBuilder supplies the richer config.
1126
1129
  typedAgent: agent,
1127
1130
  configBuilder: async (options) => {
1128
- const limits = resolveRunGuards(opts, options.parentRunId ? opts.resolveLimits?.(asRunId(options.parentRunId)) : undefined);
1131
+ const limits = resolveTurnGuards(opts, options.parentTurnId ? opts.resolveLimits?.(asTurnId(options.parentTurnId)) : undefined);
1129
1132
  // Resolved HERE, per child, rather than captured once for the session:
1130
1133
  // what day it is and which branch is checked out can both have changed
1131
1134
  // since the parent started, and a sub-agent asserting the stale answer
1132
1135
  // is worse than one that was never told.
1133
1136
  const environment = opts.readEnvironment ? await opts.readEnvironment() : null;
1134
- // AgentManager supplies the actual parent run before it stamps the child's
1137
+ // AgentManager supplies the actual parent turn before it stamps the child's
1135
1138
  // own Session ID. All delegated work shares that invoking conversation's
1136
1139
  // upstream billing session, even after the TUI moves to another one.
1137
- const parent = options.parentRunId
1138
- ? await opts.resolveParent(asRunId(options.parentRunId))
1140
+ const parent = options.parentTurnId
1141
+ ? await opts.resolveParent(asTurnId(options.parentTurnId))
1139
1142
  : undefined;
1140
1143
  const provider = await opts.buildProvider(parent?.sessionId, selection);
1141
1144
  const registry = tools();
@@ -1143,8 +1146,9 @@ model = opts.model, selection) {
1143
1146
  return {
1144
1147
  model: options.model ?? model,
1145
1148
  tokenBudget: options.tokenBudget ?? opts.tokenBudget ?? 0,
1146
- timeoutMs: options.timeoutMs ?? opts.timeoutMs ?? CLI_INTERACTIVE_RUN_TIMEOUT_MS,
1149
+ timeoutMs: options.timeoutMs ?? opts.timeoutMs ?? CLI_INTERACTIVE_TURN_TIMEOUT_MS,
1147
1150
  maxIterations: limits.maxIterations,
1151
+ pruneKeepLast: CLI_CHECKPOINT_RETENTION,
1148
1152
  provider,
1149
1153
  ...(webSearch ? { webSearch } : {}),
1150
1154
  ...(selection?.effort ? { effort: selection.effort } : {}),
@@ -1169,7 +1173,9 @@ model = opts.model, selection) {
1169
1173
  ...(opts.sandboxTeardownTimeoutMs !== undefined
1170
1174
  ? { sandboxTeardownTimeoutMs: opts.sandboxTeardownTimeoutMs }
1171
1175
  : {}),
1172
- ...(opts.pathBuilder ? { pathBuilder: opts.pathBuilder } : {}),
1176
+ ...(opts.outsideRootAccess ? { outsideRootAccess: opts.outsideRootAccess } : {}),
1177
+ ...(opts.sandboxEscape ? { sandboxEscape: opts.sandboxEscape } : {}),
1178
+ ...(opts.paths ? { paths: opts.paths } : {}),
1173
1179
  };
1174
1180
  },
1175
1181
  };