mixdog 1.3.5 → 1.4.1

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 (515) hide show
  1. package/NOTICE.md +2 -2
  2. package/README.md +2 -2
  3. package/package.json +2 -11
  4. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  5. package/scripts/daemon-stub.mjs +1 -1
  6. package/scripts/gate-local.mjs +16 -5
  7. package/scripts/latest-guard.mjs +21 -9
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +37 -37
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +123 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/native-release-status.mjs +2 -2
  14. package/scripts/post-release-check.mjs +1 -6
  15. package/scripts/pptx-kit-index.mjs +17 -4
  16. package/scripts/recall-history-cases.json +1 -1
  17. package/scripts/suite-health.mjs +20 -2
  18. package/scripts/test-data-dir.mjs +10 -7
  19. package/scripts/test.mjs +7 -11
  20. package/src/agents/reviewer/AGENT.md +7 -11
  21. package/src/agents/reviewer/agent.json +1 -1
  22. package/src/app.mjs +4 -0
  23. package/src/defaults/shipped-history.json +22 -1
  24. package/src/defaults/skills/browser-use/SKILL.md +62 -12
  25. package/src/defaults/skills/code-tidy/SKILL.md +142 -270
  26. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
  27. package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
  28. package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
  29. package/src/defaults/skills/computer-use/SKILL.md +35 -9
  30. package/src/defaults/skills/setup/SKILL.md +22 -0
  31. package/src/defaults/skills/setup/references/actions.md +39 -5
  32. package/src/defaults/skills/setup/references/surfaces.md +11 -2
  33. package/src/defaults/skills/visualize/SKILL.md +2 -1
  34. package/src/lib/rules-builder.cjs +39 -20
  35. package/src/output-styles/common.md +2 -2
  36. package/src/output-styles/simple.md +1 -1
  37. package/src/rules/agent/AGENT.md +11 -10
  38. package/src/rules/lead/LEAD.md +23 -20
  39. package/src/rules/shared/05-tool-calls.md +5 -6
  40. package/src/rules/shared/10-tool-workflow.md +4 -0
  41. package/src/rules/shared/45-destructive.md +0 -2
  42. package/src/rules/shared/50-execution.md +2 -0
  43. package/src/rules/shared/60-verification.md +7 -5
  44. package/src/rules/shared/70-delivery.md +7 -9
  45. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
  46. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  47. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
  48. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
  49. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  50. package/src/runtime/agent/orchestrator/config.mjs +17 -1
  51. package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
  52. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
  53. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
  54. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
  55. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
  56. package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
  57. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
  58. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
  59. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
  60. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  61. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
  62. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  63. package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  66. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  67. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  70. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
  71. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
  72. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
  73. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  74. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
  75. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
  76. package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
  77. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  78. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
  79. package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
  80. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
  81. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  82. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
  83. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  84. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  85. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  86. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  87. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
  88. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
  89. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  90. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
  91. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  92. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
  93. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  103. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  104. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  105. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  106. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  107. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
  109. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
  110. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
  111. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
  112. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
  113. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +20 -12
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
  117. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
  118. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
  119. package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -0
  120. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
  121. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
  122. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +49 -16
  123. package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
  124. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
  125. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
  126. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -6
  127. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
  129. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
  130. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
  131. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  132. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  133. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
  134. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  136. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  137. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  138. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
  139. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
  140. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
  141. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  142. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
  143. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
  144. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  145. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  146. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
  147. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
  148. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
  149. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
  150. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
  151. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
  152. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
  153. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
  154. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
  155. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
  156. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  158. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
  159. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
  160. package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
  161. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +5 -4
  162. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  163. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
  164. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +49 -21
  165. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
  166. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
  167. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
  168. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
  170. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  171. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  172. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
  173. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
  174. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +24 -14
  175. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
  176. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
  177. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +130 -0
  178. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
  179. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
  180. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  181. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
  182. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
  183. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
  184. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
  185. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  186. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
  187. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
  188. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
  189. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
  190. package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
  191. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
  192. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  193. package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
  194. package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
  195. package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
  196. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
  197. package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
  198. package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
  199. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
  200. package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
  201. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
  202. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  203. package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
  204. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
  209. package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
  210. package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
  211. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
  212. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
  213. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +79 -3
  214. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
  215. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
  217. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  218. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
  219. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  221. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
  222. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
  224. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  225. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
  226. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
  227. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  228. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
  229. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  231. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  232. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  233. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  234. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  235. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  236. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  237. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
  238. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  239. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  240. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  241. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
  243. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
  244. package/src/runtime/browser-bridge/action-schema.mjs +13 -2
  245. package/src/runtime/browser-bridge/client.mjs +73 -8
  246. package/src/runtime/browser-bridge/input-fields.mjs +8 -9
  247. package/src/runtime/browser-bridge/mail-links.mjs +107 -0
  248. package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
  249. package/src/runtime/channels/lib/config.mjs +6 -61
  250. package/src/runtime/channels/lib/crash-log.mjs +1 -1
  251. package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
  252. package/src/runtime/channels/lib/event-queue.mjs +3 -18
  253. package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
  254. package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
  255. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
  256. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
  257. package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
  258. package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
  259. package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
  260. package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
  261. package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
  262. package/src/runtime/channels/lib/scheduler.mjs +33 -147
  263. package/src/runtime/channels/lib/schedules-db.mjs +34 -11
  264. package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
  265. package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
  266. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  267. package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
  268. package/src/runtime/channels/lib/whisper-port.mjs +10 -1
  269. package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
  270. package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
  271. package/src/runtime/channels/lib/worker-main.mjs +10 -34
  272. package/src/runtime/computer-bridge/action-schema.mjs +42 -1
  273. package/src/runtime/computer-bridge/actions.mjs +9 -1
  274. package/src/runtime/computer-bridge/client.mjs +180 -8
  275. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  276. package/src/runtime/computer-bridge/error-recovery.mjs +28 -2
  277. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  278. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  279. package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
  280. package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
  281. package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
  282. package/src/runtime/connectors/gmail-app-password.mjs +172 -39
  283. package/src/runtime/connectors/google-mcp.mjs +10 -12
  284. package/src/runtime/local-provider/server-process.mjs +2 -1
  285. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  286. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  287. package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
  288. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  289. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  290. package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
  291. package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
  292. package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
  293. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  294. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  295. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  296. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  297. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  298. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  299. package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
  300. package/src/runtime/office/quality/design-review.mjs +1 -5
  301. package/src/runtime/office/quality/document-brief.mjs +1 -5
  302. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  303. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  304. package/src/runtime/session-search/session-search-db.mjs +73 -9
  305. package/src/runtime/session-search/session-search-ingest.mjs +110 -20
  306. package/src/runtime/shared/abort-race.mjs +89 -0
  307. package/src/runtime/shared/agent-avatar.d.mts +0 -1
  308. package/src/runtime/shared/agent-kind.mjs +4 -3
  309. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  310. package/src/runtime/shared/bounded-download.mjs +8 -3
  311. package/src/runtime/shared/config.mjs +2 -13
  312. package/src/runtime/shared/connector-accounts.mjs +20 -10
  313. package/src/runtime/shared/connector-catalog.d.mts +29 -0
  314. package/src/runtime/shared/connector-catalog.mjs +150 -0
  315. package/src/runtime/shared/connector-triggers.mjs +22 -19
  316. package/src/runtime/shared/defaults-separation.mjs +2 -17
  317. package/src/runtime/shared/delegated-approval-host.mjs +103 -11
  318. package/src/runtime/shared/err-text.mjs +24 -15
  319. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  320. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  321. package/src/runtime/shared/file-permissions.d.mts +0 -8
  322. package/src/runtime/shared/file-permissions.mjs +0 -11
  323. package/src/runtime/shared/git-direct.test-support.mjs +19 -0
  324. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  325. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  326. package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
  327. package/src/runtime/shared/heartbeat-interval.mjs +19 -0
  328. package/src/runtime/shared/idle-auto-clear-gate.mjs +126 -0
  329. package/src/runtime/shared/llm/cost.mjs +5 -1
  330. package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
  331. package/src/runtime/shared/loopback-listener.mjs +25 -2
  332. package/src/runtime/shared/mixy-presence.mjs +22 -0
  333. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  334. package/src/runtime/shared/model-route-chain.mjs +22 -4
  335. package/src/runtime/shared/open-url.mjs +10 -0
  336. package/src/runtime/shared/orchestration.d.mts +2 -0
  337. package/src/runtime/shared/pg-schema-db.mjs +27 -16
  338. package/src/runtime/shared/profile-config.cjs +1 -1
  339. package/src/runtime/shared/prompt-origin.d.mts +4 -0
  340. package/src/runtime/shared/prompt-origin.mjs +21 -0
  341. package/src/runtime/shared/provider-accounts.mjs +7 -1
  342. package/src/runtime/shared/provider-display-name.mjs +29 -0
  343. package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
  344. package/src/runtime/shared/routine-trigger.d.mts +2 -0
  345. package/src/runtime/shared/routine-trigger.mjs +10 -0
  346. package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
  347. package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
  348. package/src/runtime/shared/session-activity-signal.mjs +48 -1
  349. package/src/runtime/shared/session-scratch.mjs +37 -0
  350. package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
  351. package/src/runtime/shared/session-sidebar-host.mjs +7 -3
  352. package/src/runtime/shared/session-turn-prelude.mjs +18 -0
  353. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  354. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  355. package/src/runtime/shared/tool-result-summary.mjs +2 -15
  356. package/src/runtime/shared/tool-surface.mjs +3 -0
  357. package/src/runtime/shared/tool-work-units.mjs +2 -0
  358. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  359. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  360. package/src/runtime/shared/worktrees/git.mjs +15 -0
  361. package/src/runtime/shared/worktrees/manager.mjs +87 -38
  362. package/src/runtime/shared/worktrees/test-support.mjs +14 -13
  363. package/src/runtime/terminal-bridge/client.mjs +10 -1
  364. package/src/runtime/visualize-bridge/client.mjs +29 -8
  365. package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
  366. package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
  367. package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
  368. package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
  369. package/src/session-runtime/agent-home-delivery.mjs +489 -185
  370. package/src/session-runtime/agent-task-sessions.mjs +467 -229
  371. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  372. package/src/session-runtime/boot/apis.mjs +9 -0
  373. package/src/session-runtime/boot/infrastructure.mjs +4 -0
  374. package/src/session-runtime/boot/providers.mjs +3 -0
  375. package/src/session-runtime/boot/tools.mjs +11 -2
  376. package/src/session-runtime/bot-status.mjs +12 -6
  377. package/src/session-runtime/bot-target.mjs +38 -0
  378. package/src/session-runtime/channel-config-api.mjs +6 -1
  379. package/src/session-runtime/config-lifecycle.mjs +6 -0
  380. package/src/session-runtime/connector-merge-migration.mjs +305 -0
  381. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  382. package/src/session-runtime/conversation-import/discovery.mjs +271 -25
  383. package/src/session-runtime/conversation-import/service.mjs +26 -5
  384. package/src/session-runtime/handoff-attachments.mjs +82 -31
  385. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
  386. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
  387. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  388. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
  389. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  390. package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
  391. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
  392. package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
  393. package/src/session-runtime/lifecycle/teardown.mjs +23 -5
  394. package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
  395. package/src/session-runtime/mcp-oauth-login.mjs +5 -3
  396. package/src/session-runtime/mixy-heartbeat.mjs +153 -33
  397. package/src/session-runtime/model-route/set-route.mjs +11 -2
  398. package/src/session-runtime/notification-bus.mjs +31 -117
  399. package/src/session-runtime/notification-completion-queue.mjs +54 -0
  400. package/src/session-runtime/notification-listeners.mjs +76 -0
  401. package/src/session-runtime/owned-automation-run.mjs +2 -1
  402. package/src/session-runtime/prewarm/channel-start.mjs +3 -7
  403. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  404. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  405. package/src/session-runtime/provider-models.mjs +4 -2
  406. package/src/session-runtime/resource-mcp-api.mjs +143 -224
  407. package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
  408. package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
  409. package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
  410. package/src/session-runtime/resource-mcp-servers.mjs +78 -0
  411. package/src/session-runtime/resource-mcp-store.mjs +49 -0
  412. package/src/session-runtime/resource-recall-api.mjs +6 -1
  413. package/src/session-runtime/routine-owner.mjs +40 -9
  414. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  415. package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
  416. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  417. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  418. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  419. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  420. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
  421. package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
  422. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  423. package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
  424. package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
  425. package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
  426. package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
  427. package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
  428. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
  429. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
  430. package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
  431. package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
  432. package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
  433. package/src/session-runtime/services/channel-admin.mjs +7 -13
  434. package/src/session-runtime/services/channel-session-router.mjs +4 -2
  435. package/src/session-runtime/services/provider-admin.mjs +2 -1
  436. package/src/session-runtime/services/seeds.mjs +0 -28
  437. package/src/session-runtime/session-compaction-sync.mjs +27 -0
  438. package/src/session-runtime/session-create/session-options.mjs +1 -0
  439. package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
  440. package/src/session-runtime/settings-compaction-api.mjs +2 -40
  441. package/src/session-runtime/settings-system-api.mjs +13 -1
  442. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
  443. package/src/session-runtime/setup-tool/executor.mjs +145 -22
  444. package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
  445. package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
  446. package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
  447. package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
  448. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
  449. package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
  450. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  451. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  452. package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
  453. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  454. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
  455. package/src/session-runtime/workspace/transitions.mjs +25 -0
  456. package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
  457. package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
  458. package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
  459. package/src/standalone/channel-transport/client-registry.mjs +24 -163
  460. package/src/standalone/channel-transport.mjs +1 -1
  461. package/src/standalone/daemon-channels-loader.mjs +10 -8
  462. package/src/standalone/daemon-session-control/list-page.mjs +72 -0
  463. package/src/standalone/daemon-session-control/request.mjs +51 -0
  464. package/src/standalone/daemon-session-control/room-host.mjs +57 -0
  465. package/src/standalone/daemon-session-control/route-control.mjs +48 -0
  466. package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
  467. package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
  468. package/src/standalone/daemon-session-control.mjs +142 -190
  469. package/src/standalone/daemon.mjs +26 -3
  470. package/src/standalone/session-client.mjs +7 -3
  471. package/src/standalone/session-protocol.mjs +5 -0
  472. package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
  473. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  474. package/src/standalone/session-service/quota-resume.mjs +3 -0
  475. package/src/standalone/session-service/retention/busy.mjs +65 -1
  476. package/src/standalone/session-service/session-calls/session-action.mjs +30 -2
  477. package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
  478. package/src/standalone/session-tool-output.mjs +15 -7
  479. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  480. package/src/tui/app/app-view/floating-panel.jsx +7 -4
  481. package/src/tui/app/model-options.mjs +3 -28
  482. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  483. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  484. package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
  485. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  486. package/src/tui/app/provider-setup-picker.mjs +9 -5
  487. package/src/tui/components/QuestionPanel.jsx +13 -4
  488. package/src/tui/dist/index.mjs +133 -92
  489. package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
  490. package/src/tui/session/initial-state.mjs +3 -0
  491. package/src/tui/session/notice-surface.mjs +7 -1
  492. package/src/tui/session/queue-helpers.mjs +3 -42
  493. package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
  494. package/src/tui/session/session-api/routes-write.mjs +5 -1
  495. package/src/tui/session/session-api/routes.mjs +1 -0
  496. package/src/tui/session/session-api/settings.mjs +17 -1
  497. package/src/tui/session/session-flow/auto-clear.mjs +4 -33
  498. package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
  499. package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
  500. package/src/tui/session/session-flow/drain-retry.mjs +35 -0
  501. package/src/tui/session/session-flow/drain.mjs +118 -149
  502. package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
  503. package/src/tui/session/session-flow/queue/take-entries.mjs +16 -2
  504. package/src/tui/session/tool-approval-delegation.mjs +64 -0
  505. package/src/tui/session/tool-approval-request.mjs +39 -0
  506. package/src/tui/session/tool-approval-settle.mjs +62 -0
  507. package/src/tui/session/tool-approval.mjs +69 -115
  508. package/src/tui/session/tui-steering-persist.mjs +8 -1
  509. package/src/tui/session/turn-stream.mjs +19 -2
  510. package/src/tui/session/turn.mjs +1 -0
  511. package/src/ui/statusline-agents.mjs +1 -3
  512. package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
  513. package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
  514. package/scripts/code-graph-description-contract.mjs +0 -188
  515. package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
@@ -0,0 +1,64 @@
1
+ /**
2
+ * src/tui/session/tool-approval-delegation.mjs — where else a tool-approval
3
+ * request shows: the top-level chat above a sub-agent (`delegationSurface`) or
4
+ * the chats handing this session work (`handsOff`, `offerToHandoffs`;
5
+ * runtime/shared/delegated-approval-host.mjs).
6
+ */
7
+ import { agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
8
+ import { roomMemberOfSession } from '../../runtime/agent/orchestrator/session/agent-room.mjs';
9
+ import { delegateToHandoffs } from '../../runtime/shared/delegated-approval-host.mjs';
10
+
11
+ /** Requests a sub-agent (or a session a chat handed work to) shows in the
12
+ * conversation the user watches too. A secret and a takeover go there as
13
+ * well: the value goes to this PC by its request id and the sign-in window
14
+ * is bound to the asking session, wherever the card is answered. A
15
+ * sub-agent's question stays in its own session (its answer belongs to that
16
+ * conversation); a handed-off session's question shows in the chats handing
17
+ * it work too, beside their hand-off line (tool-approval.mjs
18
+ * `handoffQuestions`), never in their queue. */
19
+ const DELEGATED_KINDS = new Set(['', 'approval', 'outbound', 'permission', 'secret', 'takeover']);
20
+ const HANDOFF_KINDS = new Set([...DELEGATED_KINDS, 'question']);
21
+
22
+ export function createApprovalDelegation({ surfaceOf, ownSessionId }) {
23
+ /** `{ sessionId, chain }` of the top-level chat a sub-agent's request also
24
+ * shows in, or null (no delegation, another kind, or this is the top). */
25
+ function delegationSurface(request) {
26
+ if (typeof surfaceOf !== 'function' || !DELEGATED_KINDS.has(request.kind)) return null;
27
+ const own = String(request.sessionId || ownSessionId());
28
+ let surface = null;
29
+ try {
30
+ surface = surfaceOf(own);
31
+ } catch {
32
+ return null;
33
+ }
34
+ const sessionId = String(surface?.sessionId || '');
35
+ if (!sessionId || sessionId === own || sessionId === ownSessionId()) return null;
36
+ return { sessionId, chain: Array.isArray(surface.chain) ? surface.chain.map(String) : [] };
37
+ }
38
+ /** Whether a request this (top-level) session itself makes also shows in
39
+ * the chats handing it work (delegated-approval-host.mjs), while it waits. */
40
+ function handsOff(request) {
41
+ if (typeof surfaceOf !== 'function' || !HANDOFF_KINDS.has(request.kind)) return false;
42
+ const own = ownSessionId();
43
+ return Boolean(own) && String(request.sessionId || own) === own;
44
+ }
45
+ function offerToHandoffs(id, request, answer) {
46
+ const own = ownSessionId();
47
+ const agentId = agentIdOfHomeSession(own) || roomMemberOfSession(own)?.agentId || '';
48
+ // Each chat handing this session work names it its own way.
49
+ delegateToHandoffs({
50
+ id,
51
+ sessionId: own,
52
+ request,
53
+ answer,
54
+ copyFor: (chat, { title }) => ({
55
+ ...request,
56
+ sessionId: request.sessionId || own,
57
+ chain: [],
58
+ surfaceSessionId: chat,
59
+ handoff: { title, ...(agentId ? { agentId } : {}) },
60
+ }),
61
+ });
62
+ }
63
+ return { delegationSurface, handsOff, offerToHandoffs };
64
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * src/tui/session/tool-approval-request.mjs — the request record a tool-approval
3
+ * queue (tool-approval.mjs) holds and presents: name, args, reason, and its
4
+ * own wait limit.
5
+ */
6
+ import { humanRequestFields } from '../../runtime/agent/orchestrator/session/human-gate/requests.mjs';
7
+
8
+ /** The queue's default wait limit from its `timeoutMs` option: a positive
9
+ * number, else null (no limit). */
10
+ export function defaultApprovalTimeoutMs(timeoutMs) {
11
+ return Number.isFinite(Number(timeoutMs)) && Number(timeoutMs) > 0 ? Number(timeoutMs) : null;
12
+ }
13
+
14
+ export function normalizeToolApprovalRequest(input, id, defaultTimeoutMs) {
15
+ const now = Date.now();
16
+ // An explicit `timeoutMs: null` means no wait limit (no timer, no expiry);
17
+ // any other missing/invalid value falls back to the session default,
18
+ // which is itself no limit unless the runtime configures one.
19
+ let requestTimeoutMs = defaultTimeoutMs;
20
+ if (input?.timeoutMs === null) requestTimeoutMs = null;
21
+ else if (Number.isFinite(Number(input?.timeoutMs)) && Number(input.timeoutMs) > 0) {
22
+ requestTimeoutMs = Number(input.timeoutMs);
23
+ }
24
+ return {
25
+ id,
26
+ name: String(input?.name || input?.tool_name || 'tool'),
27
+ kind: typeof input?.kind === 'string' ? input.kind : '',
28
+ args: input?.args ?? input?.tool_input ?? null,
29
+ cwd: input?.cwd || null,
30
+ sessionId: input?.sessionId || input?.session_id || null,
31
+ toolCallId: input?.toolCallId || input?.tool_use_id || null,
32
+ reason: String(input?.reason || input?.message || 'approval requested by hook').trim(),
33
+ requestedAt: now,
34
+ timeoutMs: requestTimeoutMs,
35
+ expiresAt: requestTimeoutMs === null ? null : now + requestTimeoutMs,
36
+ // outbound / secret / takeover / permission fields (human-gate/requests.mjs).
37
+ ...humanRequestFields(input),
38
+ };
39
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * src/tui/session/tool-approval-settle.mjs — how one tool-approval entry ends:
3
+ * the answer its waiter gets, the forwarded answer of a copy, and the outcome
4
+ * record published on the state (`toolApprovalResult`).
5
+ */
6
+ import { normalizeHumanResponse } from '../../runtime/agent/orchestrator/session/human-gate/requests.mjs';
7
+ import { withdrawDelegatedApproval } from '../../runtime/shared/delegated-approval-host.mjs';
8
+
9
+ // Settle one entry: drop its timeout, then hand the waiter its answer. The
10
+ // resolve stays guarded — a waiter whose caller already went away must never
11
+ // take the rest of the queue down with it.
12
+ export function settleToolApproval(entry, approved, reason, answers, reply, extra, device = '') {
13
+ if (entry?.timer) clearTimeout(entry.timer);
14
+ const result = { approved, reason };
15
+ if (answers !== undefined) result.answers = answers;
16
+ if (reply !== undefined) result.reply = reply;
17
+ // A human-kind request answers with its canonical response (never a value).
18
+ if (entry?.request?.remember) {
19
+ Object.assign(result, normalizeHumanResponse(entry.request, approved, extra));
20
+ if (device) result.device = device;
21
+ }
22
+ if (extra?.timedOut === true) result.timedOut = true;
23
+ // Settled here: its copy in the top-level chat goes away.
24
+ if (entry?.delegated) {
25
+ withdrawDelegatedApproval(entry.id, { approved, device, ...(extra?.timedOut === true ? { expired: true } : {}) });
26
+ }
27
+ try {
28
+ entry.resolve(result);
29
+ } catch {
30
+ // The requester's resolver must not break settling the queue.
31
+ }
32
+ }
33
+
34
+ /** Hand a copy's answer to the queue that owns the request; false when the
35
+ * owner had already settled it. */
36
+ export function forwardToOwner(entry, approved, reason, device, answers, reply, extra) {
37
+ try {
38
+ return entry.mirror.answer(approved, reason, device, answers, reply, extra) === true;
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+
44
+ /** How the shown entry ended, from its own finish: only an answer from a known
45
+ * device is attributed; a real timeout says `expired`; any other unattributed
46
+ * end names nobody (null). */
47
+ export function finishedOutcome(id, approved, device, extra) {
48
+ if (device) return { id, approved: approved === true, device: String(device), at: Date.now() };
49
+ if (extra?.timedOut === true) return { id, approved: false, device: '', expired: true, at: Date.now() };
50
+ return null;
51
+ }
52
+
53
+ /** How a copy ended, from the owner's settle: answered from a known device
54
+ * (who), a real timeout (`expired`), or taken away with no answer
55
+ * (`withdrawn`: the owner's turn ended, the hand-off copy was removed). */
56
+ export function copyOutcome(id, result) {
57
+ const device = String(result?.device || '');
58
+ const at = Date.now();
59
+ if (device) return { id, approved: result.approved === true, device, at };
60
+ if (result?.expired === true) return { id, approved: false, device: '', expired: true, at };
61
+ return { id, approved: false, device: '', withdrawn: true, at };
62
+ }
@@ -13,20 +13,14 @@
13
13
  * that session's own turn ending, and its answer is forwarded to the owning
14
14
  * queue, so either place settles the one request once.
15
15
  */
16
- import {
17
- humanRequestFields,
18
- normalizeHumanResponse,
19
- } from '../../runtime/agent/orchestrator/session/human-gate/requests.mjs';
20
16
  import {
21
17
  delegateApproval,
22
18
  delegatedApprovalsFor,
23
19
  registerApprovalQueue,
24
- withdrawDelegatedApproval,
25
20
  } from '../../runtime/shared/delegated-approval-host.mjs';
26
-
27
- /** Approvals a sub-agent shows in the top-level chat too; a question, a secret
28
- * or a takeover stays in its own session (its answer or window is there). */
29
- const DELEGATED_KINDS = new Set(['', 'approval', 'outbound', 'permission']);
21
+ import { defaultApprovalTimeoutMs, normalizeToolApprovalRequest } from './tool-approval-request.mjs';
22
+ import { copyOutcome, finishedOutcome, forwardToOwner, settleToolApproval } from './tool-approval-settle.mjs';
23
+ import { createApprovalDelegation } from './tool-approval-delegation.mjs';
30
24
 
31
25
  /** The wait limit an approval has when its request names none, from
32
26
  * MIXDOG_TOOL_APPROVAL_TIMEOUT_MS (milliseconds, one second at least): null —
@@ -39,10 +33,18 @@ export function resolveToolApprovalTimeoutMs(env = process.env) {
39
33
  }
40
34
 
41
35
  export function createToolApproval({ getState, set, nextId, getDisposed, timeoutMs = null, surfaceOf = null }) {
42
- const defaultTimeoutMs = Number.isFinite(Number(timeoutMs)) && Number(timeoutMs) > 0 ? Number(timeoutMs) : null;
36
+ const defaultTimeoutMs = defaultApprovalTimeoutMs(timeoutMs);
43
37
  const toolApprovalQueue = [];
44
38
  let activeToolApproval = null;
39
+ // Copies of the ask_user questions of sessions this chat handed work to
40
+ // (`{ id, request, mirror }`): published as `handoffQuestions`, each shown
41
+ // at its hand-off line for the user alone (no transcript row), outside the
42
+ // queue so they never hold this chat's own requests back and several show
43
+ // at once. Answered here, the answer goes to the asking session's queue.
44
+ const handoffQuestions = [];
45
+ const publishHandoffQuestions = () => set({ handoffQuestions: handoffQuestions.map((entry) => entry.request) });
45
46
  const ownSessionId = () => String(getState()?.sessionId || '');
47
+ const { delegationSurface, handsOff, offerToHandoffs } = createApprovalDelegation({ surfaceOf, ownSessionId });
46
48
  const unregister =
47
49
  typeof surfaceOf === 'function'
48
50
  ? registerApprovalQueue({
@@ -53,33 +55,6 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
53
55
  })
54
56
  : () => {};
55
57
 
56
- function normalizeToolApprovalRequest(input = {}, id = nextId()) {
57
- const now = Date.now();
58
- // An explicit `timeoutMs: null` means no wait limit (no timer, no expiry);
59
- // any other missing/invalid value falls back to the session default,
60
- // which is itself no limit unless the runtime configures one.
61
- const requestTimeoutMs =
62
- input?.timeoutMs === null
63
- ? null
64
- : Number.isFinite(Number(input?.timeoutMs)) && Number(input.timeoutMs) > 0
65
- ? Number(input.timeoutMs)
66
- : defaultTimeoutMs;
67
- return {
68
- id,
69
- name: String(input?.name || input?.tool_name || 'tool'),
70
- kind: typeof input?.kind === 'string' ? input.kind : '',
71
- args: input?.args ?? input?.tool_input ?? null,
72
- cwd: input?.cwd || null,
73
- sessionId: input?.sessionId || input?.session_id || null,
74
- toolCallId: input?.toolCallId || input?.tool_use_id || null,
75
- reason: String(input?.reason || input?.message || 'approval requested by hook').trim(),
76
- requestedAt: now,
77
- timeoutMs: requestTimeoutMs,
78
- expiresAt: requestTimeoutMs === null ? null : now + requestTimeoutMs,
79
- // outbound / secret / takeover / permission fields (human-gate/requests.mjs).
80
- ...humanRequestFields(input),
81
- };
82
- }
83
58
  // A request that has a limit expires from ITS OWN requestedAt, queued or
84
59
  // active. Arming the timer only on presentation let a queued request sit past
85
60
  // expiresAt (retaining its promise and surfacing an obsolete approval later).
@@ -93,54 +68,35 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
93
68
  }, remainingMs);
94
69
  entry.timer.unref?.();
95
70
  }
96
- // Settle one entry: drop its timeout, then hand the waiter its answer. The
97
- // resolve stays guarded — a waiter whose caller already went away must never
98
- // take the rest of the queue down with it.
99
- function settleToolApproval(entry, approved, reason, answers, reply, extra, device = '') {
100
- if (entry?.timer) clearTimeout(entry.timer);
101
- const result = { approved, reason };
102
- if (answers !== undefined) result.answers = answers;
103
- if (reply !== undefined) result.reply = reply;
104
- // A human-kind request answers with its canonical response (never a value).
105
- if (entry?.request?.remember) {
106
- Object.assign(result, normalizeHumanResponse(entry.request, approved, extra));
107
- if (device) result.device = device;
108
- }
109
- if (extra?.timedOut === true) result.timedOut = true;
110
- // Settled here: its copy in the top-level chat goes away.
111
- if (entry?.delegated) withdrawDelegatedApproval(entry.id, { approved, device });
112
- try {
113
- entry.resolve(result);
114
- } catch {}
115
- }
116
- /** Hand a copy's answer to the queue that owns the request; false when the
117
- * owner had already settled it. */
118
- function forwardToOwner(entry, approved, reason, device, answers, reply, extra) {
119
- try {
120
- return entry.mirror.answer(approved, reason, device, answers, reply, extra) === true;
121
- } catch {
122
- return false;
123
- }
124
- }
125
71
  function offerDelegatedApproval(delegated) {
126
72
  if (getDisposed() || delegated.sessionId !== ownSessionId()) return;
73
+ if (delegated.request?.kind === 'question') {
74
+ if (handoffQuestions.some((entry) => entry.id === delegated.id)) return;
75
+ handoffQuestions.push({ id: delegated.id, request: delegated.request, mirror: delegated });
76
+ publishHandoffQuestions();
77
+ return;
78
+ }
127
79
  if (activeToolApproval?.id === delegated.id || toolApprovalQueue.some((entry) => entry.id === delegated.id)) return;
128
80
  toolApprovalQueue.push({ id: delegated.id, request: delegated.request, mirror: delegated, timer: null });
129
81
  presentNextToolApproval();
130
82
  }
131
83
  function withdrawDelegatedCopy(id, result) {
84
+ const question = handoffQuestions.findIndex((entry) => entry.id === id);
85
+ if (question >= 0) {
86
+ handoffQuestions.splice(question, 1);
87
+ if (!getDisposed()) publishHandoffQuestions();
88
+ return;
89
+ }
132
90
  if (activeToolApproval?.mirror && activeToolApproval.id === id) {
133
91
  activeToolApproval = null;
134
- const device = String(result?.device || '');
135
- set({
136
- toolApproval: null,
137
- toolApprovalResult: device ? { id, approved: result.approved === true, device, at: Date.now() } : null,
138
- });
92
+ set({ toolApproval: null, toolApprovalResult: copyOutcome(id, result) });
139
93
  presentNextToolApproval();
140
94
  return;
141
95
  }
142
96
  const index = toolApprovalQueue.findIndex((entry) => entry.mirror && entry.id === id);
143
- if (index >= 0) toolApprovalQueue.splice(index, 1);
97
+ if (index < 0) return;
98
+ toolApprovalQueue.splice(index, 1);
99
+ presentNextToolApproval();
144
100
  }
145
101
  /** Show the delegated approvals waiting for this session (it loaded, or its
146
102
  * session id became the top-level one after the request was made). */
@@ -149,16 +105,23 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
149
105
  if (!sessionId || typeof surfaceOf !== 'function') return;
150
106
  for (const delegated of delegatedApprovalsFor(sessionId)) offerDelegatedApproval(delegated);
151
107
  }
108
+ /** Show the next request when none is shown, and publish how many wait
109
+ * behind the shown one (`toolApprovalsWaiting`: the dock's "1/N"). */
152
110
  function presentNextToolApproval() {
153
- if (activeToolApproval || getDisposed()) return;
154
- const entry = toolApprovalQueue.shift();
155
- if (!entry) {
156
- if (getState().toolApproval) set({ toolApproval: null });
157
- return;
111
+ if (getDisposed()) return;
112
+ const patch = {};
113
+ if (!activeToolApproval) {
114
+ const entry = toolApprovalQueue.shift();
115
+ if (entry) {
116
+ activeToolApproval = entry;
117
+ armToolApprovalTimeout(entry);
118
+ patch.toolApproval = entry.request;
119
+ } else if (getState().toolApproval) patch.toolApproval = null;
120
+ }
121
+ if ((getState().toolApprovalsWaiting ?? 0) !== toolApprovalQueue.length) {
122
+ patch.toolApprovalsWaiting = toolApprovalQueue.length;
158
123
  }
159
- activeToolApproval = entry;
160
- armToolApprovalTimeout(entry);
161
- set({ toolApproval: entry.request });
124
+ if (Object.keys(patch).length > 0) set(patch);
162
125
  }
163
126
  function finishToolApproval(
164
127
  id,
@@ -173,12 +136,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
173
136
  if (activeToolApproval && activeToolApproval.id === targetId) {
174
137
  const entry = activeToolApproval;
175
138
  activeToolApproval = null;
176
- // Only an answer from a known device is attributed; a timeout or an
177
- // interrupt names nobody.
178
- const toolApprovalResult = device
179
- ? { id: targetId, approved: approved === true, device: String(device), at: Date.now() }
180
- : null;
181
- set({ toolApproval: null, toolApprovalResult });
139
+ set({ toolApproval: null, toolApprovalResult: finishedOutcome(targetId, approved, device, extra) });
182
140
  let accepted = true;
183
141
  if (entry.mirror) {
184
142
  accepted = forwardToOwner(entry, approved, reason, device, answers, reply, extra);
@@ -191,10 +149,17 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
191
149
  const index = toolApprovalQueue.findIndex((entry) => entry.id === targetId);
192
150
  if (index >= 0) {
193
151
  const [entry] = toolApprovalQueue.splice(index, 1);
152
+ presentNextToolApproval();
194
153
  if (entry.mirror) return forwardToOwner(entry, approved, reason, device, answers, reply, extra);
195
154
  settleToolApproval(entry, approved === true, String(reason || ''), answers, reply, extra, String(device || ''));
196
155
  return true;
197
156
  }
157
+ const question = handoffQuestions.findIndex((entry) => entry.id === targetId);
158
+ if (question >= 0) {
159
+ const [entry] = handoffQuestions.splice(question, 1);
160
+ publishHandoffQuestions();
161
+ return forwardToOwner(entry, approved, reason, device, answers, reply, extra);
162
+ }
198
163
  return false;
199
164
  }
200
165
  /** Deny this session's own requests. A copy of a sub-agent's request stays
@@ -202,11 +167,19 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
202
167
  * unanswered: the next runtime of this session adopts it again. */
203
168
  function denyAllToolApprovals(reason = 'approval cancelled') {
204
169
  const closing = getDisposed();
205
- if (closing) unregister();
170
+ if (closing) {
171
+ unregister();
172
+ // Dropped unanswered with this runtime: the next one adopts them again.
173
+ handoffQuestions.length = 0;
174
+ }
206
175
  if (activeToolApproval && !(activeToolApproval.mirror && !closing)) {
207
176
  const entry = activeToolApproval;
208
177
  activeToolApproval = null;
209
- if (!entry.mirror) settleToolApproval(entry, false, reason);
178
+ if (!entry.mirror) {
179
+ settleToolApproval(entry, false, reason);
180
+ // Stop/turn abort ended it: not a timeout, nobody answered.
181
+ set({ toolApprovalResult: { id: entry.id, approved: false, device: '', interrupted: true, at: Date.now() } });
182
+ }
210
183
  }
211
184
  const kept = [];
212
185
  while (toolApprovalQueue.length > 0) {
@@ -215,7 +188,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
215
188
  else if (!closing) kept.push(entry);
216
189
  }
217
190
  toolApprovalQueue.push(...kept);
218
- if (activeToolApproval) return;
191
+ if (activeToolApproval) return presentNextToolApproval();
219
192
  if (getState().toolApproval) set({ toolApproval: null });
220
193
  presentNextToolApproval();
221
194
  }
@@ -223,43 +196,24 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
223
196
  if (getDisposed()) return Promise.resolve({ approved: false, reason: 'runtime disposed' });
224
197
  return new Promise((resolve) => {
225
198
  const id = nextId();
226
- const full = normalizeToolApprovalRequest(input, id);
199
+ const full = normalizeToolApprovalRequest(input, id, defaultTimeoutMs);
227
200
  const surface = delegationSurface(full);
228
201
  if (surface) {
229
202
  // Who asks, from the top-level chat down ("사무관 › Worker"), and where the copy is.
230
203
  full.chain = surface.chain;
231
204
  full.surfaceSessionId = surface.sessionId;
232
205
  }
233
- const entry = { id, request: full, resolve, timer: null, delegated: Boolean(surface) };
206
+ const handoffs = !surface && handsOff(full);
207
+ const entry = { id, request: full, resolve, timer: null, delegated: Boolean(surface || handoffs) };
234
208
  toolApprovalQueue.push(entry);
235
209
  armToolApprovalTimeout(entry);
236
210
  presentNextToolApproval();
237
- if (surface) {
238
- delegateApproval({
239
- id,
240
- sessionId: surface.sessionId,
241
- request: full,
242
- answer: (approved, reason, device, answers, reply, extra) =>
243
- finishToolApproval(id, approved, reason, device, answers, reply, extra),
244
- });
245
- }
211
+ const answer = (approved, reason, device, answers, reply, extra) =>
212
+ finishToolApproval(id, approved, reason, device, answers, reply, extra);
213
+ if (surface) delegateApproval({ id, sessionId: surface.sessionId, request: full, answer });
214
+ if (handoffs) offerToHandoffs(id, full, answer);
246
215
  });
247
216
  }
248
- /** `{ sessionId, chain }` of the top-level chat a sub-agent's request also
249
- * shows in, or null (no delegation, another kind, or this is the top). */
250
- function delegationSurface(request) {
251
- if (typeof surfaceOf !== 'function' || !DELEGATED_KINDS.has(request.kind)) return null;
252
- const own = String(request.sessionId || ownSessionId());
253
- let surface = null;
254
- try {
255
- surface = surfaceOf(own);
256
- } catch {
257
- return null;
258
- }
259
- const sessionId = String(surface?.sessionId || '');
260
- if (!sessionId || sessionId === own || sessionId === ownSessionId()) return null;
261
- return { sessionId, chain: Array.isArray(surface.chain) ? surface.chain.map(String) : [] };
262
- }
263
217
 
264
218
  return {
265
219
  presentNextToolApproval,
@@ -70,10 +70,17 @@ function persistedQueuePayload(entry) {
70
70
  const value = entry[field];
71
71
  if (value && typeof value === 'object' && !Array.isArray(value)) out[field] = value;
72
72
  }
73
- for (const field of ['mode', 'priority', 'context']) {
73
+ for (const field of ['mode', 'priority', 'context', 'origin']) {
74
74
  if (typeof entry[field] === 'string' && entry[field]) out[field] = entry[field];
75
75
  }
76
76
  if (entry.skipSlashCommands === true) out.skipSlashCommands = true;
77
+ // Retry of a failed turn: the drain rewinds the failed prompt by these.
78
+ if (typeof entry.skillSelection === 'string') out.skillSelection = entry.skillSelection;
79
+ if (entry.suppressDisplay === true) out.suppressDisplay = true;
80
+ if (entry.retryFailedTurn === true) out.retryFailedTurn = true;
81
+ for (const field of ['retryTurnId', 'retryAttemptId']) {
82
+ if (typeof entry[field] === 'string' && entry[field]) out[field] = entry[field];
83
+ }
77
84
  return out;
78
85
  }
79
86
 
@@ -588,6 +588,12 @@ function stopReconnectCountdown(stream) {
588
588
  stream.reconnectTimer = null;
589
589
  }
590
590
 
591
+ // The spinner's wait fields for a reconnect stage (see applyStageChange).
592
+ function reconnectWait(detail, now = Date.now()) {
593
+ const retryAt = Number(detail?.retryAt) || 0;
594
+ return { retryAt, retryInMs: retryAt > 0 ? Math.max(0, retryAt - now) : 0 };
595
+ }
596
+
591
597
  // Re-renders the reconnect verb once a second until the wait ends, the stage
592
598
  // moves on, or the turn is gone. The desktop reads the same spinner state.
593
599
  function startReconnectCountdown(stream, detail) {
@@ -599,7 +605,7 @@ function startReconnectCountdown(stream, detail) {
599
605
  stopReconnectCountdown(stream);
600
606
  return;
601
607
  }
602
- stream.set({ spinner: { ...spinner, verb: reconnectVerb(detail) } });
608
+ stream.set({ spinner: { ...spinner, verb: reconnectVerb(detail), ...reconnectWait(detail) } });
603
609
  }, 1_000);
604
610
  stream.reconnectTimer.unref?.();
605
611
  }
@@ -635,7 +641,18 @@ export async function applyStageChange(stream, stage, detail = null) {
635
641
  }
636
642
  if (value === 'reconnecting') {
637
643
  stream.compactingActive = false;
638
- set({ spinner: { ...getState().spinner, mode: 'reconnecting', verb: reconnectVerb(detail) } });
644
+ // The wait rides on the spinner so a surface that repaints on its own
645
+ // clock (the desktop status line) counts it down itself: `retryInMs` is
646
+ // the remaining wait at publish (relative, so a remote client's clock skew
647
+ // cannot distort it) and `retryAt` only identifies this retry.
648
+ set({
649
+ spinner: {
650
+ ...getState().spinner,
651
+ mode: 'reconnecting',
652
+ verb: reconnectVerb(detail),
653
+ ...reconnectWait(detail),
654
+ },
655
+ });
639
656
  startReconnectCountdown(stream, detail);
640
657
  await yieldToRenderer();
641
658
  return;
@@ -777,6 +777,7 @@ export function createRunTurn(bag) {
777
777
  submissionIds: turn.submittedIds,
778
778
  submittedAt: options.submittedAt,
779
779
  promptSource: options.promptSource,
780
+ ...(options.promptOrigin ? { promptOrigin: options.promptOrigin } : {}),
780
781
  retryFailedTurn: options.retryFailedTurn === true,
781
782
  retryTurnId: options.retryTurnId,
782
783
  retryAttemptId: options.retryAttemptId,
@@ -13,9 +13,7 @@ import { positiveInt } from '../runtime/shared/numbers.mjs';
13
13
 
14
14
  // One table owns both halves of a maintenance agent: which agents are hidden
15
15
  // from the worker list by default, and the short label they render as.
16
- const MAINTENANCE_AGENT_LABELS = new Map([
17
- ['cycle1-agent', 'cycle1'],
18
- ]);
16
+ const MAINTENANCE_AGENT_LABELS = new Map([['cycle1-agent', 'cycle1']]);
19
17
  const DEFAULT_HIDDEN_STATUSLINE_AGENTS = Object.freeze([...MAINTENANCE_AGENT_LABELS.keys()]);
20
18
  const TERMINAL_AGENT_STATUS = /idle|done|complete|success|closed|error|fail|cancel|killed|timeout/i;
21
19
  const ACTIVE_AGENT_STATUS = /^(?:connecting|requesting|streaming|tool[-_\s]?running|running|queued|pending|starting)$/i;