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,130 @@
1
+ // The fallback chain a running session follows, read from its settings when
2
+ // it is needed (a hop, a status read) instead of the copy taken at creation:
3
+ // an edit made while the session runs applies from its next model request,
4
+ // and a chain cleared to [] stops further hops at once.
5
+ // - A Lead-class session (coding Lead, a bot's chat, Mixy) follows its
6
+ // owner's stored route (owner-route-fallbacks.mjs);
7
+ // - a delegated agent follows the route it was spawned from
8
+ // (`routeFallbackSource`: its agent's route, else Main's, or a named preset).
9
+ // The stored chain applies only while the session's primary — the route it
10
+ // ran on before its first hop — is that stored route's model. A session
11
+ // whose source cannot be read (an older record, a direct route) keeps its own.
12
+ import { findPreset } from '../../runtime-core/config-helpers.mjs';
13
+ import { normalizeWorkflowRoute } from '../../runtime-core/workflow.mjs';
14
+ import { configuredAgentRouteCandidates } from '../../../../shared/agent-route-config.mjs';
15
+ import { executionFallbacks } from '../../../../shared/model-route-chain.mjs';
16
+ import { CODING_MODE, resolveSessionMode } from '../agent-mode.mjs';
17
+ import { _liveSessions } from '../store/live-state.mjs';
18
+ import { ownerConfiguredRoute, sameRouteModel } from './owner-route-fallbacks.mjs';
19
+
20
+ const LEAF_FIELDS = ['effort', 'fast', 'autoEffort', 'modelParameters', 'contextPercent', 'contextTokens'];
21
+
22
+ /** The switchable fields of a route or session record (no chain). */
23
+ export function routeLeaf(route) {
24
+ const leaf = { provider: route?.provider || '', model: route?.model || '' };
25
+ for (const key of LEAF_FIELDS) if (route?.[key] !== undefined && route[key] !== null) leaf[key] = route[key];
26
+ return leaf;
27
+ }
28
+
29
+ /** The route the session ran on before its first fallback hop; its own route
30
+ * while it has not hopped. */
31
+ export function sessionRoutePrimary(session) {
32
+ if (session?.routeFallbackPrimary?.provider) return session.routeFallbackPrimary;
33
+ const first = session?.routeFallbackFailures?.[0];
34
+ if (first?.provider && first?.model) return { provider: first.provider, model: first.model };
35
+ return routeLeaf(session);
36
+ }
37
+
38
+ function normalizedOrNull(stored) {
39
+ if (!stored) return null;
40
+ try {
41
+ return normalizeWorkflowRoute(stored) || null;
42
+ } catch {
43
+ return null;
44
+ }
45
+ }
46
+
47
+ /** The stored route the session's chain comes from, read now; null when the
48
+ * session has no readable source (it then keeps its own chain). */
49
+ export function sessionChainSource(session, config) {
50
+ const { mode, agentId } = resolveSessionMode({ session });
51
+ if (agentId) return ownerConfiguredRoute({ sessionMode: mode, agentId, config });
52
+ const source = session?.routeFallbackSource;
53
+ if (source?.agent) {
54
+ // As the spawn resolved it: the agent's own route, else Main's.
55
+ const own = configuredAgentRouteCandidates(config, source.agent).map(normalizedOrNull).find(Boolean);
56
+ return own || normalizedOrNull(findPreset(config, config?.default));
57
+ }
58
+ if (source?.preset) return normalizedOrNull(findPreset(config, source.preset));
59
+ return null;
60
+ }
61
+
62
+ /** `{ chain, fromSettings }`: the fallback routes the session follows now. */
63
+ export function liveRouteFallbacks(session, config) {
64
+ const source = sessionChainSource(session, config);
65
+ if (!source)
66
+ return { chain: Array.isArray(session?.routeFallbacks) ? session.routeFallbacks : [], fromSettings: false };
67
+ const onSourcePrimary = sameRouteModel(source, sessionRoutePrimary(session));
68
+ return { chain: onSourcePrimary ? executionFallbacks(source) : [], fromSettings: true };
69
+ }
70
+
71
+ /** Index in `chain` of the next route to try: the first after the session's
72
+ * current model that this session has not already run (its primary and the
73
+ * models it already left); `chain.length` when none is left. */
74
+ export function nextRouteFallbackIndex(session, chain) {
75
+ const tried = [sessionRoutePrimary(session), ...(session?.routeFallbackFailures || []), session];
76
+ const at = chain.findIndex((entry) => sameRouteModel(entry, session));
77
+ for (let index = at + 1; index < chain.length; index += 1) {
78
+ if (!tried.some((route) => sameRouteModel(chain[index], route))) return index;
79
+ }
80
+ return chain.length;
81
+ }
82
+
83
+ const modelOf = (route) => ({ provider: route?.provider || '', model: route?.model || '' });
84
+
85
+ /** The public fallback position of one session: the route it is on against
86
+ * its primary, the hop index, the chain it follows now and why it left each model. */
87
+ export function routeFallbackPosition(session, config) {
88
+ const { chain, fromSettings } = liveRouteFallbacks(session, config);
89
+ const next = chain[nextRouteFallbackIndex(session, chain)] || null;
90
+ const primary = sessionRoutePrimary(session);
91
+ const { mode, agentId } = resolveSessionMode({ session });
92
+ let kind = 'agent';
93
+ if (agentId) kind = mode === CODING_MODE ? 'lead' : 'bot';
94
+ return {
95
+ sessionId: session.id,
96
+ kind,
97
+ agent: agentId || session.agent || null,
98
+ current: modelOf(session),
99
+ primary: modelOf(primary),
100
+ onPrimary: sameRouteModel(primary, session),
101
+ fallbackIndex: Number(session.routeFallbackIndex) || 0,
102
+ fallbacks: chain.map(modelOf),
103
+ chainFrom: fromSettings ? 'settings' : 'session',
104
+ next: next ? modelOf(next) : null,
105
+ failures: (session.routeFallbackFailures || []).map(({ provider, model, kind: errorKind, error }) => ({
106
+ provider,
107
+ model,
108
+ kind: errorKind,
109
+ error,
110
+ })),
111
+ };
112
+ }
113
+
114
+ /** Whether the session has left its primary for a fallback model. */
115
+ export const routeFallbackHopped = (session) =>
116
+ Number(session?.routeFallbackIndex) > 0 || Boolean(session?.routeFallbackFailures?.length);
117
+
118
+ /** Positions of the sessions held in this process that follow a chain or have
119
+ * hopped; `keep(position)` narrows them. */
120
+ export function liveRouteFallbackPositions(config, keep = () => true) {
121
+ const rows = [];
122
+ for (const session of _liveSessions.values()) {
123
+ // Only a session with an agent hops (advanceAgentRoute).
124
+ if (!session?.id || session.closed === true || !session.agent) continue;
125
+ const position = routeFallbackPosition(session, config);
126
+ if (!position.fallbacks.length && !routeFallbackHopped(session)) continue;
127
+ if (keep(position)) rows.push(position);
128
+ }
129
+ return rows;
130
+ }
@@ -59,15 +59,19 @@ function omitToolsKey(omitTools) {
59
59
  .join(',');
60
60
  }
61
61
 
62
- export function _buildSharedRules({ omitTools = [], allowTools = null } = {}) {
62
+ export function _buildSharedRules({ omitTools = [], allowTools = null, ownerIsAgent = false } = {}) {
63
63
  const PLUGIN_ROOT = mixdogRoot();
64
64
  const RULES_DIR = join(PLUGIN_ROOT, 'rules');
65
65
  return buildCachedRules(
66
66
  'buildSharedToolContent',
67
67
  'shared tool rules',
68
68
  [join(RULES_DIR, 'shared')],
69
- { PLUGIN_ROOT, DATA_DIR: resolvePluginData(), omitTools, allowTools },
70
- JSON.stringify([omitToolsKey(omitTools), Array.isArray(allowTools) ? omitToolsKey(allowTools) : null])
69
+ { PLUGIN_ROOT, DATA_DIR: resolvePluginData(), omitTools, allowTools, ownerIsAgent },
70
+ JSON.stringify([
71
+ omitToolsKey(omitTools),
72
+ Array.isArray(allowTools) ? omitToolsKey(allowTools) : null,
73
+ ownerIsAgent === true,
74
+ ])
71
75
  );
72
76
  }
73
77
 
@@ -98,8 +102,17 @@ export function _buildRouteRules({ provider = null, model = null, omitTools = []
98
102
 
99
103
  // BP1 = shared tool policy followed by this route's rules. Every site that
100
104
  // renders or re-identifies the BP1 block must use this one composition.
101
- export function _buildBaseRules({ provider = null, model = null, omitTools = [], allowTools = null } = {}) {
102
- return [_buildSharedRules({ omitTools, allowTools }), _buildRouteRules({ provider, model, omitTools, allowTools })]
105
+ export function _buildBaseRules({
106
+ provider = null,
107
+ model = null,
108
+ omitTools = [],
109
+ allowTools = null,
110
+ ownerIsAgent = false,
111
+ } = {}) {
112
+ return [
113
+ _buildSharedRules({ omitTools, allowTools, ownerIsAgent }),
114
+ _buildRouteRules({ provider, model, omitTools, allowTools }),
115
+ ]
103
116
  .filter(Boolean)
104
117
  .join('\n\n---\n\n');
105
118
  }
@@ -201,9 +214,14 @@ export function _buildLeadLanguage() {
201
214
  });
202
215
  }
203
216
 
204
- export function _buildLeadLanguageContext() {
217
+ export function _buildLeadLanguageContext({ includeOutputStyle = true } = {}) {
218
+ const PLUGIN_ROOT = mixdogRoot();
205
219
  const DATA_DIR = resolvePluginData();
206
- return buildCachedRules('buildLeadLanguageContent', 'lead language context', [join(DATA_DIR, 'mixdog-config.json')], {
207
- DATA_DIR,
208
- });
220
+ return buildCachedRules(
221
+ 'buildLeadLanguageContent',
222
+ 'lead language context',
223
+ [join(DATA_DIR, 'mixdog-config.json'), join(PLUGIN_ROOT, 'output-styles'), join(DATA_DIR, 'output-styles')],
224
+ { PLUGIN_ROOT, DATA_DIR, includeOutputStyle },
225
+ includeOutputStyle ? 'style' : 'no-style'
226
+ );
209
227
  }
@@ -17,16 +17,22 @@
17
17
  // stage, lastStreamDeltaAt, lastTransportAt, firstSemanticAt,
18
18
  // lastSemanticAt, lastReasoningAt, lastVisibleTextAt, lastToolProtocolAt,
19
19
  // lastToolCall, lastError, updatedAt,
20
+ // modelRequestStartedAt, requestTransportAt, requestFirstSemanticAt,
21
+ // modelResponseAccepted, // the current logical model request (see
22
+ // // _setLogicalModelRequest); the fields above
23
+ // // stay turn-level history
20
24
  // controller?: AbortController, // set while an ask is in flight
21
25
  // generation?: number, // snapshot taken at ask start
22
26
  // closed?: boolean, // flipped by closeSession()
23
27
  // }
24
28
  import { createAbortController } from '../../../../shared/abort-controller.mjs';
25
29
  import { emitSessionApprovalWaitChange } from '../../../../shared/session-approval-wait.mjs';
26
- import { emitSessionActivityChange } from '../../../../shared/session-activity-signal.mjs';
30
+ import { emitSessionActivityChange, emitSessionTurnStart } from '../../../../shared/session-activity-signal.mjs';
27
31
  import { DEFAULT_ACTIVITY_HEARTBEAT_MS } from '../../stall-policy.mjs';
28
32
  import { MODEL_THINKING_STAGE, awaitingModelResponse, lastProgressAt } from '../../../../shared/quiet-progress.mjs';
29
- import { finishBrowserTurn } from '../../../../browser-bridge/client.mjs';
33
+ import { beginBrowserTurn, finishBrowserTurn, forgetBrowserSession } from '../../../../browser-bridge/client.mjs';
34
+ import { registerSessionPurgeHook } from '../store.mjs';
35
+ import { finishComputerTurn } from '../../../../computer-bridge/client.mjs';
30
36
  import { configureUsageMetricsRuntime, dropMetricSeenState, bumpUsageMetricsTurnId } from './usage-metrics.mjs';
31
37
  import { runtimeState as _runtimeState, isTurnInFlight } from './runtime-state.mjs';
32
38
 
@@ -48,11 +54,25 @@ const VALID_STAGES = new Set([
48
54
  ]);
49
55
  const TERMINAL_STAGES = new Set(['done', 'error']);
50
56
 
57
+ function beginBrowserWork(id, entry) {
58
+ void beginBrowserTurn(id, entry.browserTurnId).catch((error) => {
59
+ process.stderr.write(`[browser] Task start failed: ${error?.message || error}\n`);
60
+ });
61
+ }
62
+
63
+ // A session deleted for good no longer has browser turns to report.
64
+ registerSessionPurgeHook(forgetBrowserSession);
65
+
51
66
  function finishBrowserWork(id, entry, aborted = false) {
52
67
  const turnId = Number(entry.browserTurnId ?? entry.session?.usageMetricsTurnId) || 0;
53
68
  void finishBrowserTurn(id, turnId, { aborted }).catch((error) => {
54
69
  process.stderr.write(`[browser] Task cleanup failed: ${error?.message || error}\n`);
55
70
  });
71
+ // The same terminal state settles the turn's Computer Use saved-login fills
72
+ // (lead and sub-agent sessions alike).
73
+ void finishComputerTurn(id, turnId).catch((error) => {
74
+ process.stderr.write(`[computer] Turn settlement failed: ${error?.message || error}\n`);
75
+ });
56
76
  }
57
77
 
58
78
  // Injected deps that would otherwise pull manager.mjs's store/provider surface
@@ -115,6 +135,23 @@ function _startToolActivityHeartbeat(id) {
115
135
  _toolActivityHeartbeats.set(id, timer);
116
136
  }
117
137
 
138
+ // One logical model request owns one first-output allowance: its request
139
+ // clock and its own first transport / first semantic marks. It begins with the
140
+ // ask's first request, with the first request after the model's previous
141
+ // response was accepted (its tool calls ran — the request that carries the
142
+ // tool results), and with a request after a settled turn. Every other entry
143
+ // into `requesting` — a provider or loop retry, a route fallback, a no-tool
144
+ // recovery continuation — re-sends the same logical request and keeps all of
145
+ // it, so a retry never earns a fresh allowance. The turn-level marks
146
+ // (firstSemanticAt, lastTransportAt, …) are history and are not touched.
147
+ // `startedAt` null: no request yet (an ask starting).
148
+ function _setLogicalModelRequest(entry, startedAt) {
149
+ entry.modelRequestStartedAt = startedAt;
150
+ entry.requestTransportAt = null;
151
+ entry.requestFirstSemanticAt = null;
152
+ entry.modelResponseAccepted = false;
153
+ }
154
+
118
155
  export function updateSessionStage(id, stage) {
119
156
  if (stage === MODEL_THINKING_STAGE) {
120
157
  markSessionRequestSent(id);
@@ -127,8 +164,11 @@ export function updateSessionStage(id, stage) {
127
164
  entry.stage = stage;
128
165
  // A new stage (a retried attempt included) has not sent its request yet.
129
166
  entry.requestSentAt = null;
130
- if (stage === 'requesting' && priorStage !== 'requesting') {
131
- entry.modelRequestStartedAt = now;
167
+ if (
168
+ stage === 'requesting' &&
169
+ (!entry.modelRequestStartedAt || entry.modelResponseAccepted || TERMINAL_STAGES.has(priorStage))
170
+ ) {
171
+ _setLogicalModelRequest(entry, now);
132
172
  }
133
173
  entry.lastProgressAt = now;
134
174
  entry.updatedAt = now;
@@ -149,6 +189,7 @@ export function markSessionAskStart(id) {
149
189
  const sessionForTurn = entry.session ?? _deps.loadSession(id);
150
190
  if (sessionForTurn) bumpUsageMetricsTurnId(sessionForTurn);
151
191
  entry.browserTurnId = Number(sessionForTurn?.usageMetricsTurnId) || 0;
192
+ beginBrowserWork(id, entry);
152
193
  entry.stage = 'connecting';
153
194
  entry.lastStreamDeltaAt = null;
154
195
  entry.lastTransportAt = null;
@@ -175,10 +216,11 @@ export function markSessionAskStart(id) {
175
216
  // after provider admission (the scheduler emits stage=requesting).
176
217
  const now = Date.now();
177
218
  entry.askStartedAt = now;
178
- entry.modelRequestStartedAt = null;
219
+ _setLogicalModelRequest(entry, null);
179
220
  entry.lastProgressAt = now;
180
221
  entry.updatedAt = now;
181
222
  entry.taskWaits = 0;
223
+ emitSessionTurnStart(id);
182
224
  emitSessionActivityChange(id);
183
225
  }
184
226
  /** The provider put the request on the wire; its response headers are
@@ -211,13 +253,14 @@ export function markSessionTransportActivity(id) {
211
253
  if (!entry || entry.closed || entry.controller?.signal?.aborted || TERMINAL_STAGES.has(entry.stage)) return;
212
254
  const now = Date.now();
213
255
  entry.lastTransportAt = now;
256
+ entry.requestTransportAt = now;
214
257
  entry.updatedAt = now;
215
258
  }
216
259
  function _normalizeModelProgressKind(kind) {
217
260
  let value = 'semantic';
218
261
  if (typeof kind === 'string') value = kind;
219
262
  else if (kind && typeof kind.kind === 'string') value = kind.kind;
220
- if (value === 'transport' || value === 'reasoning' || value === 'text' || value === 'tool') {
263
+ if (value === 'transport' || value === 'keepalive' || value === 'reasoning' || value === 'text' || value === 'tool') {
221
264
  return value;
222
265
  }
223
266
  return 'semantic';
@@ -239,12 +282,22 @@ export async function markSessionStreamDelta(id, kind = 'semantic') {
239
282
  markSessionTransportActivity(id);
240
283
  return;
241
284
  }
285
+ if (progressKind === 'keepalive') {
286
+ markSessionTransportActivity(id);
287
+ // A keepalive before the request's first semantic event is covered by the
288
+ // first-output window and never counts as progress. lastProgressAt stays
289
+ // untouched: the watchdog caps how long keepalives may extend it.
290
+ if (entry.requestFirstSemanticAt) entry.lastKeepaliveAt = Date.now();
291
+ return;
292
+ }
242
293
  _stopToolActivityHeartbeat(id);
243
294
  const now = Date.now();
244
295
  // Every semantic model event also proves transport health. The inverse is
245
296
  // intentionally false: raw chunks/keepalives update only lastTransportAt.
246
297
  entry.lastTransportAt = now;
298
+ entry.requestTransportAt = now;
247
299
  if (!entry.firstSemanticAt) entry.firstSemanticAt = now;
300
+ if (!entry.requestFirstSemanticAt) entry.requestFirstSemanticAt = now;
248
301
  entry.lastSemanticAt = now;
249
302
  entry.lastSemanticKind = progressKind;
250
303
  if (progressKind === 'reasoning') entry.lastReasoningAt = now;
@@ -278,7 +331,12 @@ export function markSessionToolCall(id, toolName) {
278
331
  entry.toolOutputTailAt = null;
279
332
  entry.toolStartedAt = Date.now();
280
333
  entry.lastTransportAt = entry.toolStartedAt;
334
+ entry.requestTransportAt = entry.toolStartedAt;
281
335
  if (!entry.firstSemanticAt) entry.firstSemanticAt = entry.toolStartedAt;
336
+ if (!entry.requestFirstSemanticAt) entry.requestFirstSemanticAt = entry.toolStartedAt;
337
+ // The response whose tool call runs now was accepted: the next model
338
+ // request carries its tool results and is a new logical request.
339
+ entry.modelResponseAccepted = true;
282
340
  entry.lastSemanticAt = entry.toolStartedAt;
283
341
  entry.lastSemanticKind = 'tool';
284
342
  entry.lastToolProtocolAt = entry.toolStartedAt;
@@ -418,6 +476,18 @@ export function markSessionCancelled(id) {
418
476
  entry.emptyFinalAt = null;
419
477
  _unlinkParentAbortListener(entry);
420
478
  }
479
+ /**
480
+ * The session's current logical model request: when it started and whether
481
+ * it has produced semantic output yet. A provider stream opened for it — a
482
+ * retry or a route fallback included — bounds its first-output phase by this
483
+ * request instead of starting a fresh one. Null without a request.
484
+ */
485
+ export function getLogicalModelRequest(sessionId) {
486
+ const entry = sessionId ? _runtimeState.get(sessionId) : null;
487
+ if (!entry?.modelRequestStartedAt) return null;
488
+ return { startedAt: entry.modelRequestStartedAt, outputSeen: Boolean(entry.requestFirstSemanticAt) };
489
+ }
490
+
421
491
  export function getSessionRuntime(id) {
422
492
  return id ? _runtimeState.get(id) || null : null;
423
493
  }
@@ -440,8 +510,10 @@ export function getSessionProgressSnapshot(sessionId) {
440
510
  const firstActivityAt = firstSemanticAt;
441
511
  const stage = entry.stage || 'idle';
442
512
  const activeModelStage = stage === 'connecting' || stage === 'requesting' || stage === 'streaming';
443
- const waitingForTransport = Boolean(modelRequestStartedAt && activeModelStage && !entry.lastTransportAt);
444
- const waitingForFirstSemantic = Boolean(modelRequestStartedAt && activeModelStage && !firstSemanticAt);
513
+ // Judged per logical model request: output an earlier request of this turn
514
+ // produced never ends a later request's first-output phase.
515
+ const waitingForTransport = Boolean(modelRequestStartedAt && activeModelStage && !entry.requestTransportAt);
516
+ const waitingForFirstSemantic = Boolean(modelRequestStartedAt && activeModelStage && !entry.requestFirstSemanticAt);
445
517
  return {
446
518
  stage,
447
519
  askStartedAt,
@@ -463,6 +535,7 @@ export function getSessionProgressSnapshot(sessionId) {
463
535
  toolOutputTail: entry.toolOutputTail || null,
464
536
  toolOutputTailAt: entry.toolOutputTailAt || 0,
465
537
  lastProgressAt: entry.lastProgressAt || 0,
538
+ lastKeepaliveAt: entry.lastKeepaliveAt || 0,
466
539
  updatedAt: entry.updatedAt || 0,
467
540
  hasFirstActivity: Boolean(firstSemanticAt && (!askStartedAt || firstSemanticAt >= askStartedAt)),
468
541
  hasFirstSemantic: Boolean(firstSemanticAt && (!askStartedAt || firstSemanticAt >= askStartedAt)),
@@ -24,6 +24,7 @@ import {
24
24
  } from './runtime-liveness.mjs';
25
25
  import { clearTurnCheckpoint } from './turn-checkpoint.mjs';
26
26
  import { forgetSessionSaveBaseline } from '../store/save-worker.mjs';
27
+ import { publishSessionPersistence } from '../store/session-persistence-events.mjs';
27
28
  import { forgetSessionLoadCache } from '../store/load-cache.mjs';
28
29
  import { releaseReadSnapshotScope } from '../../tools/builtin/snapshot-store.mjs';
29
30
  import { cancelOwnedShellTrees } from '../../tools/lib/owned-shell-trees.mjs';
@@ -142,6 +143,7 @@ function finishClose({ id, reason, tombstone, entry, closeSnapshot, newGen, outc
142
143
  // above; committing it stops the turn's checkpoint writer. Only now is it
143
144
  // safe to remove the crash fallback.
144
145
  closeSnapshot?.commit();
146
+ publishSessionPersistence(id, 'closed');
145
147
  _stopToolActivityHeartbeat(id);
146
148
  cancelOwnedShellProcesses({ id, reason, tombstone });
147
149
  clearTurnCheckpoint(id);
@@ -42,11 +42,13 @@ import { ensureCodexWireSessionId, mintSessionId } from './session-id.mjs';
42
42
  import { providerCacheKey } from './provider-cache-key.mjs';
43
43
  import { buildSessionRecord, normalizeDesktopSessionMetadata, sessionOriginFields } from './session-record.mjs';
44
44
  import { normalizeWorkflowRoute } from '../../runtime-core/workflow.mjs';
45
+ import { executionFallbacks } from '../../../../shared/model-route-chain.mjs';
45
46
  import { ownerRouteFallbacks } from './owner-route-fallbacks.mjs';
46
47
  import { applyPendingWorkspaceReroot, refreshSessionBp3Environment } from './prompt-utils.mjs';
47
48
  import { isWorktreeBound } from '../../../../shared/worktrees/contract.mjs';
48
49
  import { applyAgentToolExposure } from '../loop/tool-exposure-migration.mjs';
49
50
  import { prewarmSessionAutoEffort } from './ask-turn-auto-effort.mjs';
51
+ import { cancelCacheWarm } from '../cache-warm.mjs';
50
52
 
51
53
  // Durable turn-checkpoint recovery; re-exported so prior importers of this
52
54
  // module stay unchanged.
@@ -239,11 +241,13 @@ export function createSession(createOpts) {
239
241
  ? Object.hasOwn(opts, 'routeFallbacks')
240
242
  ? opts.routeFallbacks
241
243
  : ownerRouteFallbacks({ sessionMode, agentId: actingAgent, provider: providerName, model: modelName })
242
- : normalizeWorkflowRoute({
243
- provider: providerName,
244
- model: modelName,
245
- fallbacks: Object.hasOwn(opts, 'routeFallbacks') ? opts.routeFallbacks : presetObj?.fallbacks,
246
- })?.fallbacks;
244
+ : executionFallbacks(
245
+ normalizeWorkflowRoute({
246
+ provider: providerName,
247
+ model: modelName,
248
+ fallbacks: Object.hasOwn(opts, 'routeFallbacks') ? opts.routeFallbacks : presetObj?.fallbacks,
249
+ })
250
+ );
247
251
  // Provider cache strategy — agentRuntime.resolveSync() above is a
248
252
  // best-effort injection point (setAgentRuntime() has no live caller
249
253
  // today, so that branch never fires); build it directly here so every
@@ -262,7 +266,7 @@ export function createSession(createOpts) {
262
266
  : agentProfileRevision(surface.resolvedAgent, { mixy: sessionMode === AGENT_MODE });
263
267
  // A bot thread lives on across releases: the rules it was built from.
264
268
  const rulesRevision = agentProfile && sessionMode === AGENT_MODE ? promptRulesRevision() : '';
265
- const prompt = composeSessionSystem(opts, { profile, providerName, modelName, surface, sessionMode });
269
+ const prompt = composeSessionSystem(opts, { profile, providerName, modelName, surface, sessionMode, sessionId: id });
266
270
  const messages = seedSessionMessages(prompt, opts.files);
267
271
  logSessionSurface(surface);
268
272
  const contextMeta = resolveSessionContextMeta(provider, modelName, {
@@ -288,6 +292,13 @@ export function createSession(createOpts) {
288
292
  if (rulesRevision) session.rulesRevision = rulesRevision;
289
293
  }
290
294
  if (routeFallbacks?.length) session.routeFallbacks = routeFallbacks;
295
+ // Where an agent's chain is read from at each hop (route-fallback-chain.mjs).
296
+ const fallbackSource = Object.hasOwn(opts, 'routeFallbackSource')
297
+ ? opts.routeFallbackSource
298
+ : presetObj?.fallbackSource;
299
+ if (!actingAgent && fallbackSource && typeof fallbackSource === 'object') {
300
+ session.routeFallbackSource = { ...fallbackSource };
301
+ }
291
302
  // A non-native agent sends core + bridge, built from its filtered tools.
292
303
  applyAgentToolExposure(session);
293
304
  refreshSessionBp3Environment(session, opts.cwd);
@@ -315,24 +326,27 @@ export function contextSeedForRouteUpdate(session, routeChanged, selectedContext
315
326
  // ever replaced; custom-prompt or agent layouts without that block are left
316
327
  // untouched, and a same-variant switch is a no-op.
317
328
  export function _refreshSessionRuleVariantsForModel(session, previousModel, previousProvider = session?.provider) {
329
+ const ownerIsAgent = isAgentOwner(session);
318
330
  const deny = [
319
331
  ...(Array.isArray(session?.disallowedTools) ? session.disallowedTools : []),
320
332
  ...(getHiddenAgent(session?.agent || null) ? ['Skill'] : []),
321
- ...(delegationDisabled(session, isAgentOwner(session)) ? ['agent'] : []),
333
+ ...(delegationDisabled(session, ownerIsAgent) ? ['agent'] : []),
322
334
  ];
323
335
  const allowTools = honoredSchemaAllowlist(session?.schemaAllowedTools, {
324
- ownerIsAgent: isAgentOwner(session),
336
+ ownerIsAgent,
325
337
  agent: session?.agent || null,
326
338
  });
327
339
  const previousRules = _buildBaseRules({
328
340
  omitTools: [...deny, unusedModelEditToolName(previousModel)],
329
341
  allowTools,
342
+ ownerIsAgent,
330
343
  provider: previousProvider,
331
344
  model: previousModel,
332
345
  });
333
346
  const nextRules = _buildBaseRules({
334
347
  omitTools: [...deny, unusedModelEditToolName(session?.model)],
335
348
  allowTools,
349
+ ownerIsAgent,
336
350
  provider: session?.provider,
337
351
  model: session?.model,
338
352
  });
@@ -364,6 +378,7 @@ function applyRouteFields(session, route) {
364
378
  else delete session.routeFallbacks;
365
379
  delete session.routeFallbackIndex;
366
380
  delete session.routeFallbackFailures;
381
+ delete session.routeFallbackPrimary;
367
382
  }
368
383
  ensureCodexWireSessionId(session);
369
384
  if (Object.hasOwn(route, 'modelParameters')) {
@@ -428,6 +443,10 @@ function resetSessionForRouteChange(id, session, previousModel, previousProvider
428
443
  delete session._providerPrefixGuardState;
429
444
  // The new route resolves its own wire before its first request.
430
445
  session.wireRoute = null;
446
+ // A warm chain replays the previous route's request: stop it. Its recorded
447
+ // warm use names that route, so it never counts as fresh cache for the new
448
+ // one (compact-policy.mjs shouldCompactForExpiredAgentCache).
449
+ cancelCacheWarm(id);
431
450
  const prepared = _prepareResumeTools(session, session.preset || 'full');
432
451
  session.tools = prepared.tools;
433
452
  session.toolSpec = prepared.toolSpec;
@@ -21,6 +21,7 @@ import {
21
21
  describeShellToolsStartupState,
22
22
  } from '../../tools/builtin/runtime-capabilities.mjs';
23
23
  import { captureOriginalUserCwd } from '../../../../shared/user-cwd.mjs';
24
+ import { sessionScratchDir } from '../../../../shared/session-scratch.mjs';
24
25
  import { delegationDisabled } from './session-tool-surface.mjs';
25
26
  import { contextAckMessage } from '../compact/user-message-kind.mjs';
26
27
 
@@ -31,7 +32,9 @@ import { contextAckMessage } from '../compact/user-message-kind.mjs';
31
32
  // it still get a location line via captureOriginalUserCwd(), which
32
33
  // resolves explicit session signals first and never leaks the daemon's
33
34
  // install root (user-cwd.mjs safe fallback chain).
34
- function buildShellEnvironmentContext(opts, ownerIsAgent, toolsForRouting) {
35
+ function buildShellEnvironmentContext(opts, ownerIsAgent, toolsForRouting, sessionId = null) {
36
+ // Fixed per session id and data dir, so the line never changes across turns.
37
+ const scratchDir = sessionScratchDir(sessionId);
35
38
  const sessionCwdLine = opts.cwd || captureOriginalUserCwd();
36
39
  const wantsGitStartupLine = toolsForRouting.some((tool) => tool?.name === 'git');
37
40
  let cwdContextLine = '';
@@ -45,6 +48,9 @@ function buildShellEnvironmentContext(opts, ownerIsAgent, toolsForRouting) {
45
48
  return [
46
49
  cwdContextLine,
47
50
  `- Shell: ${shellName}. Use ${shellName} syntax unless the user specifies otherwise.`,
51
+ scratchDir
52
+ ? `- Scratch: ${scratchDir} — this session's scratch directory; TEMP, TMP and TMPDIR in shell commands point here.`
53
+ : '',
48
54
  // Which common tools the shell can run, measured where commands run
49
55
  // (login shell on POSIX, this process's PATH on Windows); see
50
56
  // runtime-capabilities.mjs. Recorded runs spent a round per session
@@ -84,7 +90,7 @@ export function buildWorkspacePromptContext(session, cwd) {
84
90
  ...(Array.isArray(session?.deferredToolCatalog) ? session.deferredToolCatalog : []),
85
91
  ];
86
92
  return {
87
- environmentContext: buildShellEnvironmentContext({ cwd }, ownerIsAgent, tools),
93
+ environmentContext: buildShellEnvironmentContext({ cwd }, ownerIsAgent, tools, session?.id),
88
94
  // Agent mode never carries project instruction files.
89
95
  instructionFilesContext:
90
96
  session?.skipInstructionFiles === true || sessionModeOf(session) === AGENT_MODE
@@ -143,7 +149,7 @@ export function sessionRolePromptFields(identity, { ownerIsAgent, toolFreeRole,
143
149
  };
144
150
  }
145
151
 
146
- export function composeSessionSystem(opts, { profile, providerName, modelName, surface, sessionMode }) {
152
+ export function composeSessionSystem(opts, { profile, providerName, modelName, surface, sessionMode, sessionId }) {
147
153
  const agentMode = sessionMode === AGENT_MODE;
148
154
  const { ownerIsAgent, resolvedAgent, skills } = surface;
149
155
  // A tool-free hidden role (a one-shot classifier or title writer) carries
@@ -156,6 +162,7 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
156
162
  : _buildBaseRules({
157
163
  omitTools: surface.ruleOmitTools,
158
164
  allowTools: surface.schemaAllowedTools,
165
+ ownerIsAgent,
159
166
  provider: providerName,
160
167
  model: modelName,
161
168
  });
@@ -177,12 +184,12 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
177
184
  const metaContext = leadOnly ? _buildLeadMetaContext({ includeOutputStyle: !agentMode }) : '';
178
185
  // Lead-only response language; closes the environment block so no English
179
186
  // system text (session/shell/git lines) follows it.
180
- const languageContext = leadOnly ? _buildLeadLanguageContext() : '';
187
+ const languageContext = leadOnly ? _buildLeadLanguageContext({ includeOutputStyle: !agentMode }) : '';
181
188
  // Cwd, shell and repository facts only serve tool calls; a tool-free role
182
189
  // gets none, which also keeps its prompt identical across projects.
183
190
  const shellEnvironmentContext = toolFreeRole
184
191
  ? ''
185
- : buildShellEnvironmentContext(opts, ownerIsAgent, surface.toolsForRouting);
192
+ : buildShellEnvironmentContext(opts, ownerIsAgent, surface.toolsForRouting, sessionId);
186
193
  // Persisted env tail: refreshSessionBp3Environment rebuilds the env block
187
194
  // as [session, bp3EnvironmentContext], so the language block must
188
195
  // already sit at the end of this string to stay last after a refresh.
@@ -36,7 +36,7 @@ export function normalizeDesktopSessionMetadata(value, cwd = null) {
36
36
  return null;
37
37
  }
38
38
 
39
- function initialCompactionConfig(compaction = {}, contextMeta = {}) {
39
+ export function initialCompactionConfig(compaction = {}, contextMeta = {}) {
40
40
  return {
41
41
  auto: compaction?.auto !== false,
42
42
  model: compaction?.model || null,
@@ -3,7 +3,8 @@
3
3
  import { compareCodePoints } from '../../../../shared/code-point-order.mjs';
4
4
  import { getMcpTools } from '../../mcp/client.mjs';
5
5
  import { getInternalTools } from '../../internal-tools.mjs';
6
- import { BUILTIN_TOOLS } from '../../tools/builtin/builtin-tools.mjs';
6
+ import { BUILTIN_TOOLS, bindAgentOwner, bindShellKind } from '../../tools/builtin/builtin-tools.mjs';
7
+ import { resolveShellFor } from '../../tools/builtin/shell-runtime.mjs';
7
8
  import { PATCH_TOOL_DEFS } from '../../tools/patch-tool-defs.mjs';
8
9
  import { CODE_GRAPH_TOOL_DEFS } from '../../tools/code-graph-tool-defs.mjs';
9
10
  import { buildSkillToolDefs } from '../../context/collect.mjs';
@@ -50,7 +51,7 @@ const FILESYSTEM_TOOL_NAMES = new Set(['code_graph', 'find', 'glob', 'list', 'gr
50
51
  const READONLY_FS_TOOL_NAMES = new Set(['code_graph', 'find', 'glob', 'list', 'grep', 'read']);
51
52
 
52
53
  // Lead-only control tools: never part of a worker/sub-agent session surface.
53
- export const AGENT_WORKER_DENIED_TOOLS = Object.freeze(new Set(['agent', 'ask_user', 'session']));
54
+ export const AGENT_WORKER_DENIED_TOOLS = Object.freeze(new Set(['agent', 'ask_user', 'handoff_user', 'session']));
54
55
 
55
56
  export function finalizeSessionToolList(
56
57
  tools,
@@ -69,7 +70,7 @@ export function finalizeSessionToolList(
69
70
  }
70
71
  if (ownerIsAgent) {
71
72
  out = out.filter((t) => !AGENT_WORKER_DENIED_TOOLS.has(String(t?.name || '').toLowerCase()));
72
- out = orderSessionTools(out);
73
+ out = orderSessionTools(out.map(bindAgentOwner));
73
74
  }
74
75
  return out;
75
76
  }
@@ -101,7 +102,11 @@ export function resolveSessionTools(
101
102
  // time (loop.mjs), so the schema bytes stay bit-identical across roles /
102
103
  // cwds and the provider cache shard does not fragment.
103
104
  const skillTools = buildSkillToolDefs(skills, { ownerIsAgentSession });
104
- return filterModelEditTools(_computeBaseTools(toolSpec, mcp, skillTools), modelName);
105
+ // The shell text follows the system shell the runtime actually resolves
106
+ // (Git Bash/WSL on Windows, pwsh on POSIX), before the edit-dialect rewrite.
107
+ const shellKind = resolveShellFor('default')?.shellType;
108
+ const base = _computeBaseTools(toolSpec, mcp, skillTools).map((tool) => bindShellKind(tool, shellKind));
109
+ return filterModelEditTools(base, modelName);
105
110
  }
106
111
 
107
112
  export function previewSessionTools(toolSpec, skills = [], options = {}) {
@@ -93,6 +93,10 @@ export function captureTurnCheckpointContextState(session, messages, currentUser
93
93
  ),
94
94
  ...(kind === 'post_compact' ? { usageSnapshot: { ...usageSnapshot } } : {}),
95
95
  compaction: compactCheckpointState(session.compaction),
96
+ // Diagnostic only: the prefix fingerprint of the turn's last settled
97
+ // request (anthropic-prefix-trace.mjs), so the first request after a
98
+ // crash is still traced against it.
99
+ ...(session.providerPrefixBaseline ? { prefixBaseline: session.providerPrefixBaseline } : {}),
96
100
  };
97
101
  }
98
102