mixdog 1.4.1 → 1.4.3

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 (630) hide show
  1. package/package.json +4 -3
  2. package/scripts/build-shipped-history.mjs +125 -33
  3. package/scripts/gate-local.mjs +220 -63
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +139 -32
  6. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  7. package/scripts/lib/run-node-tests.mjs +71 -34
  8. package/scripts/lib/scoped-temp.mjs +1 -0
  9. package/scripts/lib/test-failure-records.mjs +14 -1
  10. package/scripts/lib/test-failure-summary.mjs +9 -4
  11. package/scripts/lib/test-spawn-ledger.mjs +43 -3
  12. package/scripts/post-release-check.mjs +26 -16
  13. package/scripts/pptx-kit-index.mjs +5 -6
  14. package/scripts/provider-pingpong-live.mjs +1 -1
  15. package/scripts/prune-embedding-runtime.mjs +3 -1
  16. package/scripts/release-paths.mjs +7 -1
  17. package/scripts/suite-health.mjs +110 -28
  18. package/scripts/test.mjs +9 -14
  19. package/src/agents/advisor/AGENT.md +4 -4
  20. package/src/agents/advisor/agent.json +1 -1
  21. package/src/agents/explore/AGENT.md +22 -0
  22. package/src/agents/explore/agent.json +6 -0
  23. package/src/cli.mjs +7 -0
  24. package/src/defaults/agents.json +7 -0
  25. package/src/defaults/shipped-history.json +38 -2
  26. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  27. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  28. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  29. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  30. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  31. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  32. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  33. package/src/defaults/skills/setup/SKILL.md +2 -2
  34. package/src/defaults/skills/setup/references/actions.md +28 -9
  35. package/src/defaults/skills/setup/references/surfaces.md +5 -2
  36. package/src/defaults/skills/setup-guide/SKILL.md +11 -3
  37. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  38. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  39. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  40. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  41. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  42. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  43. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  44. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  45. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  46. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  47. package/src/defaults/skills/visualize/SKILL.md +6 -2
  48. package/src/lib/instruction-text.cjs +36 -0
  49. package/src/lib/rules-builder.cjs +40 -50
  50. package/src/orchestration/balanced.md +23 -0
  51. package/src/orchestration/focused.md +22 -0
  52. package/src/orchestration/none.md +5 -0
  53. package/src/orchestration/swarm.md +24 -0
  54. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  55. package/src/rules/agent-mode/MIXY.md +2 -2
  56. package/src/rules/lead/LEAD.md +3 -3
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/60-verification.md +10 -9
  60. package/src/rules/shared/70-delivery.md +4 -3
  61. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  62. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
  65. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
  66. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  69. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  71. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  72. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
  79. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  81. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  82. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  84. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
  85. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  86. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  90. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  91. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  92. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  95. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  96. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  97. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  98. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  99. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  103. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  104. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  105. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  106. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  107. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  113. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  116. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  118. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  119. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  120. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  121. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  122. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
  123. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  124. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
  125. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  126. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  127. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  129. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  130. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  131. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  132. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  133. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  134. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  136. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  137. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  138. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  139. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  140. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
  141. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  142. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  146. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  149. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  150. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  151. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  152. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  153. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  155. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  156. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  159. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  160. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  161. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
  162. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
  163. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
  164. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  165. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  166. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  167. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
  169. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  172. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  174. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  175. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  176. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  177. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  178. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  179. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  181. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  182. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
  183. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
  184. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  185. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  186. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  187. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  188. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
  189. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  190. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  191. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  192. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  193. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  194. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  195. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  196. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  197. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  198. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  199. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  200. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  201. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  202. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  203. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  204. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
  205. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
  206. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  207. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
  208. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  210. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
  211. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  212. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
  213. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  214. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  215. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  216. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
  217. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  218. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  219. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  220. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  221. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  222. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
  223. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  224. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  225. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  226. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
  227. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  228. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  229. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  230. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  231. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  232. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  233. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  234. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  235. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  236. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  237. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  238. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  239. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
  240. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  241. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  242. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  243. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  244. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  245. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  246. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  247. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  248. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  249. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  250. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  251. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  252. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  253. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  254. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
  255. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
  256. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  257. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  258. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  259. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  260. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  261. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  262. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
  263. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  264. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  265. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  266. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  267. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  269. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  270. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  271. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  272. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  273. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  274. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  275. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
  276. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  277. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  278. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  279. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
  280. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  281. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  282. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
  283. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  284. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  285. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  286. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  287. package/src/runtime/attachments/store.d.mts +1 -0
  288. package/src/runtime/attachments/store.mjs +2 -2
  289. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  290. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  291. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  292. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  293. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  294. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  295. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  296. package/src/runtime/channels/lib/whisper-server.mjs +22 -13
  297. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  298. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  299. package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
  300. package/src/runtime/connectors/gmail-app-password.mjs +4 -4
  301. package/src/runtime/connectors/google-mcp.mjs +1 -1
  302. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  303. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  304. package/src/runtime/explore/explorer.mjs +88 -0
  305. package/src/runtime/explore/tool-defs.mjs +35 -0
  306. package/src/runtime/explore/tool.mjs +123 -0
  307. package/src/runtime/local-provider/hardware.mjs +1 -1
  308. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  309. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  310. package/src/runtime/media/media-usage.mjs +1 -1
  311. package/src/runtime/media/store.mjs +1 -1
  312. package/src/runtime/memory/index.mjs +15 -1
  313. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  314. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  315. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  316. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  317. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  318. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  319. package/src/runtime/memory/lib/memory.mjs +17 -0
  320. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  321. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  322. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  323. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  324. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  325. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  326. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  327. package/src/runtime/office/capabilities.mjs +1 -1
  328. package/src/runtime/office/core/office-core.mjs +1 -1
  329. package/src/runtime/office/design/content-model.mjs +3 -3
  330. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  331. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  332. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  333. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  334. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  335. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  336. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  337. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  338. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  339. package/src/runtime/shared/agent-route-config.mjs +17 -2
  340. package/src/runtime/shared/atomic-file.d.mts +8 -0
  341. package/src/runtime/shared/atomic-file.mjs +103 -2
  342. package/src/runtime/shared/background-tasks.mjs +37 -10
  343. package/src/runtime/shared/background-wait.mjs +66 -0
  344. package/src/runtime/shared/child-guardian.mjs +17 -7
  345. package/src/runtime/shared/config.mjs +313 -16
  346. package/src/runtime/shared/connector-accounts.mjs +5 -5
  347. package/src/runtime/shared/connector-catalog.d.mts +14 -8
  348. package/src/runtime/shared/connector-catalog.mjs +70 -52
  349. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  350. package/src/runtime/shared/file-has-data.mjs +26 -2
  351. package/src/runtime/shared/file-lock.mjs +21 -18
  352. package/src/runtime/shared/git-launch.d.mts +9 -0
  353. package/src/runtime/shared/git-launch.mjs +213 -0
  354. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  355. package/src/runtime/shared/git-runner.mjs +7 -2
  356. package/src/runtime/shared/idle-gc.mjs +30 -7
  357. package/src/runtime/shared/llm/cost.mjs +6 -1
  358. package/src/runtime/shared/llm/http-agent.mjs +316 -29
  359. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  360. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  361. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  362. package/src/runtime/shared/llm/system-proxy.mjs +453 -0
  363. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  364. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  365. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  366. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  367. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  368. package/src/runtime/shared/process-runner.mjs +8 -4
  369. package/src/runtime/shared/provider-accounts.mjs +52 -2
  370. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  371. package/src/runtime/shared/routine-trigger.mjs +34 -0
  372. package/src/runtime/shared/run-child.d.mts +2 -1
  373. package/src/runtime/shared/run-child.mjs +70 -18
  374. package/src/runtime/shared/session-scratch.mjs +14 -2
  375. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  376. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  377. package/src/runtime/shared/staged-update.mjs +47 -2
  378. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  379. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  380. package/src/runtime/shared/tool-surface.mjs +110 -36
  381. package/src/runtime/shared/tool-work-units.mjs +35 -6
  382. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  383. package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
  384. package/src/runtime/shared/worker-requests.mjs +17 -3
  385. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  386. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  387. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  388. package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
  389. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  390. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  391. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  392. package/src/runtime/shared/worktrees/git.mjs +97 -7
  393. package/src/runtime/shared/worktrees/include.mjs +6 -4
  394. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  395. package/src/runtime/shared/worktrees/manager.mjs +962 -197
  396. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  397. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  398. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  399. package/src/runtime/tidy/install.mjs +95 -15
  400. package/src/runtime/tidy/languages.mjs +17 -15
  401. package/src/runtime/tidy/process.mjs +9 -5
  402. package/src/runtime/tidy/resolve.mjs +19 -16
  403. package/src/runtime/tidy/runners/biome.mjs +3 -3
  404. package/src/runtime/tidy/tool.mjs +1 -1
  405. package/src/runtime/tidy/worktree.mjs +10 -6
  406. package/src/runtime/visualize-bridge/client.mjs +4 -1
  407. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  408. package/src/runtime/web-search/index.mjs +4 -23
  409. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  410. package/src/runtime/web-search/tool-defs.mjs +17 -26
  411. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  412. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  413. package/src/session-runtime/boot/apis.mjs +27 -4
  414. package/src/session-runtime/boot/begin.mjs +2 -0
  415. package/src/session-runtime/boot/config.mjs +10 -1
  416. package/src/session-runtime/boot/facade.mjs +1 -0
  417. package/src/session-runtime/boot/providers.mjs +70 -3
  418. package/src/session-runtime/boot/session.mjs +2 -0
  419. package/src/session-runtime/boot/tools.mjs +71 -25
  420. package/src/session-runtime/bot-status.mjs +103 -103
  421. package/src/session-runtime/channel-config-api.mjs +1 -0
  422. package/src/session-runtime/config-change-effects.mjs +179 -0
  423. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  424. package/src/session-runtime/config-lifecycle.mjs +160 -24
  425. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  426. package/src/session-runtime/conversation-import/discovery.mjs +245 -47
  427. package/src/session-runtime/conversation-import/service.mjs +12 -5
  428. package/src/session-runtime/goal-facade-api.mjs +49 -3
  429. package/src/session-runtime/handoff-attachments.mjs +1 -1
  430. package/src/session-runtime/held-requests.mjs +3 -1
  431. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  432. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  433. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
  434. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  435. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
  436. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  437. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  438. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  439. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  440. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  441. package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
  442. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  443. package/src/session-runtime/lifecycle-api.mjs +1 -0
  444. package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
  445. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  446. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  447. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  448. package/src/session-runtime/model-route/set-route.mjs +40 -7
  449. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  450. package/src/session-runtime/provider-auth/login.mjs +2 -2
  451. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  452. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  453. package/src/session-runtime/provider-readiness.mjs +53 -4
  454. package/src/session-runtime/resource-api.mjs +1 -1
  455. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  456. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  457. package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
  458. package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
  459. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  460. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  461. package/src/session-runtime/routine-executor.mjs +152 -0
  462. package/src/session-runtime/routine-home-turn.mjs +46 -5
  463. package/src/session-runtime/runtime-facade.mjs +5 -0
  464. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  465. package/src/session-runtime/schedule-session-run.mjs +1 -0
  466. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  467. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  468. package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
  469. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  470. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  471. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  472. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
  473. package/src/session-runtime/services/agent-tool.mjs +51 -1
  474. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  475. package/src/session-runtime/services/channel-admin.mjs +18 -0
  476. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  477. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  478. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  479. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  480. package/src/session-runtime/services/plugin-admin.mjs +14 -6
  481. package/src/session-runtime/services/provider-admin.mjs +281 -10
  482. package/src/session-runtime/services/seeds.mjs +7 -0
  483. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  484. package/src/session-runtime/session-create/materialize.mjs +4 -2
  485. package/src/session-runtime/session-create/session-options.mjs +2 -0
  486. package/src/session-runtime/session-turn-api.mjs +2 -0
  487. package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
  488. package/src/session-runtime/settings-system-api.mjs +1 -1
  489. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  490. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  491. package/src/session-runtime/setup-tool/executor.mjs +14 -3
  492. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  493. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  494. package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
  495. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  496. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  497. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  498. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  499. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  500. package/src/session-runtime/tool-surface.mjs +38 -1
  501. package/src/session-runtime/turn/agent-ops.mjs +33 -2
  502. package/src/session-runtime/turn/session-ops.mjs +2 -0
  503. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  504. package/src/session-runtime/turn/turn-run.mjs +1 -1
  505. package/src/session-runtime/webhook-session-run.mjs +2 -0
  506. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
  507. package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
  508. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  509. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  510. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  511. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  512. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  513. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  514. package/src/session-runtime/workspace/session-view.mjs +149 -0
  515. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  516. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  517. package/src/session-runtime/workspace/transitions.mjs +128 -1070
  518. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  519. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  520. package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
  521. package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
  522. package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
  523. package/src/standalone/daemon-agent-control.mjs +25 -8
  524. package/src/standalone/daemon-desktop-runtime.mjs +8 -2
  525. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  526. package/src/standalone/daemon-session-control.mjs +151 -136
  527. package/src/standalone/daemon.mjs +61 -2
  528. package/src/standalone/desktop-service-registry.mjs +9 -0
  529. package/src/standalone/local-session-runtime.mjs +21 -1
  530. package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
  531. package/src/standalone/session-client.mjs +5 -1
  532. package/src/standalone/session-frame-stream.mjs +83 -11
  533. package/src/standalone/session-protocol.mjs +15 -0
  534. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  535. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  536. package/src/standalone/session-service/agent-tree.mjs +45 -9
  537. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  538. package/src/standalone/session-service/quota-resume.mjs +9 -0
  539. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  540. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  541. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  542. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  543. package/src/standalone/session-service/session-calls.mjs +2 -1
  544. package/src/standalone/session-service/stored-reader.mjs +127 -40
  545. package/src/tui/App.jsx +162 -164
  546. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  547. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  548. package/src/tui/app/clipboard.mjs +22 -11
  549. package/src/tui/app/create-app-pickers.mjs +2 -0
  550. package/src/tui/app/doctor.mjs +2 -2
  551. package/src/tui/app/panel-signature.mjs +1 -1
  552. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  553. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  554. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  555. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  556. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  557. package/src/tui/app/provider-setup-picker.mjs +20 -13
  558. package/src/tui/app/settings-picker.mjs +53 -8
  559. package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
  560. package/src/tui/app/slash-commands.mjs +2 -1
  561. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  562. package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
  563. package/src/tui/app/slash-dispatch.mjs +1 -1
  564. package/src/tui/app/use-btw-panel.mjs +29 -0
  565. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  566. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  567. package/src/tui/app/use-mouse-input.mjs +11 -0
  568. package/src/tui/app/use-onboarding-start.mjs +8 -3
  569. package/src/tui/app/use-panel-transition.mjs +10 -1
  570. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  571. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  572. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  573. package/src/tui/app/use-prompt-queue-history.mjs +5 -4
  574. package/src/tui/app/use-selection-focus.mjs +11 -2
  575. package/src/tui/app/use-selection-geometry.mjs +18 -9
  576. package/src/tui/app/use-selection-paint.mjs +4 -4
  577. package/src/tui/app/use-selection-stitch.mjs +3 -3
  578. package/src/tui/app/use-slash-palette.mjs +62 -0
  579. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  580. package/src/tui/app/use-transcript-activity.mjs +48 -33
  581. package/src/tui/app/use-transcript-follow.mjs +12 -4
  582. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  583. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  584. package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
  585. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  586. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  587. package/src/tui/app/use-transcript-window.mjs +21 -11
  588. package/src/tui/app/use-tui-ready.mjs +18 -0
  589. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  590. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  591. package/src/tui/components/Picker.jsx +27 -3
  592. package/src/tui/components/SignInUrl.jsx +68 -0
  593. package/src/tui/components/TextEntryPanel.jsx +76 -46
  594. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  595. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  596. package/src/tui/components/question-panel-model.mjs +4 -4
  597. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  598. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  599. package/src/tui/components/user-message-skills.mjs +1 -1
  600. package/src/tui/dist/index.mjs +2205 -1371
  601. package/src/tui/markdown/render-ansi.mjs +1 -1
  602. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  603. package/src/tui/session/agent-job-feed.mjs +2 -0
  604. package/src/tui/session/context-state.mjs +3 -0
  605. package/src/tui/session/goal-turn-state.mjs +6 -2
  606. package/src/tui/session/quota-resume.mjs +1 -1
  607. package/src/tui/session/session-api/controls.mjs +4 -0
  608. package/src/tui/session/session-api/extensions.mjs +8 -0
  609. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  610. package/src/tui/session/session-api/intake.mjs +2 -0
  611. package/src/tui/session/session-api/integrations.mjs +2 -2
  612. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  613. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  614. package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
  615. package/src/tui/session/session-api/settings.mjs +2 -2
  616. package/src/tui/session/session-api/worktree.mjs +13 -1
  617. package/src/tui/session/session-flow/drain.mjs +11 -14
  618. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  619. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  620. package/src/tui/session/transcript-spill.mjs +92 -4
  621. package/src/tui/session/transcript-store.mjs +2 -0
  622. package/src/tui/session/turn-quiet.mjs +1 -1
  623. package/src/tui/session/turn.mjs +3 -0
  624. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  625. package/src/tui/spinner-meta.mjs +3 -3
  626. package/src/tui/spinner-verbs.mjs +2 -2
  627. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  628. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
  629. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  630. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -18,9 +18,12 @@ import { resetOutputLimitRecovery, resolveOutputLimit } from './no-tool-turn/out
18
18
  import { resolveRefusal } from './no-tool-turn/refusal.mjs';
19
19
  import { resumeContinuation } from './no-tool-turn/continuation.mjs';
20
20
  import { nudgeEmptyTurn } from './no-tool-turn/empty-nudge.mjs';
21
+ import { noteTodoProgress, staleTodoReminder, todoCompletionReminder } from './no-tool-turn/todo-check.mjs';
21
22
  import { isReactionSuccess, reactionCallIds, takeReactionTarget } from '../../runtime-core/reaction-tool-defs.mjs';
22
23
  import { messageIdOf } from '../message-ids.mjs';
23
24
  import { isReactableMessage } from '../message-reactions.mjs';
25
+ import { joinReports, withEarlierReport } from './turn-report.mjs';
26
+ import { TODO_TOOL } from '../../runtime-core/todo-tool-defs.mjs';
24
27
 
25
28
  // `escalateMaxTokens()` asks the live provider for a higher one-shot max_tokens
26
29
  // (number) or reports none (null/undefined) — the loop stays provider-agnostic.
@@ -32,6 +35,7 @@ export function createNoToolTurnResolver({
32
35
  drainSteering,
33
36
  escalateMaxTokens = () => null,
34
37
  streamedChars = () => 0,
38
+ turnLimited = () => false,
35
39
  }) {
36
40
  const segments = createTurnSegments({ messages, opts });
37
41
  // Per-turn recovery counters shared by the ladders.
@@ -51,6 +55,14 @@ export function createNoToolTurnResolver({
51
55
  // Continuations since the last executed tool batch — bounds the text-only
52
56
  // continuation runaway (see PROVIDER_CONTINUATION_NO_TOOL_LIMIT).
53
57
  continuationsSinceToolBatch: 0,
58
+ // Answers the turn went on past (keepEndedAnswer): those still in the
59
+ // segments (parts before endedPartsEnd), and those a tool batch cleared
60
+ // from them.
61
+ endedPartsEnd: 0,
62
+ carriedAnswers: [],
63
+ // The newest kept answer was followed by nothing but todo bookkeeping:
64
+ // it is the turn's answer, and an empty end after it is no failure.
65
+ reportStands: false,
54
66
  };
55
67
  // The stable id (message-ids.mjs, kept across compaction) of the newest
56
68
  // real user input; runtime reminders and notices are not reactable.
@@ -112,60 +124,108 @@ export function createNoToolTurnResolver({
112
124
  };
113
125
  };
114
126
 
127
+ // An answer the turn goes on past (queued input or a todo reminder arrived
128
+ // after it) is committed like any segment and also kept as part of the
129
+ // turn's report: a tool batch clears the segments, and the caller (an
130
+ // agent's owner) must still receive that answer, not only the short reply
131
+ // that follows it. The answer is every part since the previous one or the
132
+ // last tool batch (an output-limit cut and its resumption included).
133
+ const keepEndedAnswer = (response, hasContent) => {
134
+ if (!segments.commitIntermediate(response) || !hasContent) return false;
135
+ segments.record(response.content, { committed: true });
136
+ state.endedPartsEnd = segments.parts.length;
137
+ return true;
138
+ };
139
+ const endedReport = () =>
140
+ joinReports([...state.carriedAnswers, segments.parts.slice(0, state.endedPartsEnd).join('')]);
141
+ // Answers still in the segments are in the response's own aggregate.
142
+ const finalize = (response) =>
143
+ state.carriedAnswers.length === 0 ? response : withEarlierReport(response, joinReports(state.carriedAnswers));
144
+
145
+ async function resolveTurn(response, iteration) {
146
+ const hasContent = typeof response.content === 'string' && response.content.trim().length > 0;
147
+ const stopReason = response.stopReason ?? response.stop_reason ?? null;
148
+ const isOutputLimitStop = isOutputLimitStopReason(stopReason);
149
+ if (isOutputLimitStop || (hasContent && response.streamCut === true)) {
150
+ return resolveOutputLimit(response, ladder);
151
+ }
152
+ if (stopReason === 'refusal') return resolveRefusal(response, hasContent, ladder);
153
+ // Output-limit stops keep the bounded max-output ladder above and
154
+ // refusals (already returned) keep the bounded refusal retry; both
155
+ // own their own continuation semantics. No lexical/progress-text
156
+ // heuristic is consulted.
157
+ const continuationSignal = isOutputLimitStop ? null : providerContinuationSignal(response);
158
+ if (
159
+ continuationSignal &&
160
+ resumeContinuation(response, { iteration, signal: continuationSignal, hasContent, stopReason }, ladder)
161
+ ) {
162
+ return { action: 'continue', response };
163
+ }
164
+ // Hidden roles are exempt from the empty-turn nudge: their own role
165
+ // rules define a different output contract (pipe-separated chunker
166
+ // output, …) and a text-only terminal turn is the correct shape —
167
+ // nudging them produces a contradictory user message that traps the
168
+ // model in a tool-call-blocked vs contract-required oscillation.
169
+ // A turn that left a reaction on the user's message may end with no
170
+ // text: the reaction is its answer (react tool), never an empty turn.
171
+ // Nor does a turn whose kept answer only todo bookkeeping followed: that
172
+ // answer is its reply.
173
+ if (!hasContent && !HIDDEN_AGENT_NAMES.has(sessionAgent) && !reactionAnswersLatest() && !state.reportStands) {
174
+ return nudgeEmptyTurn(
175
+ response,
176
+ { stopReason, isIncompleteStop: stopReason && INCOMPLETE_STOP_REASONS.has(stopReason) },
177
+ ladder
178
+ );
179
+ }
180
+ // Pending-input rule: queued user input is folded into
181
+ // needs_follow_up before terminal completion. Commit the terminal
182
+ // text first (beforeAppend), then resume.
183
+ if (
184
+ drainSteering('terminal', {
185
+ maxPriority: 'next',
186
+ beforeAppend: () => keepEndedAnswer(response, hasContent),
187
+ })
188
+ ) {
189
+ state.emptyNudgeStreak = 0;
190
+ resetOutputLimitRecovery(state);
191
+ return { action: 'continue', response };
192
+ }
193
+ const reminder = todoCompletionReminder(opts.session, {
194
+ sessionId,
195
+ sessionAgent,
196
+ turnLimited: turnLimited(),
197
+ });
198
+ if (reminder) {
199
+ if (keepEndedAnswer(response, hasContent)) state.reportStands = true;
200
+ messages.push({ role: 'user', content: reminder });
201
+ return { action: 'continue', response };
202
+ }
203
+ return finishTurn(response);
204
+ }
205
+
115
206
  return {
116
207
  // { action: 'continue' | 'break', response }. 'continue' means the
117
208
  // recovery appended to the transcript and the loop must re-send;
118
- // 'break' returns the (possibly aggregated) terminal response.
209
+ // 'break' returns the (possibly aggregated) terminal response, with the
210
+ // ended answers a tool batch cleared from it as its report.
119
211
  async resolve(response, iteration) {
120
- const hasContent = typeof response.content === 'string' && response.content.trim().length > 0;
121
- const stopReason = response.stopReason ?? response.stop_reason ?? null;
122
- const isOutputLimitStop = isOutputLimitStopReason(stopReason);
123
- if (isOutputLimitStop || (hasContent && response.streamCut === true)) {
124
- return resolveOutputLimit(response, ladder);
125
- }
126
- if (stopReason === 'refusal') return resolveRefusal(response, hasContent, ladder);
127
- // Output-limit stops keep the bounded max-output ladder above and
128
- // refusals (already returned) keep the bounded refusal retry; both
129
- // own their own continuation semantics. No lexical/progress-text
130
- // heuristic is consulted.
131
- const continuationSignal = isOutputLimitStop ? null : providerContinuationSignal(response);
132
- if (
133
- continuationSignal &&
134
- resumeContinuation(response, { iteration, signal: continuationSignal, hasContent, stopReason }, ladder)
135
- ) {
136
- return { action: 'continue', response };
137
- }
138
- // Hidden roles are exempt from the empty-turn nudge: their own role
139
- // rules define a different output contract (pipe-separated chunker
140
- // output, …) and a text-only terminal turn is the correct shape —
141
- // nudging them produces a contradictory user message that traps the
142
- // model in a tool-call-blocked vs contract-required oscillation.
143
- // A turn that left a reaction on the user's message may end with no
144
- // text: the reaction is its answer (react tool), never an empty turn.
145
- if (!hasContent && !HIDDEN_AGENT_NAMES.has(sessionAgent) && !reactionAnswersLatest()) {
146
- return nudgeEmptyTurn(
147
- response,
148
- { stopReason, isIncompleteStop: stopReason && INCOMPLETE_STOP_REASONS.has(stopReason) },
149
- ladder
150
- );
151
- }
152
- // Pending-input rule: queued user input is folded into
153
- // needs_follow_up before terminal completion. Commit the terminal
154
- // text first (beforeAppend), then resume.
155
- if (
156
- drainSteering('terminal', {
157
- maxPriority: 'next',
158
- beforeAppend: () => {
159
- if (segments.commitIntermediate(response) && hasContent)
160
- segments.record(response.content, { committed: true });
161
- },
162
- })
163
- ) {
164
- state.emptyNudgeStreak = 0;
165
- resetOutputLimitRecovery(state);
166
- return { action: 'continue', response };
167
- }
168
- return finishTurn(response);
212
+ const outcome = await resolveTurn(response, iteration);
213
+ if (outcome.action !== 'break') return outcome;
214
+ return { ...outcome, response: finalize(outcome.response) };
215
+ },
216
+ // The terminal response of a turn that ended any other way (a capped
217
+ // turn's overrun) gets the same report.
218
+ finalize,
219
+ // Every answer the turn went on past, for a turn that fails after them.
220
+ endedReport,
221
+ // Input the turn took in (steering at any boundary) is new work: its
222
+ // outcome is the turn's, not the kept answer's.
223
+ noteNewInput() {
224
+ state.reportStands = false;
225
+ },
226
+ // An empty end after the kept answer is that answer's turn ending.
227
+ get reportStands() {
228
+ return state.reportStands;
169
229
  },
170
230
  // A turn that produced tool calls is never an empty contract violation,
171
231
  // and it is real progress: a later output-limit cut starts a fresh ladder.
@@ -177,6 +237,12 @@ export function createNoToolTurnResolver({
177
237
  // succeeded marks the turn as having reacted.
178
238
  noteToolBatchCompleted(calls = [], results = []) {
179
239
  state.continuationsSinceToolBatch = 0;
240
+ noteTodoProgress(opts.session);
241
+ const stale = staleTodoReminder(opts.session, calls, results, { sessionAgent });
242
+ if (stale) messages.push({ role: 'user', content: stale, meta: 'hook' });
243
+ if (state.endedPartsEnd > 0) state.carriedAnswers.push(segments.parts.slice(0, state.endedPartsEnd).join(''));
244
+ state.endedPartsEnd = 0;
245
+ if (calls.some((call) => (call?.name ?? call?.function?.name) !== TODO_TOOL.name)) state.reportStands = false;
180
246
  segments.clear();
181
247
  state.reactions.push(...batchReactions(calls, results));
182
248
  },
@@ -14,7 +14,11 @@
14
14
  import { isAgentOwner } from '../../agent-owner.mjs';
15
15
  import { isOffReadonlySurface } from './deferred-call-through.mjs';
16
16
  import { BRIDGE_CALL_TOOL_NAME, bridgeErrorText, isToolBridgeEnabled } from '../../runtime-core/tool-bridge.mjs';
17
- import { sessionAllowlistExcludes, sessionDisallows } from '../../runtime-core/deferred-tool-availability.mjs';
17
+ import {
18
+ sessionAllowlistExcludes,
19
+ sessionDisallows,
20
+ sessionFeatureDenies,
21
+ } from '../../runtime-core/deferred-tool-availability.mjs';
18
22
  import { providerToolExclusionReason } from './provider-tool-exclusions.mjs';
19
23
  import { workflowOverlayDenial } from '../manager/workflow-switch-notice.mjs';
20
24
  import { agentMcpToolPermission, connectorPolicyAgentOf, projectMcpToolDisabled } from '../../mcp/agent-connectors.mjs';
@@ -125,6 +129,9 @@ export function preDispatchDenyForSession(sessionRef, call) {
125
129
  const workflowDenial = workflowOverlayDenial(sessionRef, schemaName);
126
130
  if (workflowDenial) return workflowDenial;
127
131
  if (sessionDisallows(sessionRef, schemaName)) {
132
+ if (sessionFeatureDenies(sessionRef, schemaName)) {
133
+ return `Error: tool "${schemaName}" is disabled in settings by the user. Do not retry unless the user turns it back on.`;
134
+ }
128
135
  return `Error: tool "${name}" is not available in this session.`;
129
136
  }
130
137
  // An agent's connectors: a tool of a server it does not mount, or one set
@@ -43,7 +43,7 @@ export function beginProviderToolExclusions(sessionRef) {
43
43
  if (isSessionRef(sessionRef)) sessions.get(sessionRef)?.current.clear();
44
44
  }
45
45
 
46
- export function excludedToolNoticeText({ name, pointer, reason }) {
46
+ function excludedToolNoticeText({ name, pointer, reason }) {
47
47
  return `Tool "${name}" was excluded from this session's requests: its input schema is invalid at ${pointer || '/'} (${reason}). Fix the tool's schema or disable the tool.`;
48
48
  }
49
49
 
@@ -38,7 +38,7 @@ const HOP_REASONS = {
38
38
  const routeLabel = (route) => displayModelName(route.model, route.provider) || `${route.provider}/${route.model}`;
39
39
 
40
40
  /** The muted transcript line for a hop: `<from> <reason> — switched to <to>.` */
41
- export function routeFallbackNoticeText(from, to, error) {
41
+ function routeFallbackNoticeText(from, to, error) {
42
42
  const reason = HOP_REASONS[providerErrorKind(error).kind] || 'unavailable';
43
43
  return `${routeLabel(from)} ${reason} — switched to ${routeLabel(to)}.`;
44
44
  }
@@ -198,7 +198,8 @@ function injectSteeringEntry(merged, { messages, opts, stage, onSkillPrompt }) {
198
198
  // The drain is synchronous (terminal guards depend on that) and returns whether
199
199
  // anything was injected. `onSkillPrompt` receives each typed entry so the loop
200
200
  // can run its policy-checked skill selection before the next provider snapshot.
201
- export function createSteeringDrain({ messages, opts, sessionId, onSkillPrompt }) {
201
+ // `onInjected` learns of every drain that added input, whatever its stage.
202
+ export function createSteeringDrain({ messages, opts, sessionId, onSkillPrompt, onInjected = () => {} }) {
202
203
  return function drainSteeringIntoMessages(stage = 'mid-turn', options = {}) {
203
204
  if (typeof opts.drainSteering !== 'function') return false;
204
205
  let steerMsgs = [];
@@ -232,6 +233,7 @@ export function createSteeringDrain({ messages, opts, sessionId, onSkillPrompt }
232
233
  totalTextLen += injected.textLength;
233
234
  maxQueueWaitMs = Math.max(maxQueueWaitMs, injected.queueWaitMs);
234
235
  }
236
+ onInjected(stage);
235
237
  if (sessionId) {
236
238
  try {
237
239
  process.stderr.write(
@@ -6,12 +6,11 @@
6
6
  // copy `[mixdog compacted …]` back as literal patch input.
7
7
  //
8
8
  // Mutation bodies (patch / old_string / new_string / content / rewrite) are
9
- // never collapsed after the fact. The sweep that used to do it (deferBodies
10
- // plus a settled-body pass on the next push) rewrote a prefix the provider had
11
- // already cached, and every rewrite re-billed that whole request at the
12
- // uncached rate. Measured over one 89-task run: $1.20 lost to recover $0.16,
13
- // because the collapsed tokens only come back at the cached rate over the
14
- // REMAINING turns, and a task rarely has enough of them left. Bodies now stay
9
+ // never collapsed after the fact. A later sweep would rewrite a prefix the
10
+ // provider has already cached, and every rewrite re-bills that whole request at
11
+ // the uncached rate. Measured over one 89-task run: $1.20 lost to recover
12
+ // $0.16, because the collapsed tokens only come back at the cached rate over
13
+ // the REMAINING turns, and a task rarely has enough of them left. Bodies stay
15
14
  // verbatim in history, so the prefix — and its cache — survives the session.
16
15
  import { createHash } from 'node:crypto';
17
16
 
@@ -16,14 +16,26 @@ import {
16
16
  } from '../../human-gate/gate.mjs';
17
17
  import { applyEditedArgs } from '../../human-gate/requests.mjs';
18
18
  import { effectiveToolCwd } from '../../../tools/builtin/bash-tool/shell-cwd.mjs';
19
+ import { noteTodoUserWait } from '../no-tool-turn/todo-check.mjs';
19
20
 
20
21
  const isArgsObject = (value) => value && typeof value === 'object' && !Array.isArray(value);
21
22
 
22
23
  async function askApproval(
23
24
  call,
24
- { callerSessionId, executeOpts, toolApprovalHook, decision, request = null, gate = null, onApproved = null }
25
+ {
26
+ callerSessionId,
27
+ executeOpts,
28
+ toolApprovalHook,
29
+ decision,
30
+ request = null,
31
+ gate = null,
32
+ onApproved = null,
33
+ account = '',
34
+ }
25
35
  ) {
26
36
  const askReason = String(decision?.reason || 'approval requested by hook').trim();
37
+ // The connector account the call is bound to rides on the card.
38
+ if (account) request = { ...(request || {}), account };
27
39
  // While the user decides, the session is waiting on them, not working.
28
40
  const releaseApprovalWait = beginSessionApprovalWait(callerSessionId);
29
41
  let askOutcome;
@@ -45,7 +57,11 @@ async function askApproval(
45
57
  }
46
58
  const approval = askOutcome.approval;
47
59
  await recordHumanDecision(gate, approval);
48
- if (askOutcome.denial) return { denial: askOutcome.denial };
60
+ if (askOutcome.denial) {
61
+ // The user said no: this turn may end waiting on them (todo-check.mjs).
62
+ noteTodoUserWait(callerSessionId);
63
+ return { denial: askOutcome.denial };
64
+ }
49
65
  if (approval && typeof approval === 'object' && isArgsObject(approval.args)) call.args = approval.args;
50
66
  // The card's edited text replaces the model's before the call runs.
51
67
  if (request?.kind === 'outbound' && approval?.editedArgs) {
@@ -72,9 +88,13 @@ export const CONNECTOR_APPROVAL_REASON = 'This connector tool is set to ask befo
72
88
  * remembered outbound grant answered it) is not asked a second time. With the
73
89
  * "Allow all actions" developer option on, `needs_approval` is not asked
74
90
  * either (a payment or permanent delete was asked by the outbound gate above).
91
+ * `account` is the connector account the call is bound to, for the card.
75
92
  * @returns {Promise<{ denial: string } | null>} the denial, or null to run
76
93
  */
77
- export function applyConnectorApproval(call, { agentId, callerSessionId, executeOpts, toolApprovalHook }) {
94
+ export function applyConnectorApproval(
95
+ call,
96
+ { agentId, callerSessionId, executeOpts, toolApprovalHook, account = '' }
97
+ ) {
78
98
  if (call.outboundApproved) return null;
79
99
  if (!actingBotId(callerSessionId)) return null;
80
100
  if (agentMcpToolPermission(agentId, call.name) !== 'needs_approval') return null;
@@ -89,6 +109,7 @@ export function applyConnectorApproval(call, { agentId, callerSessionId, execute
89
109
  toolApprovalHook,
90
110
  decision: { reason: CONNECTOR_APPROVAL_REASON },
91
111
  request: rememberable ? { kind: 'approval', agentId: botId, remember: ['once', 'agent'] } : null,
112
+ account,
92
113
  onApproved: async (approval) => {
93
114
  if (!rememberable || approval?.remember !== 'agent') return;
94
115
  try {
@@ -130,6 +151,7 @@ export async function applyBeforeToolHook({
130
151
  beforeToolHook,
131
152
  toolApprovalHook,
132
153
  mcpScopeId = null,
154
+ account = '',
133
155
  }) {
134
156
  const call = { name, args, cwd };
135
157
  // ask_user and handoff_user are themselves the user prompt; they never go through the ordinary approval gate.
@@ -183,6 +205,8 @@ export async function applyBeforeToolHook({
183
205
  decision,
184
206
  request,
185
207
  gate,
208
+ // Only while the call is still the one bound to it.
209
+ account: call.name === name ? account : '',
186
210
  });
187
211
  if (denied) return denied;
188
212
  }
@@ -19,7 +19,9 @@ import {
19
19
  } from '../../../tools/builtin.mjs';
20
20
  import { executePatchTool } from '../../../tools/patch.mjs';
21
21
  import { executeInternalTool, isInternalTool } from '../../../internal-tools.mjs';
22
+ import { settingDisabledTool } from '../../../runtime-core/tool-availability.mjs';
22
23
  import { buildSkillsListResponse, viewSkill } from '../tool-helpers.mjs';
24
+ import { executeTodoTool } from '../../../runtime-core/todo-list.mjs';
23
25
  import { isOnDeferredToolSurface } from '../deferred-call-through.mjs';
24
26
  import { _executeCodeGraphToolLazy } from '../../manager/runtime-loaders.mjs';
25
27
  import { requiresReadBody } from '../tool-classify.mjs';
@@ -57,8 +59,8 @@ function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts
57
59
  return formatUnknownBuiltinToolMessage(name, args, 'tool');
58
60
  }
59
61
  // 24h trace data shows ~24% of external MCP calls are cwd-sensitive
60
- // (bash / grep / read / list / glob etc.) but the worker session's
61
- // cwd was previously dropped here. Inject cwd only when the tool's
62
+ // (bash / grep / read / list / glob etc.), so the worker session's
63
+ // cwd must reach them. Inject cwd only when the tool's
62
64
  // inputSchema declares the field — schemas without it would reject
63
65
  // an unknown argument.
64
66
  const needsCwdInjection = cwd && mcpToolHasField(name, 'cwd', mcpScopeId) && (args == null || args.cwd == null);
@@ -67,6 +69,8 @@ function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts
67
69
  signal: executeOpts.signal || null,
68
70
  ownerKey: callerSessionId,
69
71
  scopeId: mcpScopeId,
72
+ // A connector account defaults to (and becomes) this conversation's last used.
73
+ conversation: callerSessionId,
70
74
  });
71
75
  if (!isBuiltinMailRead(name, mcpScopeId)) return call;
72
76
  // The runtime's own record of the links in a mail it read for this session:
@@ -118,8 +122,20 @@ function dispatchInternal(
118
122
  */
119
123
  export function dispatchToolCall({ name, args }, ctx) {
120
124
  const { cwd, callerSessionId, sessionRef, executeOpts, toolOpts, completionToolOpts } = ctx;
125
+ const disabled = settingDisabledTool(name, sessionRef?.mcpScopeId);
126
+ if (disabled) {
127
+ return `Error: tool "${disabled}" is disabled in settings by the user; do not retry unless the user turns it back on`;
128
+ }
121
129
  if (name === 'Skill' || name === 'skill_view') return viewSkill(cwd, args?.name, sessionRef);
122
130
  if (name === 'skills_list') return buildSkillsListResponse(cwd);
131
+ // The step list belongs to the calling session itself (Lead or agent).
132
+ if (name === 'todo') {
133
+ try {
134
+ return executeTodoTool(sessionRef, args || {});
135
+ } catch (error) {
136
+ return `Error: ${error?.message || String(error)}`;
137
+ }
138
+ }
123
139
  if (isMcpTool(name)) return dispatchMcp(name, args, ctx);
124
140
  if (name === 'code_graph') {
125
141
  // cwd chain: args.cwd (caller-explicit) → session cwd → undefined (handler throws)
@@ -5,7 +5,7 @@
5
5
  // tool-exec/dispatch.mjs — executor per tool family
6
6
  // tool-exec/after-hook.mjs — PostToolUse result override
7
7
  // tool-exec/read-only-deadline.mjs — bounded read-only I/O with partial-output grace
8
- import { isMcpTool } from '../../mcp/client.mjs';
8
+ import { isMcpTool, resolveMcpToolAccount } from '../../mcp/client.mjs';
9
9
  import { connectorPolicyAgentOf } from '../../mcp/agent-connectors.mjs';
10
10
  import { prepareDeferredToolCallThrough } from './deferred-call-through.mjs';
11
11
  import { refreshDeferredMcpToolCatalog } from '../../runtime-core/tool-catalog.mjs';
@@ -58,6 +58,24 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
58
58
  callArgs = guarded.args;
59
59
  completionToolOpts.shellGuardNotes = guarded.notes;
60
60
  }
61
+ // A connector call is bound to its account before any hook or card sees it,
62
+ // so an approval approves that account, whatever is used last meanwhile.
63
+ // It is bound by its unique name; `account` is its label, for display.
64
+ let bound = '';
65
+ let account = '';
66
+ if (isMcpTool(name)) {
67
+ try {
68
+ const chosen = resolveMcpToolAccount(name, callArgs, {
69
+ scopeId: sessionRef?.mcpScopeId || null,
70
+ conversation: callerSessionId,
71
+ });
72
+ bound = chosen?.name || '';
73
+ account = chosen?.label || '';
74
+ } catch (error) {
75
+ return `Error: ${error?.message || String(error)}`;
76
+ }
77
+ if (bound) callArgs = { ...callArgs, account: bound };
78
+ }
61
79
  const hooked = await applyBeforeToolHook({
62
80
  name,
63
81
  args: callArgs,
@@ -67,6 +85,7 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
67
85
  beforeToolHook: hookFrom(executeOpts, sessionRef, 'beforeToolHook'),
68
86
  toolApprovalHook,
69
87
  mcpScopeId: sessionRef?.mcpScopeId || null,
88
+ account,
70
89
  });
71
90
  if (hooked.denial) return hooked.denial;
72
91
  const connectorDenied = await applyConnectorApproval(hooked, {
@@ -74,8 +93,11 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
74
93
  callerSessionId,
75
94
  executeOpts,
76
95
  toolApprovalHook,
96
+ account: hooked.name === name ? account : '',
77
97
  });
78
98
  if (connectorDenied) return connectorDenied.denial;
99
+ // A hook's rewrite of the same tool keeps the bound account.
100
+ if (bound && hooked.name === name) hooked.args = { ...hooked.args, account: bound };
79
101
  // A decision can settle after its turn was cancelled. It must never
80
102
  // authorize a new mutation, even if the hook ignores the abort signal.
81
103
  throwIfAborted(executeOpts.signal);
@@ -1,12 +1,14 @@
1
1
  /**
2
2
  * turn-limits.mjs — a turn's caps (sendOpts.turnLimits; a heartbeat turn's,
3
- * manager/ask-turn-loop-options.mjs): `maxToolCalls` tool calls and
4
- * `wrapUpAt` (epoch ms). A call past the cap, or one made after the wrap-up
5
- * time, is answered without running. Once a cap is reached the model is told
6
- * to reply, and every later request of the turn forbids tool use
7
- * (toolChoice 'none'). A response that still calls tools after that ends the
8
- * turn with no reply, its calls answered unrun. A capped turn runs no call
9
- * eagerly (eager-dispatch.mjs), so none past the cap starts while streaming.
3
+ * manager/ask-turn-loop-options.mjs): `maxToolCalls` tool calls,
4
+ * `wrapUpAt` (epoch ms) and `maxToolRounds` tool-calling responses (an
5
+ * explorer's, runtime/explore/explorer.mjs). A call past the cap, or one made
6
+ * after the wrap-up time, is answered without running. Once a cap is reached
7
+ * the model is told to reply, and every later request of the turn forbids
8
+ * tool use (toolChoice 'none'). A response that still calls tools after that
9
+ * ends the turn with no reply, its calls answered unrun. A turn capped by
10
+ * calls or time runs no call eagerly (eager-dispatch.mjs), so none past the
11
+ * cap starts while streaming; a round cap cuts only between rounds.
10
12
  */
11
13
 
12
14
  const NOTICE =
@@ -21,6 +23,8 @@ export function turnLimitsOf(opts) {
21
23
  return {
22
24
  maxToolCalls: Number.isInteger(limits.maxToolCalls) && limits.maxToolCalls >= 0 ? limits.maxToolCalls : Infinity,
23
25
  wrapUpAt: Number.isFinite(limits.wrapUpAt) ? limits.wrapUpAt : Infinity,
26
+ maxToolRounds:
27
+ Number.isInteger(limits.maxToolRounds) && limits.maxToolRounds >= 0 ? limits.maxToolRounds : Infinity,
24
28
  };
25
29
  }
26
30
 
@@ -49,7 +53,8 @@ export function settleTurnLimits(state, overrun, now = Date.now()) {
49
53
  }
50
54
  const limits = turnLimitsOf(state.opts);
51
55
  if (!limits || state.turnLimitNoticed) return;
52
- if (state.toolCallsTotal < limits.maxToolCalls && now < limits.wrapUpAt) return;
56
+ if (state.toolCallsTotal < limits.maxToolCalls && now < limits.wrapUpAt && state.iterations < limits.maxToolRounds)
57
+ return;
53
58
  state.turnLimitNoticed = true;
54
59
  state.messages.push({ role: 'user', content: NOTICE, meta: { source: 'turn-limit' } });
55
60
  }
@@ -0,0 +1,35 @@
1
+ // The report a finished ask hands its caller (an agent's owner).
2
+ //
3
+ // A turn's `content` is what the live view still needs at its end: the text
4
+ // since the last tool batch. An answer the turn kept going past (a todo
5
+ // reminder or queued input arrived after it) and a turn that queued input
6
+ // followed in the same ask are both older than that, so the result carries
7
+ // them in `reportContent`, ahead of the newest text.
8
+
9
+ export function joinReports(parts) {
10
+ return parts
11
+ .map((part) => String(part || '').trim())
12
+ .filter(Boolean)
13
+ .join('\n\n');
14
+ }
15
+
16
+ /** The whole report of a result: `reportContent` when the ask carried earlier
17
+ * answers, else its content. */
18
+ export function turnReportText(result) {
19
+ if (typeof result?.reportContent === 'string') return result.reportContent;
20
+ return typeof result?.content === 'string' ? result.content : '';
21
+ }
22
+
23
+ /** `result` with `earlier` answers ahead of its own report. */
24
+ export function withEarlierReport(result, earlier) {
25
+ if (!earlier) return result;
26
+ return { ...result, reportContent: joinReports([earlier, turnReportText(result)]) };
27
+ }
28
+
29
+ /** A turn that fails after such answers still hands them on: `error` carries
30
+ * them (`carriedReport`, earliest first) to whoever reports the failure. */
31
+ export function carryReportOnError(error, earlier) {
32
+ if (!earlier || !error || typeof error !== 'object') return error;
33
+ error.carriedReport = joinReports([earlier, typeof error.carriedReport === 'string' ? error.carriedReport : '']);
34
+ return error;
35
+ }
@@ -90,7 +90,7 @@ const SUMMED_USAGE_FIELDS = [
90
90
  ];
91
91
 
92
92
  /** What `total` added after the running total `earlier` (both from addUsage); null when nothing. */
93
- export function usageSince(total, earlier) {
93
+ function usageSince(total, earlier) {
94
94
  if (!total) return null;
95
95
  if (!earlier) return { ...total };
96
96
  const delta = {};