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
@@ -19,7 +19,7 @@ import { providerToolExclusionReason } from './provider-tool-exclusions.mjs';
19
19
  import { workflowOverlayDenial } from '../manager/workflow-switch-notice.mjs';
20
20
  import { agentMcpToolPermission, connectorPolicyAgentOf, projectMcpToolDisabled } from '../../mcp/agent-connectors.mjs';
21
21
 
22
- const WORKER_DENIED_TOOLS = new Set(['agent', 'ask_user', 'session']);
22
+ const WORKER_DENIED_TOOLS = new Set(['agent', 'ask_user', 'handoff_user', 'session']);
23
23
  const BRIDGE_DISCOVERY_TOOL_NAMES = new Set(['load_tool']);
24
24
 
25
25
  const IMAGE_PATH_RE = /\.(?:png|jpe?g|gif|webp)(?:$|[?#])/i;
@@ -31,6 +31,13 @@ function exclusionsFor(sessionRef) {
31
31
 
32
32
  const isSessionRef = (value) => value !== null && typeof value === 'object';
33
33
 
34
+ // A schema 400 drop holds for the schema rule that refused it: a route on
35
+ // another wire family (a fallback hop, a model switch) sends the tool again.
36
+ function droppedOnRoute(sessionRef, name) {
37
+ const entry = isSessionRef(sessionRef) ? sessions.get(sessionRef)?.dropped.get(String(name || '')) : null;
38
+ return entry && entry.family === routeSchemaFamily(sessionRef) ? entry : null;
39
+ }
40
+
34
41
  /** A new provider request: exclusions describe the latest request only. */
35
42
  export function beginProviderToolExclusions(sessionRef) {
36
43
  if (isSessionRef(sessionRef)) sessions.get(sessionRef)?.current.clear();
@@ -64,15 +71,16 @@ export function providerToolExclusionReason(sessionRef, name) {
64
71
  if (!isSessionRef(sessionRef)) return null;
65
72
  const state = sessions.get(sessionRef);
66
73
  const key = String(name || '');
67
- const exclusion = state?.current.get(key) || state?.dropped.get(key);
74
+ const exclusion = state?.current.get(key) || droppedOnRoute(sessionRef, key);
68
75
  return exclusion ? unavailableText(exclusion) : null;
69
76
  }
70
77
 
71
78
  /** The provider rejected `exclusion.name`'s schema with an HTTP 400: leave the
72
- * tool out of every later request of the session and tell the user once. */
79
+ * tool out of the session's later requests on this wire family and tell the
80
+ * user once. */
73
81
  export function dropSessionTool(sessionRef, exclusion, onStageChange) {
74
82
  if (!isSessionRef(sessionRef)) return;
75
- exclusionsFor(sessionRef).dropped.set(exclusion.name, exclusion);
83
+ exclusionsFor(sessionRef).dropped.set(exclusion.name, { ...exclusion, family: routeSchemaFamily(sessionRef) });
76
84
  recordProviderToolExclusion(sessionRef, exclusion, onStageChange);
77
85
  }
78
86
 
@@ -82,7 +90,7 @@ export function withoutDroppedTools(sessionRef, { sendTools, requestToolScope })
82
90
  const dropped = isSessionRef(sessionRef) ? sessions.get(sessionRef)?.dropped : null;
83
91
  if (!dropped?.size) return { sendTools, requestToolScope };
84
92
  const prefix = providerNativeToolPrefixCount(sendTools);
85
- const kept = sendTools.filter((tool, index) => index < prefix || !dropped.has(tool?.name));
93
+ const kept = sendTools.filter((tool, index) => index < prefix || !droppedOnRoute(sessionRef, tool?.name));
86
94
  if (kept.length === sendTools.length) return { sendTools, requestToolScope };
87
95
  const next = finalizeProviderRequestTools(kept, prefix);
88
96
  return { sendTools: next, requestToolScope: { ...requestToolScope, requestTools: next } };
@@ -128,7 +136,7 @@ function schemaExclusion(session, family, tool) {
128
136
  * tools are never excluded by the schema rule. */
129
137
  export function routeToolExclusionReason(session, tool) {
130
138
  if (!tool) return null;
131
- const dropped = isSessionRef(session) ? sessions.get(session)?.dropped.get(String(tool.name || '')) : null;
139
+ const dropped = droppedOnRoute(session, tool.name);
132
140
  if (dropped) return unavailableText(dropped);
133
141
  const exclusion = schemaExclusion(session, routeSchemaFamily(session), tool);
134
142
  return exclusion ? unavailableText(exclusion) : null;
@@ -6,11 +6,19 @@ import { getProvider, initProviders } from '../../providers/registry.mjs';
6
6
  import { loadConfig } from '../../config.mjs';
7
7
  import { ensureProviderEnabled } from '../../runtime-core/config-helpers.mjs';
8
8
  import { updateSessionRoute } from '../manager/session-lifecycle.mjs';
9
+ import {
10
+ liveRouteFallbacks,
11
+ nextRouteFallbackIndex,
12
+ routeFallbackHopped,
13
+ routeLeaf,
14
+ } from '../manager/route-fallback-chain.mjs';
9
15
  import { pinSessionWireRoute } from '../../providers/wire-route.mjs';
10
16
  import { buildRequestSendOptions } from '../manager/ask-turn-loop-options.mjs';
11
17
  import { prepareTurnEffortConfiguration } from '../../providers/effort-configuration.mjs';
12
18
  import { resolveSessionContextMeta } from '../manager/context-meta.mjs';
13
19
  import { stripProviderReplayMessages } from '../manager/provider-replay.mjs';
20
+ import { isAgentOwner } from '../../agent-owner.mjs';
21
+ import { rebuildToolSurfaceForProviderWithMigration } from './tool-exposure-migration.mjs';
14
22
 
15
23
  // The short reason a notice gives for leaving a model, by provider kind.
16
24
  const HOP_REASONS = {
@@ -78,9 +86,13 @@ async function nextContextGrows(state, next) {
78
86
 
79
87
  export async function advanceAgentRoute(state, error) {
80
88
  const session = state.sessionRef;
81
- if (!session?.agent || !session.routeFallbacks?.length) return false;
82
- const index = session.routeFallbackIndex || 0;
83
- const next = session.routeFallbacks[index];
89
+ if (!session?.agent) return false;
90
+ // Read from the session's settings at this hop: a chain edited while it runs
91
+ // applies now, and one cleared to [] leaves the provider's own error.
92
+ const { chain } = liveRouteFallbacks(session, loadConfig({ secrets: false }));
93
+ if (!chain.length) return false;
94
+ const index = nextRouteFallbackIndex(session, chain);
95
+ const next = chain[index];
84
96
  // Only THIS request must have produced nothing (its stream outcome says so):
85
97
  // earlier requests of the turn may have run tools. Their calls and results
86
98
  // are already in the live turn, which the next model continues from, so no
@@ -97,6 +109,8 @@ export async function advanceAgentRoute(state, error) {
97
109
  const provider = getProvider(next.provider);
98
110
  if (!provider) throw new Error(`Provider "${next.provider}" not available`);
99
111
  const failed = routeFailure(session, error);
112
+ // The route a reset returns to (setup reset_route_fallback), kept from the first hop.
113
+ const primary = routeFallbackHopped(session) ? session.routeFallbackPrimary : routeLeaf(session);
100
114
  // The left model's share of the turn ends here: the running total at the
101
115
  // switch bounds it, so each model's tokens are booked at its own rates.
102
116
  state.routeUsageHops = [
@@ -131,10 +145,17 @@ export async function advanceAgentRoute(state, error) {
131
145
  { crossProvider: true, session }
132
146
  );
133
147
  if (!updated) throw new Error('agent session closed during model fallback');
148
+ updated.routeFallbacks = chain;
149
+ if (primary) updated.routeFallbackPrimary = primary;
134
150
  updated.routeFallbackIndex = index + 1;
135
151
  updated.routeFallbackFailures = [...(session.routeFallbackFailures || []), failed];
136
152
  await pinSessionWireRoute(updated, provider);
137
153
  state.throwIfAborted();
154
+ // The route change replaced the session's tools with its whole resolved list.
155
+ // A delegated agent's surface was already re-applied by updateSessionRoute
156
+ // (applyAgentToolExposure); a Lead-class session gets its deferred surface
157
+ // restored for the new provider, as a manual model switch does.
158
+ if (!isAgentOwner(updated)) rebuildToolSurfaceForProviderWithMigration(updated, next.provider, state.messages);
138
159
  // The live turn (prompt, assistant tool calls, tool results) carries on;
139
160
  // only the previous provider's native replay state is dropped from it.
140
161
  state.messages.splice(0, state.messages.length, ...stripProviderReplayMessages(state.messages));
@@ -150,6 +171,13 @@ export async function advanceAgentRoute(state, error) {
150
171
  state.cacheBreakTraceKeys.clear();
151
172
  state.transportRetriesUsed = 0;
152
173
  state.transportRetryMax = 0;
174
+ // The one-shot recoveries the left model spent belong to its requests; the
175
+ // next model's first request gets its own (its window, images and schemas).
176
+ state.contextOverflowRetryUsed = false;
177
+ state.imageStripUsed = false;
178
+ state.imageStrip = null;
179
+ state.thinkingReplayRepairUsed = false;
180
+ state.toolSchemaDropUsed = false;
153
181
  for (const key of Object.keys(oldOptions)) delete state.opts[key];
154
182
  Object.assign(
155
183
  state.opts,
@@ -4,7 +4,12 @@
4
4
  * consume a retry verdict, and settle a completed send into the loop state.
5
5
  */
6
6
  import { traceCacheBreak } from '../../cache-break-trace.mjs';
7
- import { anthropicPrefixChanges } from '../../providers/lib/anthropic-prefix-trace.mjs';
7
+ import {
8
+ anthropicPrefixChanges,
9
+ latestAnthropicPrefix,
10
+ persistableAnthropicPrefix,
11
+ seedAnthropicPrefix,
12
+ } from '../../providers/lib/anthropic-prefix-trace.mjs';
8
13
  import { resolveLiveToolCwd } from './tool-exec.mjs';
9
14
  import { notifySkillsApplied, prepareExplicitSkills, recordAppliedSkills } from '../explicit-skills.mjs';
10
15
  import { addUsage, usageDeltaEvent } from './usage.mjs';
@@ -126,13 +131,16 @@ export async function beginIteration(state) {
126
131
  getIterations: () => state.iterations,
127
132
  getNextIteration: () => nextIteration,
128
133
  repeatFailLimit: REPEAT_FAIL_LIMIT,
134
+ isTurnLimitNoticed: () => state.turnLimitNoticed === true,
129
135
  });
130
136
  const resolveToolCallId = createToolCallIdResolver(messages);
131
137
  opts.onToolCall = (call) => {
132
138
  resolveToolCallId(call);
133
139
  try {
134
140
  opts.onAssistantToolCallObserved?.(call, { eagerStarted: false });
135
- } catch {}
141
+ } catch {
142
+ // the tool-call observer is advisory
143
+ }
136
144
  return eager.onToolCall(call);
137
145
  };
138
146
  return {
@@ -173,7 +181,12 @@ export async function sendProviderRequest(state, round) {
173
181
  });
174
182
  try {
175
183
  opts.onProviderSendStarted?.();
176
- } catch {}
184
+ } catch {
185
+ // the send-started observer is advisory
186
+ }
187
+ // Diagnostic only: a restarted process compares its first request with the
188
+ // last prefix fingerprint the session record kept (anthropic-prefix-trace.mjs).
189
+ seedAnthropicPrefix(sessionId, sessionRef?.providerPrefixBaseline);
177
190
  // The request a /btw side question forks: kept while it is in flight, with
178
191
  // its reply once it proceeds, and dropped again if it fails.
179
192
  const sideQuestion = captureSideQuestionRequest({
@@ -369,6 +382,10 @@ function traceActualCacheMiss(state, sent, response, { previousGuardState, previ
369
382
  );
370
383
  }
371
384
  sessionRef.lastProviderCachedPrefixTokens = cachePrefixTokens;
385
+ // The fingerprint of this request survives a restart on the record, so the
386
+ // next process's first miss can still name what moved.
387
+ const fingerprint = persistableAnthropicPrefix(latestAnthropicPrefix(sessionId));
388
+ if (fingerprint) sessionRef.providerPrefixBaseline = fingerprint;
372
389
  }
373
390
 
374
391
  /** Fold a completed send into the state: prefix guard, image-strip
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { normalizeToolEnvelope, makeToolEnvelope } from '../../tool-envelope.mjs';
6
6
  import { resolveToolResultAfterHook } from '../tool-helpers.mjs';
7
+ import { effectiveToolCwd } from '../../../tools/builtin/bash-tool/shell-cwd.mjs';
7
8
 
8
9
  export async function applyAfterToolHook(result, afterToolHook, { name, args, cwd, callerSessionId, toolCallId }) {
9
10
  if (typeof afterToolHook !== 'function') return result;
@@ -15,7 +16,7 @@ export async function applyAfterToolHook(result, afterToolHook, { name, args, cw
15
16
  const hookResult = await afterToolHook({
16
17
  name,
17
18
  args,
18
- cwd,
19
+ cwd: effectiveToolCwd(name, args, cwd),
19
20
  sessionId: callerSessionId,
20
21
  toolCallId,
21
22
  result: visible,
@@ -15,6 +15,7 @@ import {
15
15
  recordHumanDecision,
16
16
  } from '../../human-gate/gate.mjs';
17
17
  import { applyEditedArgs } from '../../human-gate/requests.mjs';
18
+ import { effectiveToolCwd } from '../../../tools/builtin/bash-tool/shell-cwd.mjs';
18
19
 
19
20
  const isArgsObject = (value) => value && typeof value === 'object' && !Array.isArray(value);
20
21
 
@@ -31,7 +32,7 @@ async function askApproval(
31
32
  resolvePreToolAskApproval({
32
33
  toolName: call.name,
33
34
  args: call.args,
34
- cwd: call.cwd,
35
+ cwd: effectiveToolCwd(call.name, call.args, call.cwd),
35
36
  sessionId: callerSessionId,
36
37
  toolCallId: executeOpts.toolCallId || null,
37
38
  askReason,
@@ -131,8 +132,8 @@ export async function applyBeforeToolHook({
131
132
  mcpScopeId = null,
132
133
  }) {
133
134
  const call = { name, args, cwd };
134
- // ask_user is itself the user prompt; it never goes through the ordinary approval gate.
135
- if (name === 'ask_user') return call;
135
+ // ask_user and handoff_user are themselves the user prompt; they never go through the ordinary approval gate.
136
+ if (name === 'ask_user' || name === 'handoff_user') return call;
136
137
  try {
137
138
  const hookDecision = beforeToolHook
138
139
  ? await runAbortable(executeOpts.signal, () =>
@@ -140,7 +141,7 @@ export async function applyBeforeToolHook({
140
141
  {
141
142
  name,
142
143
  args,
143
- cwd,
144
+ cwd: effectiveToolCwd(name, args, cwd),
144
145
  sessionId: callerSessionId,
145
146
  toolCallId: executeOpts.toolCallId || null,
146
147
  },
@@ -3,7 +3,14 @@
3
3
  * MCP, code graph, internal tools, shell, apply_patch, built-ins and foreign
4
4
  * CLI adapters.
5
5
  */
6
- import { executeMcpTool, isMcpTool, isRegisteredMcpTool, mcpToolHasField } from '../../../mcp/client.mjs';
6
+ import {
7
+ executeMcpTool,
8
+ isBuiltinMailRead,
9
+ isMcpTool,
10
+ isRegisteredMcpTool,
11
+ mcpToolHasField,
12
+ } from '../../../mcp/client.mjs';
13
+ import { recordMailLinks } from '../../../../../browser-bridge/mail-links.mjs';
7
14
  import {
8
15
  executeBuiltinTool,
9
16
  formatUnknownBuiltinToolMessage,
@@ -56,11 +63,18 @@ function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts
56
63
  // an unknown argument.
57
64
  const needsCwdInjection = cwd && mcpToolHasField(name, 'cwd', mcpScopeId) && (args == null || args.cwd == null);
58
65
  const finalArgs = needsCwdInjection ? { ...(args || {}), cwd } : args;
59
- return executeMcpTool(name, finalArgs, {
66
+ const call = executeMcpTool(name, finalArgs, {
60
67
  signal: executeOpts.signal || null,
61
68
  ownerKey: callerSessionId,
62
69
  scopeId: mcpScopeId,
63
70
  });
71
+ if (!isBuiltinMailRead(name, mcpScopeId)) return call;
72
+ // The runtime's own record of the links in a mail it read for this session:
73
+ // the only way Browser Use may open a link carrying a token.
74
+ return call.then((result) => {
75
+ recordMailLinks(callerSessionId, result);
76
+ return result;
77
+ });
64
78
  }
65
79
 
66
80
  function dispatchInternal(
@@ -19,6 +19,7 @@ import { applyBeforeToolHook, applyConnectorApproval, applyShellElevationGate }
19
19
  import { dispatchToolCall } from './tool-exec/dispatch.mjs';
20
20
  import { applyAfterToolHook } from './tool-exec/after-hook.mjs';
21
21
  import { runReadOnlyIoWithDeadline } from './tool-exec/read-only-deadline.mjs';
22
+ import { guardShellCall, requestedShellType } from '../../tools/builtin/bash-tool/misuse-guard.mjs';
22
23
 
23
24
  export { runReadOnlyIoWithDeadline as _runReadOnlyIoWithDeadlineForTest };
24
25
  export {
@@ -43,9 +44,23 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
43
44
  const prepared = prepareToolCall(name, args, cwd, callerSessionId, sessionRef, executeOpts);
44
45
  const { toolOpts, notifyFn, completionToolOpts } = prepared;
45
46
  const toolApprovalHook = hookFrom(executeOpts, sessionRef, 'toolApprovalHook');
47
+ // Shell misuse is judged before any hook or approval sees the call, so they
48
+ // read the command that will run and the directory it runs in.
49
+ let callArgs = prepared.args;
50
+ if (name === 'shell') {
51
+ const guarded = guardShellCall(callArgs, {
52
+ shellType: requestedShellType(callArgs),
53
+ agent: sessionRef?.agent || null,
54
+ sessionId: callerSessionId,
55
+ telemetry: executeOpts.resultTelemetry,
56
+ });
57
+ if (guarded.failure) return guarded.failure;
58
+ callArgs = guarded.args;
59
+ completionToolOpts.shellGuardNotes = guarded.notes;
60
+ }
46
61
  const hooked = await applyBeforeToolHook({
47
62
  name,
48
- args: prepared.args,
63
+ args: callArgs,
49
64
  cwd: prepared.cwd,
50
65
  callerSessionId,
51
66
  executeOpts,
@@ -18,6 +18,7 @@ import { isAgentOwner } from '../../agent-owner.mjs';
18
18
  import { honoredSchemaAllowlist } from '../manager/session-tool-surface.mjs';
19
19
  import { syncSystemPrefix } from '../manager/prompt-utils.mjs';
20
20
  import { invalidateProviderContextBaseline } from './compact-policy.mjs';
21
+ import { rebindToChangedPrefix } from '../thinking-binding.mjs';
21
22
 
22
23
  /** Drop everything measured against the previous tool surface. */
23
24
  function invalidateForToolSurfaceMigration(session) {
@@ -34,15 +35,55 @@ function invalidateForToolSurfaceMigration(session) {
34
35
  */
35
36
  export function markToolSurfaceMigrated(session, intent = TOOL_SURFACE_MIGRATION_INTENT) {
36
37
  invalidateForToolSurfaceMigration(session);
38
+ // The stored thinking was bound to the previous prefix and can never be
39
+ // replayed again (../thinking-binding.mjs); an open tool round a stopped
40
+ // turn left behind is ended first. Outside a turn only: a running turn sends
41
+ // from its own working transcript, whose latest tool round must keep its
42
+ // thinking.
43
+ if (Array.isArray(session.messages) && !Array.isArray(session.liveTurnMessages)) {
44
+ session.messages = rebindToChangedPrefix(session.messages);
45
+ }
37
46
  session.pendingCacheBreakIntent = intent;
38
47
  }
39
48
 
40
- /** Provider switch: rebuild the surface for `provider`, migrating bridge ↔ native. */
41
- export function rebuildToolSurfaceForProviderWithMigration(session, provider) {
49
+ /**
50
+ * Run `apply` with `messages` (the transcript a running turn works on) as the
51
+ * session's messages, so a fixed-guidance rewrite lands there; the canonical
52
+ * transcript takes the rewritten system prefix. Without `messages`, `apply`
53
+ * runs on the session's own. `apply` runs synchronously.
54
+ */
55
+ function applyOnWorkingMessages(session, messages, apply) {
56
+ const stored = session.messages;
57
+ const working = Array.isArray(messages) ? messages : stored;
58
+ if (Array.isArray(working)) session.messages = working;
59
+ try {
60
+ apply();
61
+ } finally {
62
+ if (Array.isArray(working) && session.messages !== working) {
63
+ // The rewrite may drop an emptied system message: keep the array
64
+ // identity the request loop holds.
65
+ working.splice(0, working.length, ...session.messages);
66
+ }
67
+ session.messages = stored;
68
+ }
69
+ // The rewritten prompt messages are fresh objects; the canonical transcript
70
+ // the save path persists takes them too, so the next save writes the new
71
+ // prompt together with the new exposure.
72
+ if (Array.isArray(stored) && Array.isArray(working) && stored !== working) syncSystemPrefix(stored, working);
73
+ }
74
+
75
+ /**
76
+ * Provider switch: rebuild the surface for `provider`, migrating bridge ↔
77
+ * native. `messages`: the running turn's transcript, when a switch happens
78
+ * mid-turn (a route fallback hop).
79
+ */
80
+ export function rebuildToolSurfaceForProviderWithMigration(session, provider, messages) {
42
81
  if (!session) return false;
43
82
  const migrating = toolExposureMigrationNeeded(session, provider);
44
- rebuildDeferredToolSurfaceForProvider(session, provider);
45
- if (migrating) markToolSurfaceMigrated(session);
83
+ applyOnWorkingMessages(session, messages, () => {
84
+ rebuildDeferredToolSurfaceForProvider(session, provider);
85
+ if (migrating) markToolSurfaceMigrated(session);
86
+ });
46
87
  return migrating;
47
88
  }
48
89
 
@@ -66,26 +107,12 @@ function hasUnansweredToolCalls(messages) {
66
107
  */
67
108
  export function migrateToolExposureAtBoundary(session, messages) {
68
109
  if (!session || !toolExposureMigrationNeeded(session) || hasUnansweredToolCalls(messages)) return false;
69
- const stored = session.messages;
70
- const working = Array.isArray(messages) ? messages : stored;
71
- if (Array.isArray(working)) session.messages = working;
72
- try {
110
+ applyOnWorkingMessages(session, messages, () =>
73
111
  applyDeferredToolSurface(session, session.deferredSurfaceMode || 'lead', [], {
74
112
  provider: session.provider,
75
113
  model: session.model,
76
- });
77
- } finally {
78
- if (Array.isArray(working) && session.messages !== working) {
79
- // The rewrite may drop an emptied system message: keep the request
80
- // transcript array identity the loop holds.
81
- working.splice(0, working.length, ...session.messages);
82
- }
83
- session.messages = stored;
84
- }
85
- // The rewritten prompt messages are fresh objects; the canonical transcript
86
- // the save path persists takes them too, so the next save writes the new
87
- // prompt together with the new exposure.
88
- if (Array.isArray(stored) && Array.isArray(working) && stored !== working) syncSystemPrefix(stored, working);
114
+ })
115
+ );
89
116
  invalidateForToolSurfaceMigration(session);
90
117
  return true;
91
118
  }
@@ -105,6 +132,7 @@ const AGENT_BRIDGE_FIELDS = [
105
132
  'deferredToolDeltaRevision',
106
133
  'nativeDeferredDiscovery',
107
134
  'mcpServerInstructions',
135
+ 'mcpInstructionsAnnounced',
108
136
  ];
109
137
 
110
138
  /**
@@ -12,10 +12,7 @@ import {
12
12
  loadSkillResource,
13
13
  buildSkillToolEnvelope,
14
14
  filterSkillsExcludingDisabled,
15
- isSkillDisabled,
16
- skillMissingFeature,
17
- skillOutsideScope,
18
- skillOutsideScopeError,
15
+ skillLoadRefusal,
19
16
  } from '../../context/collect.mjs';
20
17
 
21
18
  // Eager-dispatch: tools with readOnlyHint:true in their declaration are safe
@@ -95,12 +92,8 @@ export function buildSkillsListResponse(cwd) {
95
92
  export function viewSkill(cwd, name, session = null) {
96
93
  const skillName = String(name || '').trim();
97
94
  if (!skillName) return 'Error: skill name is required';
98
- const missingFeature = skillMissingFeature(skillName);
99
- if (missingFeature) {
100
- return `Error: skill "${skillName}" needs the ${missingFeature} built-in feature, which is not installed or is switched off in Extensions → Plugin → Built-in`;
101
- }
102
- if (isSkillDisabled(skillName)) return `Error: skill "${skillName}" is disabled`;
103
- if (skillOutsideScope(skillName, cwd)) return skillOutsideScopeError(skillName);
95
+ const refusal = skillLoadRefusal(skillName, cwd);
96
+ if (refusal) return refusal;
104
97
  const res = loadSkillResource(skillName, cwd);
105
98
  if (!res) return `Error: skill "${skillName}" not found`;
106
99
  // Return the general tool envelope: the model-visible tool_result is the
@@ -9,6 +9,7 @@ import { processToolBatch } from '../tool-batch.mjs';
9
9
  import { CROSS_TURN_CAP, REPEAT_FAIL_LIMIT } from './loop-state.mjs';
10
10
  import { markStepEffort } from './step-auto-effort.mjs';
11
11
  import { resolveExecutionToolCalls } from './tool-call-resolution.mjs';
12
+ import { rememberSensitiveValues } from '../sensitive-values.mjs';
12
13
  import { callsAllowed, settleTurnLimits, turnLimitsOf } from './turn-limits.mjs';
13
14
 
14
15
  function isSleepLikeToolCall(call) {
@@ -41,13 +42,19 @@ export async function runToolPhase(state, round, sent, onToolCall) {
41
42
  // derive the multi-tool adoption ratio without scanning message bodies.
42
43
  // Audit records what runs: a bridged call_tool is recorded as its target.
43
44
  // The wire calls stay the transcript identity (assistant turn below).
44
- const toolBatchId = recordToolBatch(sessionId, resolveExecutionToolCalls(calls, sessionRef), state.iterations);
45
+ const executionCalls = resolveExecutionToolCalls(calls, sessionRef);
46
+ const toolBatchId = recordToolBatch(sessionId, executionCalls, state.iterations);
47
+ // A sensitive fill (a verification code): every stored copy of the
48
+ // transcript keeps a marker instead of the value; the call runs as is.
49
+ rememberSensitiveValues(sessionId, executionCalls);
45
50
  await Promise.resolve(onToolCall?.(state.iterations, calls));
46
51
  const assistantTurnMsg = buildToolCallAssistantMessage(response, { calls, opts });
47
52
  commitAssistantMessage(messages, assistantTurnMsg, opts);
48
53
  try {
49
54
  opts.onToolPhaseStarted?.();
50
- } catch {}
55
+ } catch {
56
+ // the tool-phase-started observer is advisory
57
+ }
51
58
  const toolsT0 = Date.now();
52
59
  const resultsFrom = messages.length;
53
60
  ({ dedupStubTotal: state.dedupStubTotal, editCount: state.editCount } = await processToolBatch({
@@ -90,7 +97,9 @@ export async function runToolPhase(state, round, sent, onToolCall) {
90
97
  calls: calls.length,
91
98
  elapsedMs: toolsEndedAt - toolsT0,
92
99
  });
93
- } catch {}
100
+ } catch {
101
+ // the tool-phase-completed observer is advisory
102
+ }
94
103
  traceLoopPhaseTiming({
95
104
  iteration: round.nextIteration,
96
105
  preSendMs: sent.preSendMs,
@@ -9,6 +9,7 @@ import {
9
9
  drainPendingMessages,
10
10
  releasePendingMessages,
11
11
  } from './pending-messages.mjs';
12
+ import { promptOriginOf } from '../../../../shared/prompt-origin.mjs';
12
13
 
13
14
  const SYNTHETIC_PROMPT_SOURCES = ['goal-continuation', 'goal-closeout'];
14
15
 
@@ -35,6 +36,7 @@ const tailTurnFor = (group) => ({
35
36
  content: group.content,
36
37
  entries: group.entries,
37
38
  ...(group.hop ? { hop: group.hop } : {}),
39
+ ...(group.origin ? { origin: group.origin } : {}),
38
40
  ...(group.mode === PENDING_MODE_TASK_NOTIFICATION
39
41
  ? promptSourceFields(PENDING_MODE_TASK_NOTIFICATION, group.execution)
40
42
  : {}),
@@ -49,13 +51,19 @@ const queuedTurnInput = (tailTurn) => ({
49
51
  pendingEntries: tailTurn.entries,
50
52
  ...(tailTurn.hop ? { hop: tailTurn.hop } : {}),
51
53
  promptSource: promptSourceFields(tailTurn.source, tailTurn.execution),
54
+ ...(tailTurn.origin ? { promptOrigin: tailTurn.origin } : {}),
52
55
  });
53
56
 
54
- export function createAskPromptQueue({ sessionId, promptSource }) {
57
+ // The caller's provenance of its initial prompt, apart from its presentation
58
+ // source: an inbound channel message or an agent report (shared/prompt-origin.mjs).
59
+ const initialPromptOriginFor = (promptOrigin) => promptOriginOf(promptOrigin);
60
+
61
+ export function createAskPromptQueue({ sessionId, promptSource, promptOrigin }) {
55
62
  // Local FIFO of follow-up prompts drained from the pending-message queue
56
63
  // after each turn — keeps queued `agent type=send` messages in order.
57
64
  const tail = [];
58
65
  let initialPromptSource = initialPromptSourceFor(promptSource);
66
+ let initialPromptOrigin = initialPromptOriginFor(promptOrigin);
59
67
  // Queue entries of the input nextTurn handed out that no turn owns yet.
60
68
  // Once a turn starts, its failure path acks or releases them instead.
61
69
  let unstartedEntries = [];
@@ -67,13 +75,15 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
67
75
  * and provenance — or null when nothing model-visible is left to run. */
68
76
  const nextTurn = (original) => {
69
77
  const source = initialPromptSource;
78
+ const origin = initialPromptOrigin;
70
79
  initialPromptSource = null;
80
+ initialPromptOrigin = null;
71
81
  let input;
72
82
  if (tail.length > 0) {
73
83
  // After the first turn, the next prompt comes from the drained queue.
74
84
  input = queuedTurnInput(tail.shift());
75
85
  } else if (hasModelVisiblePromptContent(original.prompt)) {
76
- input = { ...original, pendingEntries: [], promptSource: source };
86
+ input = { ...original, pendingEntries: [], promptSource: source, ...(origin ? { promptOrigin: origin } : {}) };
77
87
  } else {
78
88
  // Idle resume: TUI kicks an empty ask() after execution completions
79
89
  // mirror model-visible bodies into session pending. Drain that queue
@@ -19,6 +19,7 @@ import { armTurnDurability, claimTurnRuntime } from './ask-turn-open.mjs';
19
19
  import { prepareAskTurn, runAskAgentLoop } from './ask-turn-execute.mjs';
20
20
  import { commitAskTurn, publishAskTurn } from './ask-turn-settle.mjs';
21
21
  import { finalizeAskTurnFailure } from './ask-turn-failure.mjs';
22
+ import { cacheWarmTurnKind, endCacheWarmTurn, failedTurnProvenance, noteCacheWarmTurn } from '../cache-warm.mjs';
22
23
 
23
24
  export { _api_call_with_interrupt } from './ask-call-interrupt.mjs';
24
25
  export {
@@ -168,7 +169,14 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
168
169
  // return value (the queued tail turns supersede the original prompt's
169
170
  // result, mirroring how a live chat returns the latest turn).
170
171
  let result;
171
- const queue = createAskPromptQueue({ sessionId, promptSource: askOpts.promptSource });
172
+ const queue = createAskPromptQueue({
173
+ sessionId,
174
+ promptSource: askOpts.promptSource,
175
+ promptOrigin: askOpts.promptOrigin,
176
+ });
177
+ // The turn the prompt-cache warmer is told about last; it forgets it when
178
+ // the turn ends (endCacheWarmTurn), whatever way the ask unwinds.
179
+ let warmTurn = null;
172
180
  // Hoisted so the outer finally (which runs once after the whole turn loop)
173
181
  // can compare against the last turn's generation.
174
182
  let askGeneration = 0;
@@ -213,6 +221,12 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
213
221
  recoverCheckpoint: !crashRecoveryChecked,
214
222
  emitStart: !sessionStartEmitted,
215
223
  });
224
+ // The prompt-cache warmer learns idle gaps from real turns only; a
225
+ // retry is classified by the failed turn's stored provenance.
226
+ // The rebuilt retry message keeps that provenance (ask-turn-execute.mjs).
227
+ const retryProvenance = failedTurnProvenance(claimed.preSession?.messages, input);
228
+ if (retryProvenance) input.retryProvenance = retryProvenance;
229
+ warmTurn = noteCacheWarmTurn(sessionId, cacheWarmTurnKind(input, claimed.preSession?.messages));
216
230
  crashRecoveryChecked = true;
217
231
  sessionStartEmitted = true;
218
232
  askGeneration = claimed.askGeneration;
@@ -234,6 +248,7 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
234
248
  askStartedAt,
235
249
  });
236
250
  result = turn.result;
251
+ endCacheWarmTurn(sessionId, warmTurn);
237
252
  // Turn complete. Drain the pending-message queue: any `agent type=send`
238
253
  // that arrived while this turn was in flight runs next, in order, as a
239
254
  // follow-up user turn. The mutex is still held, so a send racing this
@@ -264,6 +279,9 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
264
279
  return result;
265
280
  }
266
281
  } finally {
282
+ // A failed/cancelled turn ends here too: its warmer turn entry goes (a
283
+ // later ask's own turn is never removed by this one).
284
+ endCacheWarmTurn(sessionId, warmTurn);
267
285
  // A failed/cancelled turn ends the ask: the follow-up turns drained
268
286
  // behind it never ran, so their entries go back to the pending queue.
269
287
  queue.releaseUnstarted();