mixdog 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (468) hide show
  1. package/README.md +8 -4
  2. package/package.json +8 -8
  3. package/scripts/native-release-status.mjs +238 -0
  4. package/scripts/verify-runtime-dependency-versions.mjs +158 -0
  5. package/src/agents/reviewer/AGENT.md +5 -7
  6. package/src/agents/reviewer/agent.json +1 -1
  7. package/src/defaults/shipped-history.json +9 -1
  8. package/src/defaults/skills/browser-use/SKILL.md +6 -3
  9. package/src/defaults/skills/local-provider/SKILL.md +33 -6
  10. package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
  11. package/src/defaults/skills/setup/SKILL.md +23 -1
  12. package/src/defaults/skills/setup/references/actions.md +50 -3
  13. package/src/defaults/skills/setup/references/surfaces.md +23 -3
  14. package/src/defaults/skills/setup-guide/SKILL.md +7 -3
  15. package/src/defaults/skills/visualize/SKILL.md +9 -6
  16. package/src/defaults/skills/visualize/references/craft.md +8 -1
  17. package/src/help.mjs +1 -1
  18. package/src/lib/keychain-cjs.cjs +4 -1
  19. package/src/lib/rules-builder.cjs +14 -7
  20. package/src/rules/agent-mode/AGENT_MODE.md +8 -5
  21. package/src/rules/agent-mode/MIXY.md +6 -8
  22. package/src/rules/lead/LEAD.md +7 -10
  23. package/src/rules/shared/10-tool-workflow.md +4 -0
  24. package/src/rules/shared/20-research.md +2 -0
  25. package/src/rules/shared/45-destructive.md +5 -1
  26. package/src/rules/shared/60-verification.md +6 -4
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
  28. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
  29. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
  30. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
  31. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
  32. package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
  33. package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
  34. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
  35. package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
  36. package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
  37. package/src/runtime/agent/orchestrator/config.mjs +11 -0
  38. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -2
  39. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -5
  40. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +6 -10
  41. package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
  42. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +84 -32
  43. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +38 -11
  44. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +15 -3
  45. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
  46. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +84 -42
  48. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
  49. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +14 -1
  50. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
  51. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +27 -8
  52. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  53. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
  54. package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
  55. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +14 -1
  56. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
  57. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  58. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
  59. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +16 -0
  60. package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
  61. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -1
  62. package/src/runtime/agent/orchestrator/providers/mixdog-local.mjs +3 -1
  63. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +1 -0
  64. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +5 -5
  65. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +9 -5
  66. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +9 -1
  67. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +2 -1
  68. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +30 -3
  69. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +1 -1
  70. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +3 -1
  71. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
  72. package/src/runtime/agent/orchestrator/providers/registry.mjs +19 -0
  73. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +13 -1
  74. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
  75. package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
  76. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
  77. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +5 -0
  78. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
  79. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +10 -1
  81. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +4 -6
  82. package/src/runtime/agent/orchestrator/runtime-core/route-context-state.mjs +81 -0
  83. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -1
  84. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +52 -6
  85. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +35 -13
  86. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +7 -6
  87. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
  89. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +8 -3
  90. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -1
  91. package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
  92. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
  93. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
  94. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -2
  95. package/src/runtime/agent/orchestrator/session/agent-room.mjs +196 -45
  96. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
  97. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  98. package/src/runtime/agent/orchestrator/session/compact/continuation.mjs +15 -6
  99. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +45 -19
  100. package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
  101. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +44 -0
  102. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +185 -37
  103. package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
  104. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
  105. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
  106. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +6 -2
  107. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +4 -1
  108. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  109. package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
  110. package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +240 -0
  111. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +102 -35
  112. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
  113. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +19 -9
  114. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
  115. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
  116. package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
  117. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
  118. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +199 -109
  119. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +5 -0
  120. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +2 -0
  121. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/empty-nudge.mjs +1 -1
  122. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +62 -13
  123. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +22 -6
  124. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
  125. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +5 -5
  126. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -0
  127. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
  128. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +33 -8
  129. package/src/runtime/agent/orchestrator/session/loop/tool-exec/call-prep.mjs +5 -0
  130. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +27 -0
  131. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
  132. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
  133. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
  134. package/src/runtime/agent/orchestrator/session/manager/agent-listing-notice.mjs +102 -0
  135. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +2 -0
  136. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +13 -1
  137. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
  138. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +27 -14
  139. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +14 -0
  140. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  141. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +1 -0
  142. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
  143. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +32 -1
  144. package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +115 -0
  145. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
  146. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +6 -0
  147. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
  148. package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
  149. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
  150. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +36 -0
  151. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
  152. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
  153. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
  154. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +28 -9
  155. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +55 -27
  156. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +4 -9
  157. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +14 -1
  158. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +7 -3
  159. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
  160. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
  161. package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
  162. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +52 -11
  163. package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
  164. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +18 -3
  165. package/src/runtime/agent/orchestrator/session/routine-result.mjs +126 -12
  166. package/src/runtime/agent/orchestrator/session/runtime-user-context.mjs +3 -1
  167. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +16 -3
  168. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
  169. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
  170. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
  171. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
  172. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
  173. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +5 -4
  174. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +140 -0
  175. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +5 -0
  176. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +15 -5
  177. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +49 -1
  178. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +80 -1
  179. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
  180. package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
  181. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +33 -1
  182. package/src/runtime/agent/orchestrator/session/store-summary-visibility.d.mts +5 -0
  183. package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +37 -0
  184. package/src/runtime/agent/orchestrator/session/store.mjs +1 -0
  185. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
  186. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
  187. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
  188. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +35 -5
  189. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +42 -2
  190. package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +47 -14
  191. package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
  192. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +6 -3
  193. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
  194. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
  195. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
  196. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
  197. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +127 -20
  198. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +557 -0
  199. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +10 -12
  200. package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
  201. package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
  202. package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
  203. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
  204. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
  205. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +42 -23
  206. package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
  207. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
  208. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
  209. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
  210. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
  211. package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
  212. package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
  213. package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
  214. package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
  215. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
  216. package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
  217. package/src/runtime/attachments/attachment-reference.mjs +155 -0
  218. package/src/runtime/attachments/legacy-office.mjs +110 -0
  219. package/src/runtime/attachments/limits.mjs +5 -1
  220. package/src/runtime/attachments/office-extract.mjs +3 -6
  221. package/src/runtime/attachments/pdf-extract.mjs +84 -10
  222. package/src/runtime/attachments/prompt-restore.mjs +70 -0
  223. package/src/runtime/attachments/store.mjs +109 -33
  224. package/src/runtime/browser-bridge/client.mjs +73 -20
  225. package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
  226. package/src/runtime/channels/lib/scheduler.mjs +14 -7
  227. package/src/runtime/channels/lib/state-file.mjs +15 -15
  228. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
  229. package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
  230. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
  231. package/src/runtime/channels/lib/worker-main.mjs +3 -2
  232. package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
  233. package/src/runtime/effort-judge/judge-client.mjs +66 -16
  234. package/src/runtime/effort-judge/model-install.mjs +47 -7
  235. package/src/runtime/local-provider/asset-installer.mjs +10 -4
  236. package/src/runtime/local-provider/catalog.mjs +5 -2
  237. package/src/runtime/local-provider/registered-models.mjs +64 -27
  238. package/src/runtime/local-provider/server.mjs +2 -3
  239. package/src/runtime/media/adapters/image-api.mjs +89 -0
  240. package/src/runtime/media/auth.mjs +64 -1
  241. package/src/runtime/media/catalog.mjs +66 -4
  242. package/src/runtime/media/jobs.mjs +4 -0
  243. package/src/runtime/media/lanes.mjs +46 -5
  244. package/src/runtime/media/media-usage.mjs +17 -0
  245. package/src/runtime/media/renditions.mjs +15 -15
  246. package/src/runtime/media/store.mjs +36 -35
  247. package/src/runtime/media/tool.mjs +8 -1
  248. package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
  249. package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
  250. package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
  251. package/src/runtime/memory/lib/memory-chunk-quality.mjs +14 -2
  252. package/src/runtime/memory/lib/pg/process.mjs +8 -4
  253. package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
  254. package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
  255. package/src/runtime/office/core/journal.mjs +7 -14
  256. package/src/runtime/office/design/library/design-library-core.mjs +4 -16
  257. package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
  258. package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
  259. package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
  260. package/src/runtime/office/pdf/pdf-render.mjs +30 -18
  261. package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
  262. package/src/runtime/office/portable/portable-soffice.mjs +135 -29
  263. package/src/runtime/shared/agent-avatar-sprites.mjs +23 -8
  264. package/src/runtime/shared/agent-avatar.mjs +3 -2
  265. package/src/runtime/shared/agent-kind-migration.mjs +200 -0
  266. package/src/runtime/shared/agent-message-envelope.d.mts +6 -0
  267. package/src/runtime/shared/agent-message-envelope.mjs +44 -0
  268. package/src/runtime/shared/agent-reap-state.d.mts +4 -0
  269. package/src/runtime/shared/agent-room-host.d.mts +31 -0
  270. package/src/runtime/shared/agent-room-host.mjs +58 -0
  271. package/src/runtime/shared/agent-store.mjs +24 -7
  272. package/src/runtime/shared/agent-task-starts.mjs +27 -0
  273. package/src/runtime/shared/atomic-file.d.mts +50 -0
  274. package/src/runtime/shared/atomic-file.mjs +394 -132
  275. package/src/runtime/shared/background-tasks.mjs +7 -4
  276. package/src/runtime/shared/bot-hops.mjs +35 -0
  277. package/src/runtime/shared/bot-split-migration.mjs +1 -1
  278. package/src/runtime/shared/bounded-download.mjs +4 -2
  279. package/src/runtime/shared/config.mjs +39 -9
  280. package/src/runtime/shared/defaults-separation.mjs +6 -2
  281. package/src/runtime/shared/delegated-approval-host.mjs +74 -0
  282. package/src/runtime/shared/err-text.mjs +4 -0
  283. package/src/runtime/shared/error-presentation.mjs +22 -4
  284. package/src/runtime/shared/file-has-data.mjs +28 -0
  285. package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
  286. package/src/runtime/shared/pending-agent-work.mjs +54 -0
  287. package/src/runtime/shared/process-lifecycle.mjs +8 -12
  288. package/src/runtime/shared/projects.mjs +50 -41
  289. package/src/runtime/shared/provider-accounts.mjs +17 -12
  290. package/src/runtime/shared/redact-directories.mjs +18 -0
  291. package/src/runtime/shared/remove-directory.mjs +28 -0
  292. package/src/runtime/shared/routine-trigger.d.mts +6 -1
  293. package/src/runtime/shared/routine-trigger.mjs +14 -6
  294. package/src/runtime/shared/run-child.d.mts +3 -0
  295. package/src/runtime/shared/run-child.mjs +24 -3
  296. package/src/runtime/shared/session-baseline-store.mjs +8 -2
  297. package/src/runtime/shared/session-sidebar-host.d.mts +11 -2
  298. package/src/runtime/shared/session-sidebar-host.mjs +16 -3
  299. package/src/runtime/shared/singleton-owner.mjs +7 -6
  300. package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
  301. package/src/runtime/shared/staged-update.mjs +4 -2
  302. package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
  303. package/src/runtime/shared/tool-execution-contract.mjs +10 -0
  304. package/src/runtime/shared/tool-work-units.mjs +12 -9
  305. package/src/runtime/shared/transcript-metadata.mjs +28 -3
  306. package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
  307. package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
  308. package/src/runtime/shared/turn-snapshot.mjs +277 -124
  309. package/src/runtime/shared/user-cwd.mjs +9 -4
  310. package/src/runtime/shared/user-data-guard.mjs +92 -61
  311. package/src/runtime/shared/utf8-cut.mjs +10 -0
  312. package/src/runtime/shared/worktrees/activity-gate.mjs +251 -61
  313. package/src/runtime/shared/worktrees/contract.mjs +11 -3
  314. package/src/runtime/shared/worktrees/maintenance.mjs +11 -2
  315. package/src/runtime/shared/worktrees/manager.mjs +419 -52
  316. package/src/runtime/shared/worktrees/registry.mjs +29 -27
  317. package/src/runtime/shared/worktrees/tool-host.mjs +39 -0
  318. package/src/runtime/tidy/core-install.mjs +26 -4
  319. package/src/runtime/tidy/install.mjs +91 -23
  320. package/src/runtime/tidy/process.mjs +41 -8
  321. package/src/runtime/tidy/resolve.mjs +10 -7
  322. package/src/runtime/web-search/lib/config.mjs +4 -16
  323. package/src/session-runtime/agent-home-delivery.mjs +542 -204
  324. package/src/session-runtime/agent-profile-changes.mjs +16 -0
  325. package/src/session-runtime/agent-room-delivery.mjs +81 -35
  326. package/src/session-runtime/agent-task-sessions.mjs +811 -179
  327. package/src/session-runtime/agent-tool-routing.mjs +1 -0
  328. package/src/session-runtime/boot/apis.mjs +48 -24
  329. package/src/session-runtime/boot/config.mjs +1 -0
  330. package/src/session-runtime/boot/facade.mjs +16 -7
  331. package/src/session-runtime/boot/infrastructure.mjs +14 -2
  332. package/src/session-runtime/boot/providers.mjs +2 -2
  333. package/src/session-runtime/boot/shared.mjs +12 -6
  334. package/src/session-runtime/boot/tools.mjs +23 -3
  335. package/src/session-runtime/bot-status.mjs +432 -0
  336. package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
  337. package/src/session-runtime/config-lifecycle.mjs +60 -55
  338. package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
  339. package/src/session-runtime/held-requests.mjs +31 -33
  340. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
  341. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
  342. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +24 -26
  343. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
  344. package/src/session-runtime/lifecycle/teardown.mjs +11 -3
  345. package/src/session-runtime/mcp-glue/connect.mjs +100 -186
  346. package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
  347. package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
  348. package/src/session-runtime/media-api.mjs +5 -2
  349. package/src/session-runtime/model-recency.mjs +1 -0
  350. package/src/session-runtime/model-route/route-tuning.mjs +4 -1
  351. package/src/session-runtime/model-route/set-route.mjs +61 -1
  352. package/src/session-runtime/owned-automation-run.mjs +8 -1
  353. package/src/session-runtime/provider-models/row-hydration.mjs +8 -1
  354. package/src/session-runtime/quick-model-rows/model-meta.mjs +2 -0
  355. package/src/session-runtime/quick-model-rows/provider-rows.mjs +7 -1
  356. package/src/session-runtime/route-resolution.mjs +16 -8
  357. package/src/session-runtime/route-state.mjs +1 -59
  358. package/src/session-runtime/routine-home-turn.mjs +5 -3
  359. package/src/session-runtime/runtime-bootstrap.mjs +5 -3
  360. package/src/session-runtime/runtime-paths.mjs +11 -5
  361. package/src/session-runtime/runtime-review-api.mjs +4 -1
  362. package/src/session-runtime/runtime-tunables.mjs +6 -0
  363. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +11 -2
  364. package/src/session-runtime/services/agent-tool/close-flow.mjs +4 -2
  365. package/src/session-runtime/services/agent-tool/execute-send.mjs +1 -0
  366. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +1 -0
  367. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +34 -19
  368. package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
  369. package/src/session-runtime/services/agent-tool/send-flow.mjs +25 -21
  370. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +7 -0
  371. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
  372. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +8 -5
  373. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +22 -2
  374. package/src/session-runtime/services/agent-tool/worker-index.mjs +4 -6
  375. package/src/session-runtime/services/agent-tool.mjs +6 -0
  376. package/src/session-runtime/services/daemon-crash-capture/daemon-exit-record.mjs +1 -1
  377. package/src/session-runtime/services/daemon-crash-capture/retention.mjs +4 -3
  378. package/src/session-runtime/services/hook-bus/config-loader.mjs +14 -5
  379. package/src/session-runtime/services/hook-bus/rule-file.mjs +49 -11
  380. package/src/session-runtime/services/plugin-admin.mjs +26 -26
  381. package/src/session-runtime/services/provider-admin.mjs +26 -6
  382. package/src/session-runtime/services/schedule-access.mjs +33 -4
  383. package/src/session-runtime/services/seeds.mjs +4 -3
  384. package/src/session-runtime/services/usage-dashboard.mjs +1 -1
  385. package/src/session-runtime/services/usage-stats-model.mjs +2 -1
  386. package/src/session-runtime/services/worktree-access.mjs +27 -0
  387. package/src/session-runtime/session-create/materialize.mjs +2 -3
  388. package/src/session-runtime/session-create/session-options.mjs +15 -2
  389. package/src/session-runtime/session-hooks.mjs +9 -17
  390. package/src/session-runtime/settings-builtin-tools-api.mjs +65 -1
  391. package/src/session-runtime/settings-compaction-api.mjs +86 -39
  392. package/src/session-runtime/setup-tool/executor.mjs +12 -2
  393. package/src/session-runtime/setup-tool/settings-contract.mjs +34 -1
  394. package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
  395. package/src/session-runtime/skills-api.mjs +12 -5
  396. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +349 -0
  397. package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
  398. package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
  399. package/src/session-runtime/tool-policy/policy-stage.mjs +183 -0
  400. package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
  401. package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
  402. package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
  403. package/src/session-runtime/tool-policy-refresh.mjs +48 -369
  404. package/src/session-runtime/tool-surface.mjs +10 -4
  405. package/src/session-runtime/turn/session-ops.mjs +8 -0
  406. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +95 -88
  407. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  408. package/src/session-runtime/turn/turn-run.mjs +7 -2
  409. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
  410. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +527 -333
  411. package/src/session-runtime/workflow-agents-api/agent-route.mjs +85 -63
  412. package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
  413. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
  414. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
  415. package/src/session-runtime/workspace/transition-steps.mjs +1 -18
  416. package/src/session-runtime/workspace/transitions.mjs +279 -67
  417. package/src/session-runtime/workspace/workspace-state.mjs +7 -6
  418. package/src/session-runtime/workspace/worktree-tool.mjs +194 -0
  419. package/src/standalone/daemon-agent-control.mjs +4 -1
  420. package/src/standalone/daemon-lag-profiler.mjs +3 -1
  421. package/src/standalone/daemon-session-control.mjs +173 -15
  422. package/src/standalone/daemon-telemetry.mjs +9 -0
  423. package/src/standalone/daemon.mjs +33 -10
  424. package/src/standalone/local-session-runtime.mjs +33 -16
  425. package/src/standalone/session-client.mjs +7 -2
  426. package/src/standalone/session-protocol.mjs +8 -0
  427. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +2 -0
  428. package/src/standalone/session-service/agent-route-follow.mjs +69 -0
  429. package/src/standalone/session-service/session-calls/session-turns.mjs +33 -4
  430. package/src/standalone/session-service.mjs +21 -0
  431. package/src/standalone/session-state-projection.mjs +19 -9
  432. package/src/standalone/session-tool-output.mjs +36 -9
  433. package/src/standalone/staged-import.mjs +47 -0
  434. package/src/tui/App.jsx +2 -0
  435. package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
  436. package/src/tui/app/message-selector.mjs +15 -2
  437. package/src/tui/app/model-options.mjs +16 -2
  438. package/src/tui/app/model-picker.mjs +2 -1
  439. package/src/tui/app/route-pickers.mjs +3 -1
  440. package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
  441. package/src/tui/app/slash-commands.mjs +1 -1
  442. package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
  443. package/src/tui/dist/index.mjs +617 -369
  444. package/src/tui/paste-attachments.mjs +0 -1
  445. package/src/tui/paste-text-policy.mjs +4 -5
  446. package/src/tui/prompt-history-store.mjs +16 -21
  447. package/src/tui/session/agent-job-feed/execution-delivery.mjs +4 -1
  448. package/src/tui/session/context-state.mjs +4 -0
  449. package/src/tui/session/notice-surface.mjs +3 -0
  450. package/src/tui/session/session-api/intake/abort.mjs +52 -18
  451. package/src/tui/session/session-api/intake/rewind.mjs +39 -4
  452. package/src/tui/session/session-api/media.mjs +2 -1
  453. package/src/tui/session/session-api/routes-agent-definitions.mjs +76 -0
  454. package/src/tui/session/session-api/routes-write.mjs +203 -0
  455. package/src/tui/session/session-api/routes.mjs +23 -247
  456. package/src/tui/session/session-api/settings.mjs +14 -1
  457. package/src/tui/session/session-flow/drain.mjs +28 -3
  458. package/src/tui/session/session-flow/failed-turn-rewind.mjs +4 -2
  459. package/src/tui/session/session-flow/queue/take-entries.mjs +8 -0
  460. package/src/tui/session/session-flow/steering.mjs +8 -3
  461. package/src/tui/session/tool-approval.mjs +142 -14
  462. package/src/tui/session/transcript-intake.mjs +2 -0
  463. package/src/tui/session/turn.mjs +23 -14
  464. package/src/tui/transcript-tool-failures.mjs +8 -2
  465. package/src/vendor/statusline/src/gateway/route-meta.mjs +7 -8
  466. package/src/vendor/statusline/src/gateway/session-routes.mjs +6 -7
  467. package/src/rules/agent-mode/ROUTINE.md +0 -6
  468. package/src/session-runtime/room-member-gate.mjs +0 -48
@@ -22,7 +22,10 @@ function customProviderModels(provider, providerConfig, discovered = providerCac
22
22
  } catch {
23
23
  return [];
24
24
  }
25
- return effectiveCustomModelRows(config, discovered, { providerId: provider });
25
+ const providerName = clean(config.name);
26
+ return effectiveCustomModelRows(config, discovered, { providerId: provider }).map((row) =>
27
+ providerName ? { ...row, providerName } : row
28
+ );
26
29
  }
27
30
 
28
31
  export function createQuickProviderRows({
@@ -53,6 +56,8 @@ export function createQuickProviderRows({
53
56
  display: model.display || model.name || modelId,
54
57
  contextWindow: model.contextWindow || meta.contextWindow || null,
55
58
  outputTokens: model.outputTokens || meta.outputTokens || null,
59
+ // An explicit value (an override's false included) wins; the catalog fills the rest.
60
+ supportsVision: model.supportsVision ?? meta.supportsVision,
56
61
  supportsReasoning: model.supportsReasoning === true || meta.supportsReasoning === true,
57
62
  supportsFunctionCalling: model.supportsFunctionCalling === true || meta.supportsFunctionCalling === true,
58
63
  supportsPromptCaching: model.supportsPromptCaching === true || meta.supportsPromptCaching === true,
@@ -78,6 +83,7 @@ export function createQuickProviderRows({
78
83
  contextWindow: meta.contextWindow || null,
79
84
  outputTokens: meta.outputTokens || null,
80
85
  latest: routeLike.latest === true,
86
+ supportsVision: meta.supportsVision,
81
87
  supportsReasoning: !!routeLike.effort || meta.supportsReasoning === true,
82
88
  supportsFunctionCalling: meta.supportsFunctionCalling === true,
83
89
  supportsPromptCaching: meta.supportsPromptCaching === true,
@@ -22,6 +22,10 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
22
22
  if (routeHasModel()) return rt.route;
23
23
  const models = await runAbortable(signal, () => collectProviderModels());
24
24
  throwIfAborted(signal);
25
+ // A model chosen during the catalog read stands: a new task's reservation
26
+ // prewarm starts on the empty route, its draft model lands meanwhile, and
27
+ // the first prompt joins this very prewarm.
28
+ if (routeHasModel()) return rt.route;
25
29
  if (!models?.length) {
26
30
  throw new Error('No provider models available. Open /providers to sign in, then /model to choose a model.');
27
31
  }
@@ -47,15 +51,19 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
47
51
  .find((option) => option?.id === 'context')
48
52
  ?.options?.find((option) => clean(option?.value) === contextValue);
49
53
  const modelDisplay = routeModelDisplay(rt.config, targetRoute, modelMeta);
50
- const selectedContextWindow = [contextState.selectedContextWindow, contextOption?.contextWindow]
54
+ // Without a known window the selection (share, exact tokens, resolved
55
+ // window) is kept as requested — the session sizes it from the provider's
56
+ // window; dropping it silently put the route back on the model's default.
57
+ // With one it is the clamped value, absent when it is the default window.
58
+ const windowKnown = contextState.contextDefaultPercent !== undefined;
59
+ const selectedContextWindow = [
60
+ contextState.selectedContextWindow,
61
+ contextOption?.contextWindow,
62
+ windowKnown ? undefined : targetRoute.selectedContextWindow,
63
+ ]
51
64
  .map(Number)
52
65
  .find((value) => value > 0);
53
- // Without a known window the exact selection is kept as requested; with
54
- // one it is the clamped value, absent when it is the default window.
55
- const contextTokens =
56
- contextState.contextDefaultPercent === undefined
57
- ? normalizeContextTokens(targetRoute.contextTokens)
58
- : contextState.contextTokens;
66
+ const contextTokens = windowKnown ? contextState.contextTokens : normalizeContextTokens(targetRoute.contextTokens);
59
67
  const { contextTokens: _requestedTokens, ...routeFields } = targetRoute;
60
68
  rt.route = {
61
69
  ...routeFields,
@@ -63,7 +71,7 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
63
71
  fastCapable,
64
72
  effectiveEffort,
65
73
  effortOptions: effortItemsFor(rt.route.provider, modelMeta, effectiveEffort),
66
- contextPercent: contextState.contextPercent,
74
+ contextPercent: windowKnown ? contextState.contextPercent : targetRoute.contextPercent,
67
75
  contextDefaultPercent: contextState.contextDefaultPercent,
68
76
  ...(contextTokens ? { contextTokens } : {}),
69
77
  ...(selectedContextWindow ? { selectedContextWindow } : {}),
@@ -7,8 +7,6 @@ import {
7
7
  import { clean, hasOwn } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
8
8
  import { coerceEffortFor } from '../runtime/agent/orchestrator/runtime-core/effort.mjs';
9
9
  import { fastCapableFor } from '../runtime/agent/orchestrator/runtime-core/model-capabilities.mjs';
10
- import { providerCachedModelMetadataSync } from '../runtime/agent/orchestrator/providers/provider-catalog-cache.mjs';
11
- import { contextWindowRange, normalizeContextTokens } from '../runtime/shared/llm/default-context-window.mjs';
12
10
 
13
11
  export function resolveRouteEffortState(targetRoute = {}, modelMeta = null) {
14
12
  const requested = hasOwn(targetRoute, 'effort') ? targetRoute.effort : targetRoute.preset?.effort || null;
@@ -36,63 +34,7 @@ export function selectionFastCapable(provider, modelMeta, effort, modelParameter
36
34
  return !modelMetaLooksResolved(modelMeta) || fastCapableFor(provider, modelMeta, effort, modelParameters);
37
35
  }
38
36
 
39
- // The persisted provider model rows are the SAME source the picker sized its
40
- // slider against, so they carry both windows (openai-oauth: 272k default /
41
- // 1M max). Reading them keeps a percentage saved against the picker's scale
42
- // meaningful; anything that only knows a single window would silently rescale
43
- // it (30% of 272k instead of 30% of 1M).
44
- function cachedRouteWindows(provider, model) {
45
- const row = providerCachedModelMetadataSync(provider, model)?.rawProviderModel || null;
46
- if (!row) return null;
47
- const contextWindow = Number(row.contextWindow ?? row.context_window ?? row.max_input_tokens) || 0;
48
- const maxContextWindow = Number(row.maxContextWindow ?? row.max_context_window) || 0;
49
- return contextWindow > 0 || maxContextWindow > 0 ? { contextWindow, maxContextWindow } : null;
50
- }
51
-
52
- export function resolveRouteContextState(targetRoute = {}, modelMeta = null, windowLookup = cachedRouteWindows) {
53
- // Only providers that implement getCachedModelInfo (openai-oauth, cursor,
54
- // openai-compat, opencode-go) hand lookupModelMeta a window; every other one
55
- // (anthropic-oauth, grok-oauth, gemini, …) gets the bare `{ id, provider }`
56
- // placeholder. Reading the window from that alone yields 0, which dropped the
57
- // saved context percentage for the entire session — while resolveSessionContextMeta
58
- // went on to size that session from the provider/catalog window (Claude Opus 5:
59
- // a full 1M rather than the selected 500k). Read the cached provider row here so
60
- // the percentage and the session boundary cannot disagree.
61
- const windowMeta =
62
- Number(modelMeta?.contextWindow) > 0 || Number(modelMeta?.maxContextWindow) > 0
63
- ? modelMeta
64
- : windowLookup?.(clean(targetRoute?.provider), clean(targetRoute?.model)) || modelMeta;
65
- const { defaultWindow, maxWindow } = contextWindowRange({
66
- provider: clean(targetRoute?.provider),
67
- contextWindow: windowMeta?.contextWindow,
68
- maxContextWindow: windowMeta?.maxContextWindow,
69
- });
70
- if (!maxWindow) {
71
- return { contextPercent: undefined, contextDefaultPercent: undefined, selectedContextWindow: undefined };
72
- }
73
- const contextDefaultPercent = Math.max(10, Math.min(100, Math.round((defaultWindow / maxWindow) * 10) * 10));
74
- // An exact token selection overrides the 10% stops. It is clamped to the
75
- // selectable range; one that lands on the default window is the default.
76
- const requestedTokens = normalizeContextTokens(targetRoute?.contextTokens);
77
- if (requestedTokens) {
78
- const contextTokens = Math.max(Math.ceil(maxWindow * 0.1), Math.min(maxWindow, requestedTokens));
79
- if (contextTokens === defaultWindow) {
80
- return { contextPercent: contextDefaultPercent, contextDefaultPercent, selectedContextWindow: defaultWindow };
81
- }
82
- const contextPercent = Math.max(10, Math.min(100, Math.round((contextTokens / maxWindow) * 10) * 10));
83
- return { contextPercent, contextDefaultPercent, selectedContextWindow: contextTokens, contextTokens };
84
- }
85
- const requested = Number(targetRoute?.contextPercent);
86
- const contextPercent =
87
- Number.isFinite(requested) && requested > 0
88
- ? Math.max(10, Math.min(100, Math.round(requested / 10) * 10))
89
- : contextDefaultPercent;
90
- const selectedContextWindow =
91
- contextPercent === contextDefaultPercent
92
- ? defaultWindow
93
- : Math.max(1, Math.floor((maxWindow * contextPercent) / 100));
94
- return { contextPercent, contextDefaultPercent, selectedContextWindow };
95
- }
37
+ export { resolveRouteContextState } from '../runtime/agent/orchestrator/runtime-core/route-context-state.mjs';
96
38
 
97
39
  /**
98
40
  * Human label for the statusline. A display-only user alias
@@ -9,8 +9,10 @@
9
9
  * it rides the thread's queue as its own `routine` entry (one per turn, never
10
10
  * merged or steered into another), shows as a routine marker row, and selects
11
11
  * skills only from the routine's instructions (`skillSelection`), never from a
12
- * webhook payload. While it runs the thread counts as unattended, so its
13
- * approvals are held for the owner (held-requests.mjs). Resolves with the
12
+ * webhook payload. While it runs the thread counts as an unattended run
13
+ * (held-requests.mjs): the saved routine is the user's grant, so it never asks
14
+ * (outbound actions are allowed within the bot's permissions; payments and
15
+ * permanent deletes are refused, human-gate/run-policy.mjs). Resolves with the
14
16
  * reply once the turn ends; rejects when the turn fails, is cancelled, or the
15
17
  * caller's `signal` aborts (which also aborts the turn once it runs).
16
18
  */
@@ -126,7 +128,7 @@ export async function runRoutineTurn(
126
128
  onCommitted: () => {
127
129
  if (started) return;
128
130
  started = true;
129
- // Nobody watches this turn: its approvals are held for the owner.
131
+ // Nobody watches this turn: it never asks (run-policy.mjs).
130
132
  unmark = markUnattendedRun(homeId, { kind, agentId, name });
131
133
  if (aborted) void abortTurn();
132
134
  },
@@ -13,22 +13,24 @@ import {
13
13
  CODE_GRAPH_TOOL_DEFS,
14
14
  STATUSLINE_SESSION_ROUTES,
15
15
  STANDALONE_ROOT,
16
- STANDALONE_DATA_DIR,
16
+ standaloneDataDir,
17
17
  } from './runtime-paths.mjs';
18
18
 
19
19
  export function prepareStandaloneEnvironment() {
20
20
  process.env.MIXDOG_QUIET_SESSION_LOG ??= '1';
21
21
  const startedAt = performance.now();
22
+ // Resolved per runtime start: this start's data folder, not the first one's.
23
+ const dataDir = standaloneDataDir();
22
24
  ensureStandaloneEnvironment({
23
25
  rootDir: STANDALONE_ROOT,
24
- dataDir: STANDALONE_DATA_DIR,
26
+ dataDir,
25
27
  });
26
28
  // Office journals exist only for cross-process crash recovery, so startup just
27
29
  // prunes expired ones in the background. Surfacing them as session context made
28
30
  // every new session (agents included) re-announce unrelated leftovers for the
29
31
  // full 30-day retention window; recovery stays reachable on demand through
30
32
  // office action=transactions / action=recover.
31
- listOfficeJournals(STANDALONE_DATA_DIR).catch(() => {});
33
+ listOfficeJournals(dataDir).catch(() => {});
32
34
  bootProfile('standalone-env:ready', { ms: (performance.now() - startedAt).toFixed(1) });
33
35
  }
34
36
 
@@ -1,6 +1,6 @@
1
- import { homedir } from 'node:os';
2
- import { dirname, join } from 'node:path';
1
+ import { dirname } from 'node:path';
3
2
  import { fileURLToPath } from 'node:url';
3
+ import { resolvePluginData } from '../runtime/shared/plugin-paths.mjs';
4
4
 
5
5
  export const RUNTIME = '../runtime/agent/orchestrator';
6
6
  export const WEB_SEARCH_RUNTIME = '../runtime/web-search/index.mjs';
@@ -12,10 +12,16 @@ export const STATUSLINE_SESSION_ROUTES = '../vendor/statusline/src/gateway/sessi
12
12
 
13
13
  const SESSION_RUNTIME_DIR = dirname(fileURLToPath(import.meta.url));
14
14
  export const STANDALONE_ROOT = dirname(SESSION_RUNTIME_DIR);
15
- const mixdogHome = process.env.MIXDOG_HOME || join(homedir(), '.mixdog');
16
- export const STANDALONE_DATA_DIR = process.env.MIXDOG_DATA_DIR || join(mixdogHome, 'data');
15
+
16
+ /**
17
+ * The standalone data directory, resolved from the environment on every call.
18
+ * A runtime start (a pristine boundary, a second page session) retargets
19
+ * MIXDOG_DATA_DIR, so a load-time constant would point every later start back
20
+ * at the first run's folder.
21
+ */
22
+ export const standaloneDataDir = resolvePluginData;
17
23
 
18
24
  /** The data directory a runtime writes to: its config module's plugin data dir, else the standalone default. */
19
25
  export function pluginDataDir(cfgMod) {
20
- return cfgMod.getPluginData?.() || STANDALONE_DATA_DIR;
26
+ return cfgMod.getPluginData?.() || standaloneDataDir();
21
27
  }
@@ -2,6 +2,7 @@ import { registerCacheInvalidationListener } from '../runtime/agent/orchestrator
2
2
  import { turnReviewReply } from '../runtime/shared/turn-review-reply.mjs';
3
3
  import {
4
4
  clearSessionChangeHistory,
5
+ forgetTurnSnapshotSession,
5
6
  getSessionReviewDiff,
6
7
  getSessionReviewFilePatch,
7
8
  getTurnChanges,
@@ -19,8 +20,10 @@ import { registerSessionPurgeHook } from '../runtime/agent/orchestrator/session/
19
20
 
20
21
  // A deleted history stays deleted for as long as its session exists; the
21
22
  // session's own deletion takes the marker — and its stored first-seen file
22
- // contents — with it.
23
+ // contents — with it, and its in-memory turn, parked worker reviews and
24
+ // bound worker trackers.
23
25
  registerSessionPurgeHook((sessionId) => {
26
+ forgetTurnSnapshotSession(sessionId);
24
27
  void forgetSessionChangeHistoryMarker(sessionId);
25
28
  void forgetSessionBaselines(sessionId);
26
29
  });
@@ -36,6 +36,12 @@ export function readRuntimeTunables() {
36
36
  // connected tools fold synchronously; in-flight servers join through the
37
37
  // late-tool announcement path. Operators may opt back into a grace window.
38
38
  mcpTurnGraceMs: envDelayMs('MIXDOG_MCP_TURN_GRACE_MS', 0, { min: 0, max: 2_000 }),
39
+ // A spawned agent's first turn may be its only one, so it waits for the
40
+ // initial connect — but only this long: a slow-but-alive server (a
41
+ // 20 s handshake is seen in the wild) must not hold the first model
42
+ // request for its whole startup budget. Later servers join through the
43
+ // late-tool announcement path on the agent's next turn.
44
+ mcpAgentGraceMs: envDelayMs('MIXDOG_MCP_AGENT_GRACE_MS', 3_000, { min: 0, max: 30_000 }),
39
45
  // Boot-time remote start is deferred past the first frame; see the caller.
40
46
  remoteAutoStartDelayMs: envDelayMs('MIXDOG_REMOTE_AUTOSTART_DELAY_MS', 1_500, { min: 0, max: 60_000 }),
41
47
  providerWarmupEnabled:
@@ -5,6 +5,7 @@ import { cancelBackgroundTask, listBackgroundTasks } from '../../../../runtime/s
5
5
  import { presentErrorText } from '../../../../runtime/shared/err-text.mjs';
6
6
  import { clean } from '../helpers.mjs';
7
7
  import { isLeadPoolAgent } from '../worker-rows.mjs';
8
+ import { isUnnotifiedRestartFailure } from '../worker-index/row-liveness.mjs';
8
9
 
9
10
  export function createCloseAll({ registry, close }) {
10
11
  const { tags, tagAgents, tagCwds } = registry;
@@ -17,11 +18,13 @@ export function createCloseAll({ registry, close }) {
17
18
 
18
19
  // Drop the closed workers' rows: every non-Lead row for an unscoped
19
20
  // teardown, only this owner's (plus the rows just closed) for a scoped one.
21
+ // A row whose owner is still owed its restart failure stays (a process exit
22
+ // closes every worker; the next process tells the owner).
20
23
  function purgeWorkerRows(ownerSessionId, closedSessionIds) {
21
24
  registry.flushWorkerIndexMutations();
22
25
  registry.writeWorkerRows((byKey, tombstonesByKey) => {
23
26
  for (const [key, row] of [...byKey.entries()]) {
24
- if (isLeadPoolAgent(row.agent)) continue;
27
+ if (isLeadPoolAgent(row.agent) || isUnnotifiedRestartFailure(row)) continue;
25
28
  if (
26
29
  ownerSessionId &&
27
30
  clean(row.ownerSessionId) !== ownerSessionId &&
@@ -38,15 +41,20 @@ export function createCloseAll({ registry, close }) {
38
41
  // Lead's workers: the worker index and task registry are shared by every
39
42
  // Lead in the process, and an unscoped sweep wiped sibling Leads' idle
40
43
  // workers mid-window.
44
+ // A process exit (`scope.processExit`) closes the workers but keeps their
45
+ // rows: the next process lists the finished ones for their pane window and
46
+ // settles the ones the exit cut off (restart-notify), exactly as after a
47
+ // crash. Dropping them emptied every sub-agent list after a daemon restart.
41
48
  return async function closeAll(reason = 'cli-agent-close-all', scope = {}) {
42
49
  const ownerSessionId = clean(scope.callerSessionId);
50
+ const keepRows = scope.processExit === true;
43
51
  const context = ownerSessionId ? { callerSessionId: ownerSessionId } : {};
44
52
  registry.refreshTagsFromSessions({ scanSessions: false, context });
45
53
  const closed = [];
46
54
  const failed = [];
47
55
  for (const { tag, session } of registry.agentSessionEntries({ scanSessions: false, context })) {
48
56
  try {
49
- closed.push(await close({ sessionId: session.id }, context));
57
+ closed.push(await close({ sessionId: session.id }, context, { keepRow: keepRows }));
50
58
  } catch (err) {
51
59
  failed.push({ tag, error: presentErrorText(err, { surface: 'agent' }) });
52
60
  }
@@ -57,6 +65,7 @@ export function createCloseAll({ registry, close }) {
57
65
  closed.push({ closed: true, tag: task.tag || null, sessionId: task.sessionId || null, task_id: task.task_id });
58
66
  }
59
67
  if (!ownerSessionId) resetLocalTagState();
68
+ if (keepRows) return { closed, failed };
60
69
  const closedSessionIds = new Set(closed.map((row) => clean(row.sessionId)).filter(Boolean));
61
70
  purgeWorkerRows(ownerSessionId, closedSessionIds);
62
71
  return { closed, failed };
@@ -37,7 +37,9 @@ export function createCloseFlow({ mgr, registry, views }) {
37
37
  }
38
38
  }
39
39
 
40
- async function close(args, context = {}) {
40
+ /** `keepRow`: a process exit closes the worker but leaves its row (and its
41
+ * descendants') for the next process (close-all.mjs). */
42
+ async function close(args, context = {}, { keepRow = false } = {}) {
41
43
  const scopedContext = agentScope(args, context);
42
44
  registry.refreshTagsFromSessions({ scanSessions: registry.wantsSessionScan(args), context: scopedContext });
43
45
  const taskId = taskIdFromArgs(args);
@@ -73,7 +75,7 @@ export function createCloseFlow({ mgr, registry, views }) {
73
75
  if (task?.taskId) cancelBackgroundTask(task.taskId, CLOSE_REASON);
74
76
  // Drop the row only once the cancellation is DURABLY recorded: a failed
75
77
  // close that still forgot the row would leave no cancelled state behind.
76
- if (ok) {
78
+ if (ok && !keepRow) {
77
79
  registry.forgetTerminalSession(tag, sessionId);
78
80
  for (const descendantSessionId of descendantSessionIds) {
79
81
  registry.removeWorkerRow({ sessionId: descendantSessionId });
@@ -70,6 +70,7 @@ export function createSendDispatch({ registry, defaultCwd, sendFlow, spawnFlow,
70
70
  async function send(args, { scopedContext, callerCwd, context, notifyContext }) {
71
71
  try {
72
72
  const prepared = await sendFlow.prepareSend(args, scopedContext);
73
+ await sendFlow.adoptCaller(prepared, notifyContext);
73
74
  return sendFlow.dispatchToExistingSession(prepared, notifyContext);
74
75
  } catch (err) {
75
76
  return await respawnDeadTagSend(err, args, { callerCwd, context, notifyContext });
@@ -51,6 +51,7 @@ export function createSpawnDispatch({
51
51
  }
52
52
  if (liveSessionId && registry.getLiveSession(liveSessionId)) {
53
53
  const prepared = await sendFlow.prepareSend({ ...args, tag: explicitTag }, scopedContext);
54
+ await sendFlow.adoptCaller(prepared, notifyContext);
54
55
  const route = requestedRoute(args);
55
56
  return {
56
57
  reused: sendFlow.dispatchToExistingSession(route ? { ...prepared, route } : prepared, notifyContext, {
@@ -25,11 +25,16 @@ export function isActiveWorkerRow(row = {}) {
25
25
  return !isTerminalWorkerStatus(effective);
26
26
  }
27
27
 
28
- function agentRow({ tag, session, runtime, progress, now, indexRow = null }) {
28
+ function rowState(session, runtime) {
29
29
  const status = session.closed === true ? 'closed' : session.status || 'idle';
30
30
  const stage =
31
31
  session.stage ||
32
32
  (status === 'idle' || status === 'error' || status === 'closed' ? status : runtime?.stage || status);
33
+ return { status, stage };
34
+ }
35
+
36
+ function agentRow({ tag, session, runtime, progress, now, indexRow = null }) {
37
+ const { status, stage } = rowState(session, runtime);
33
38
  // Additive: the current turn's start (worker index, stamped at dispatch) so
34
39
  // surfaces time a continued worker from its turn, not from createdAt.
35
40
  const turnStartedAt = indexRow?.turnStartedAt || session.turnStartedAt || null;
@@ -76,24 +81,34 @@ export function createAgentList({ mgr, refreshTagsFromSessions, agentSessionEntr
76
81
  return function list({ scanSessions = false, context = {}, includeTerminal = false } = {}) {
77
82
  refreshTagsFromSessions({ scanSessions, context });
78
83
  const now = Date.now();
79
- const rows = agentSessionEntries({ scanSessions, context }).map(({ tag, session, indexRow, loaded }) =>
80
- agentRow({
81
- tag,
82
- session,
83
- indexRow,
84
- runtime: mgr.getSessionRuntime?.(session.id),
85
- // A tag-bound entry is the getSession answer itself; an index row or
86
- // a scanned summary is only a projection and still reads the session.
87
- progress: progress.sessionProgressExtras(
88
- session.id,
89
- session.agent || null,
84
+ const rows = [];
85
+ for (const { tag, session, indexRow, loaded } of agentSessionEntries({ scanSessions, context })) {
86
+ const runtime = mgr.getSessionRuntime?.(session.id);
87
+ // Whether a row is listed depends on its status and stage alone, so a
88
+ // finished worker is dropped before its progress is read: that read
89
+ // loads the worker's stored session, and a Lead's status pulse (every
90
+ // 2 s) would otherwise read every worker it ever ran, whole transcripts
91
+ // on first sight, synchronously on the daemon loop.
92
+ if (!includeTerminal && !isActiveWorkerRow(rowState(session, runtime))) continue;
93
+ rows.push(
94
+ agentRow({
95
+ tag,
96
+ session,
97
+ indexRow,
98
+ runtime,
99
+ // A tag-bound entry is the getSession answer itself; an index row or
100
+ // a scanned summary is only a projection and still reads the session.
101
+ progress: progress.sessionProgressExtras(
102
+ session.id,
103
+ session.agent || null,
104
+ now,
105
+ null,
106
+ loaded ? { loaded: session } : {}
107
+ ),
90
108
  now,
91
- null,
92
- loaded ? { loaded: session } : {}
93
- ),
94
- now,
95
- })
96
- );
97
- return includeTerminal ? rows : rows.filter((row) => isActiveWorkerRow(row));
109
+ })
110
+ );
111
+ }
112
+ return rows;
98
113
  };
99
114
  }
@@ -28,6 +28,16 @@ export function restartNotificationId(row) {
28
28
  return `restart:${clean(row.task_id) || `${clean(row.sessionId)}:${clean(row.finishedAt)}`}`;
29
29
  }
30
30
 
31
+ /** The agent task id an execution id names: a task's own id, or the task a
32
+ * restart notification (restartNotificationId) reports; null for one keyed
33
+ * by session because its row recorded no task id. */
34
+ export function agentTaskIdOfExecution(executionId) {
35
+ const id = clean(executionId);
36
+ if (!id.startsWith('restart:')) return id || null;
37
+ const rest = id.slice('restart:'.length);
38
+ return rest && !rest.includes(':') ? rest : null;
39
+ }
40
+
31
41
  /** `pendingRestartFailures()` lists rows whose owner is not yet told;
32
42
  * `markRestartNotified(rows)` stamps them. `mgr` supplies the persisted
33
43
  * pending queue (enqueuePendingMessage / markCompletionEntry /
@@ -17,7 +17,13 @@ import {
17
17
  } from './job-task-reconcile.mjs';
18
18
  import { createTurnReviewCollector } from './turn-review.mjs';
19
19
  import { handoffContent } from '../../handoff-attachments.mjs';
20
+ import { rebindDelegation } from '../../../runtime/agent/orchestrator/session/human-gate/delegation.mjs';
20
21
  import { settledWorkerStatus } from './worker-index/row-liveness.mjs';
22
+ import { whileTurnDispatched } from '../../../runtime/agent/orchestrator/session/manager/runtime-state.mjs';
23
+
24
+ function workerResultIdentity({ session, tag, sessionId }) {
25
+ return { tag, sessionId, agent: session.agent || null, provider: session.provider, model: session.model };
26
+ }
21
27
 
22
28
  // `send` to an existing worker: resolve the live session, run one follow-up
23
29
  // turn under the progress watchdog, and reconcile the job/worker row. Busy
@@ -42,11 +48,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
42
48
  return (result) => {
43
49
  const abnormalError = abnormalEmptyFinishError(result, session.agent || sendAgent);
44
50
  return {
45
- tag,
46
- sessionId,
47
- agent: session.agent || null,
48
- provider: session.provider,
49
- model: session.model,
51
+ ...workerResultIdentity({ session, tag, sessionId }),
50
52
  content: result?.content || '',
51
53
  ...(sessionSurface?.canonical === true ? { handoffOnly: true } : {}),
52
54
  ...(abnormalError ? { error: abnormalError } : {}),
@@ -74,10 +76,12 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
74
76
  const cwd = session.cwd || defaultCwd;
75
77
  // The caller's forwarded files ride along as attachment parts.
76
78
  const prompt = handoffContent(text, args.attachmentParts);
77
- if (canUseSessionSurface(session)) {
78
- return sessionSurface.runTurn({ session, prompt, context: args.context || null, cwd, ...turnHooks });
79
- }
80
- return mgr.askSession(sessionId, prompt, args.context || null, null, cwd, null, turnHooks);
79
+ return whileTurnDispatched(sessionId, () => {
80
+ if (canUseSessionSurface(session)) {
81
+ return sessionSurface.runTurn({ session, prompt, context: args.context || null, cwd, ...turnHooks });
82
+ }
83
+ return mgr.askSession(sessionId, prompt, args.context || null, null, cwd, null, turnHooks);
84
+ });
81
85
  }
82
86
 
83
87
  async function runSend(prepared, notifyContext = null, job = null) {
@@ -110,11 +114,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
110
114
  const settleCancelled = (error, result = null) => {
111
115
  finalStatus = 'cancelled';
112
116
  reconcileJobCancelled(job, {
113
- tag,
114
- sessionId,
115
- agent: session.agent || null,
116
- provider: session.provider,
117
- model: session.model,
117
+ ...workerResultIdentity({ session, tag, sessionId }),
118
118
  content: turnPartialHandoff(error, mgr.getSession(sessionId), handoffMsgStart) || result?.content || '',
119
119
  });
120
120
  };
@@ -145,11 +145,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
145
145
  if (partial) {
146
146
  finalStatus = 'idle';
147
147
  const value = {
148
- tag,
149
- sessionId,
150
- agent: session.agent || null,
151
- provider: session.provider,
152
- model: session.model,
148
+ ...workerResultIdentity({ session, tag, sessionId }),
153
149
  content: watchdogStoppedHandoff(error, partial),
154
150
  stallAbort: true,
155
151
  };
@@ -164,7 +160,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
164
160
  turnReview.complete();
165
161
  watchdog?.stop?.();
166
162
  registry.upsertWorkerSessionDeferred(session, tag, {
167
- ...settledWorkerStatus(finalStatus, stalled),
163
+ ...settledWorkerStatus(finalStatus, stalled, job),
168
164
  finishedAt: new Date().toISOString(),
169
165
  });
170
166
  reconcileJobFinally(job, finalStatus);
@@ -188,6 +184,14 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
188
184
  return { ...prepared, session: mgr.getSession(sessionId) || session };
189
185
  }
190
186
 
187
+ // The calling session hands this worker new work (a `send`, or a spawn of its
188
+ // tag): from now on the worker acts as that caller does, so a run's worker
189
+ // asks when the attended chat reuses it and the other way round. Not for a
190
+ // completion wake, which is the worker's own continuation.
191
+ function adoptCaller({ sessionId }, notifyContext) {
192
+ return rebindDelegation(sessionId, notifyContext?.callerSessionId);
193
+ }
194
+
191
195
  // Shared send dispatch for an already-resolved live session. Used by the
192
196
  // `send` branch AND by the `spawn` branch when an explicit tag maps to a
193
197
  // live session (reuse path). Busy sessions queue the prompt; idle ones run a
@@ -255,5 +259,5 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
255
259
  return true;
256
260
  }
257
261
 
258
- return { prepareSend, dispatchToExistingSession, wakeIdleWorker };
262
+ return { prepareSend, adoptCaller, dispatchToExistingSession, wakeIdleWorker };
259
263
  }
@@ -4,10 +4,12 @@
4
4
  * agent work, and status publication at start and after terminal settlement.
5
5
  */
6
6
  import { sanitizeTaskMeta, startBackgroundTask } from '../../../../runtime/shared/background-tasks.mjs';
7
+ import { recordAgentTaskStart } from '../../../../runtime/shared/agent-task-starts.mjs';
7
8
  import { resourceAdmission } from '../../../../runtime/shared/resource-admission.mjs';
8
9
  import { clean, terminalPidForContext } from '../helpers.mjs';
9
10
  import { renderResult } from '../render.mjs';
10
11
  import { closeManagedSession } from '../../../lifecycle/shared.mjs';
12
+ import { hopOf } from '../../../../runtime/shared/bot-hops.mjs';
11
13
 
12
14
  /** The completion callback that hands a worker's result back to its caller session; null without a handoff. */
13
15
  function handoffNotifier(handoffSessionId, notifySessionCompletion) {
@@ -29,6 +31,8 @@ export function createJobStarter({ mgr, notifyStatusChange, notifySessionComplet
29
31
  ownerSessionId: ownerSessionId || null,
30
32
  clientHostPid: clientHostPid || null,
31
33
  notifyFn: handoffNotifier(handoffSessionId, notifySessionCompletion),
34
+ // The turn that started the job: its completion returns at that bot-chain hop (bot-hops.mjs).
35
+ ...(hopOf(notifyContext?.hop) ? { hop: notifyContext.hop } : {}),
32
36
  };
33
37
  const jobMeta = sanitizeTaskMeta({
34
38
  ...(meta || {}),
@@ -82,6 +86,9 @@ export function createJobStarter({ mgr, notifyStatusChange, notifySessionComplet
82
86
  }
83
87
  },
84
88
  });
89
+ // The model's tool call that started this job owns it (its result message
90
+ // carries the id: agent-task-starts.mjs).
91
+ recordAgentTaskStart(notifyContext?.toolCallId, task.taskId);
85
92
  notifyStatusChange();
86
93
  return task;
87
94
  };
@@ -9,6 +9,7 @@ import { resolveAgentWatchdogPolicy } from '../../../../runtime/agent/orchestrat
9
9
  import { prepareAgentSession } from '../../../../runtime/agent/orchestrator/agent-runtime/session-builder.mjs';
10
10
  import { getProvider } from '../../../../runtime/agent/orchestrator/providers/registry.mjs';
11
11
  import { resolveRouteContextState } from '../../../route-state.mjs';
12
+ import { contextSelectionFromState } from '../../../../runtime/agent/orchestrator/runtime-core/route-context-state.mjs';
12
13
  import { createSpawnPlanner } from './spawn-plan.mjs';
13
14
  import { enterWorkerSpawn } from '../../../workspace/admission-gate.mjs';
14
15
 
@@ -97,11 +98,13 @@ export function createSpawnPreparer({
97
98
 
98
99
  async function createSpawnedSession(plan, spec, prepState) {
99
100
  // A sub-100 context share needs the window it selects; a percent alone
100
- // keeps the full served window.
101
+ // keeps the full served window. A model whose window is not known yet
102
+ // resolves to nothing: the agent's own choice then travels as stored (the
103
+ // session sizes it from the provider's window) instead of being dropped
104
+ // for the model's default.
101
105
  const sessionSpec = { ...spec };
102
106
  if (plan.preset.contextPercent || plan.preset.contextTokens) {
103
- const { contextPercent, selectedContextWindow, contextTokens } = resolveRouteContextState(plan.preset, null);
104
- Object.assign(sessionSpec, { contextPercent, selectedContextWindow }, contextTokens ? { contextTokens } : {});
107
+ Object.assign(sessionSpec, contextSelectionFromState(resolveRouteContextState(plan.preset, null), plan.preset));
105
108
  }
106
109
  if (sessionSurface?.canonical === true && typeof sessionSurface.createChild === 'function') {
107
110
  return sessionSurface.createChild({ spec: sessionSpec, prompt: plan.prompt, tag: plan.tag });
@@ -26,6 +26,7 @@ import { saveSessionAsync } from '../../../../runtime/agent/orchestrator/session
26
26
  import { presetDescriptor } from './spawn-prep.mjs';
27
27
  import { workerStageForStatus } from '../worker-rows.mjs';
28
28
  import { handoffContent } from '../../../handoff-attachments.mjs';
29
+ import { whileTurnDispatched } from '../../../../runtime/agent/orchestrator/session/manager/runtime-state.mjs';
29
30
 
30
31
  // Mid-turn worker persistence cadence. The watchdog sweep runs every second;
31
32
  // a transcript save is far more expensive than a bookkeeping stamp, so the
@@ -121,10 +122,12 @@ export function createSpawnRunner({
121
122
  const { args, session, workerCwd } = prepared;
122
123
  // The caller's forwarded files ride along as attachment parts.
123
124
  const prompt = handoffContent(prepared.prompt, args.attachmentParts);
124
- if (typeof sessionSurface?.runTurn === 'function' && sessionSurface.canRun?.(session) !== false) {
125
- return sessionSurface.runTurn({ session, prompt, context: args.context || null, cwd: workerCwd, ...turnHooks });
126
- }
127
- return mgr.askSession(session.id, prompt, args.context || null, null, workerCwd, null, turnHooks);
125
+ return whileTurnDispatched(session.id, () => {
126
+ if (typeof sessionSurface?.runTurn === 'function' && sessionSurface.canRun?.(session) !== false) {
127
+ return sessionSurface.runTurn({ session, prompt, context: args.context || null, cwd: workerCwd, ...turnHooks });
128
+ }
129
+ return mgr.askSession(session.id, prompt, args.context || null, null, workerCwd, null, turnHooks);
130
+ });
128
131
  }
129
132
 
130
133
  async function runSpawn(prepared, notifyContext = null, job = null) {
@@ -221,7 +224,7 @@ export function createSpawnRunner({
221
224
  watchdog?.stop?.();
222
225
  upsertWorkerSessionDeferred(session, tag, {
223
226
  ...presetDescriptor(agent, preset, presetName),
224
- ...settledWorkerStatus(finalStatus, stalled),
227
+ ...settledWorkerStatus(finalStatus, stalled, job),
225
228
  finishedAt: new Date().toISOString(),
226
229
  });
227
230
  setImmediate(notifyStatusChange);