mixdog 1.2.3 → 1.2.4

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 (465) hide show
  1. package/package.json +1 -1
  2. package/scripts/gate-local.mjs +6 -4
  3. package/scripts/lib/gate-scheduler.mjs +29 -11
  4. package/scripts/probe-provider-catalog.mjs +31 -0
  5. package/scripts/provider-pingpong-live.mjs +128 -38
  6. package/scripts/session-sweep.mjs +5 -25
  7. package/src/agents/maintainer/AGENT.md +1 -1
  8. package/src/agents/maintainer/agent.json +1 -1
  9. package/src/agents/reviewer/AGENT.md +2 -4
  10. package/src/agents/security/AGENT.md +1 -2
  11. package/src/agents/writer/AGENT.md +2 -3
  12. package/src/defaults/shipped-history.json +6 -1
  13. package/src/defaults/skills/image/SKILL.md +21 -23
  14. package/src/lib/keychain-cjs.cjs +13 -11
  15. package/src/rules/agent/AGENT.md +7 -5
  16. package/src/rules/lead/LEAD.md +7 -9
  17. package/src/rules/shared/45-destructive.md +4 -0
  18. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  19. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  20. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  21. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  22. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  23. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  24. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +1 -1
  25. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
  26. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  28. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2 -5
  29. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -0
  30. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  31. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  32. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +81 -10
  33. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
  34. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
  35. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
  36. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
  37. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
  38. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  40. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  41. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  42. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  43. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +41 -11
  44. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
  46. package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
  47. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
  48. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
  49. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
  50. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
  51. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
  52. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
  53. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  54. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  55. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +6 -1
  56. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
  57. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
  58. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
  59. package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
  60. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  61. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
  62. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
  63. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  64. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
  65. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
  66. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  67. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
  68. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
  69. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
  70. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  72. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
  74. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
  75. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
  76. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  78. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
  79. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  80. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +3 -1
  81. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
  82. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
  83. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
  84. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
  85. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
  86. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
  87. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
  88. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
  89. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
  90. package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
  91. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
  92. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
  93. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
  94. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
  95. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
  96. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  97. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
  98. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  99. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  100. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  101. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +3 -1
  102. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  103. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
  104. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
  105. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
  106. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  107. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  108. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  109. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  110. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  111. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -11
  112. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  113. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
  114. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  115. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
  116. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  118. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  119. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +1 -1
  120. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  121. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  122. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -4
  123. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
  124. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -27
  125. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  126. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  127. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  128. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +4 -1
  129. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
  130. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
  131. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  132. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
  133. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
  134. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  135. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
  136. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
  137. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
  138. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  139. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  140. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +21 -1
  141. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
  142. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  143. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
  144. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
  145. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  146. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  147. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  148. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  149. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +29 -8
  150. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  151. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  152. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +32 -14
  153. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
  155. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  156. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
  157. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  158. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
  159. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  160. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
  161. package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
  162. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
  163. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  164. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  165. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  167. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  169. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +5 -11
  170. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  171. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  172. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -32
  174. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  175. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  176. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  177. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +1 -1
  178. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  179. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
  180. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
  181. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  182. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  183. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +7 -8
  184. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  185. package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
  186. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
  187. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
  188. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  189. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
  190. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  191. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  192. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  193. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  194. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  195. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +204 -10
  196. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  197. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  198. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  199. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  200. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  201. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  202. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  203. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +200 -17
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  205. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  206. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  207. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  208. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  209. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  210. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  211. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  212. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  213. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  214. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  215. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  216. package/src/runtime/attachments/store.d.mts +9 -0
  217. package/src/runtime/attachments/store.mjs +80 -9
  218. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  219. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  220. package/src/runtime/computer-bridge/action-schema.mjs +178 -178
  221. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  222. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  223. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  224. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  225. package/src/runtime/github/tool.mjs +118 -17
  226. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  227. package/src/runtime/media/catalog.mjs +4 -4
  228. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  229. package/src/runtime/media/defaults.mjs +37 -0
  230. package/src/runtime/media/jobs.mjs +12 -2
  231. package/src/runtime/media/lanes.mjs +12 -0
  232. package/src/runtime/media/tool-defs.mjs +15 -4
  233. package/src/runtime/media/tool.mjs +41 -12
  234. package/src/runtime/media/upstream-error.mjs +72 -6
  235. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  236. package/src/runtime/memory/lib/pg/process.mjs +5 -7
  237. package/src/runtime/memory/lib/pg/supervisor.mjs +4 -1
  238. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  239. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  240. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  241. package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
  242. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  243. package/src/runtime/office/core/office-write-ledger.mjs +1 -5
  244. package/src/runtime/office/index.mjs +2 -3
  245. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  246. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  247. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  248. package/src/runtime/shared/atomic-file.d.mts +1 -1
  249. package/src/runtime/shared/background-tasks.mjs +6 -1
  250. package/src/runtime/shared/bounded-line-diff.mjs +11 -2
  251. package/src/runtime/shared/browser-launch.mjs +15 -0
  252. package/src/runtime/shared/err-text.mjs +42 -4
  253. package/src/runtime/shared/file-lock.mjs +6 -5
  254. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  255. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  256. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  257. package/src/runtime/shared/model-route-chain.mjs +48 -0
  258. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  259. package/src/runtime/shared/pid-liveness.mjs +12 -0
  260. package/src/runtime/shared/provider-api-key.mjs +6 -0
  261. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  262. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  263. package/src/runtime/shared/quiet-progress.mjs +101 -0
  264. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  265. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  266. package/src/runtime/shared/remote-intent.mjs +2 -42
  267. package/src/runtime/shared/slow-span.mjs +8 -1
  268. package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
  269. package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
  270. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  271. package/src/runtime/shared/tool-result-summary.mjs +16 -2
  272. package/src/runtime/shared/tool-status.mjs +3 -2
  273. package/src/runtime/shared/tool-surface.mjs +2 -3
  274. package/src/runtime/shared/tool-work-units.mjs +22 -15
  275. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  276. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  277. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  278. package/src/runtime/shared/transcript-writer.mjs +14 -4
  279. package/src/runtime/shared/turn-changes.mjs +2 -1
  280. package/src/runtime/shared/turn-snapshot.mjs +11 -3
  281. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  282. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  283. package/src/runtime/shared/worktrees/carry.mjs +6 -4
  284. package/src/runtime/shared/worktrees/contract.mjs +27 -1
  285. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  286. package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
  287. package/src/runtime/shared/worktrees/git-head.mjs +22 -13
  288. package/src/runtime/shared/worktrees/include.mjs +125 -7
  289. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  290. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  291. package/src/runtime/shared/worktrees/manager.mjs +378 -32
  292. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  293. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  294. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  295. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  296. package/src/runtime/terminal-bridge/client.mjs +14 -10
  297. package/src/session-runtime/boot/apis.mjs +7 -1
  298. package/src/session-runtime/boot/config.mjs +2 -0
  299. package/src/session-runtime/boot/facade.mjs +3 -0
  300. package/src/session-runtime/boot/session.mjs +3 -2
  301. package/src/session-runtime/boot/tools.mjs +3 -0
  302. package/src/session-runtime/conversation-import/service.mjs +1 -1
  303. package/src/session-runtime/goal-facade-api.mjs +2 -2
  304. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
  305. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
  306. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
  307. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  308. package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
  309. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
  310. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
  311. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  312. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  313. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  314. package/src/session-runtime/lifecycle/teardown.mjs +7 -16
  315. package/src/session-runtime/media-api.mjs +8 -0
  316. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  317. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  318. package/src/session-runtime/model-route/set-route.mjs +114 -34
  319. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  320. package/src/session-runtime/model-route-api.mjs +4 -2
  321. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  322. package/src/session-runtime/native-web-search.mjs +9 -8
  323. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  324. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  325. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  326. package/src/session-runtime/provider-models.mjs +1 -0
  327. package/src/session-runtime/provider-usage.mjs +4 -0
  328. package/src/session-runtime/route-resolution.mjs +3 -1
  329. package/src/session-runtime/runtime-core.mjs +4 -0
  330. package/src/session-runtime/runtime-facade.mjs +6 -0
  331. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  332. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  333. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  334. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  335. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  336. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  337. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  338. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  339. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  340. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  341. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  342. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  343. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +9 -6
  344. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  345. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  346. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  347. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  348. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  349. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  350. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  351. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  352. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  353. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -9
  354. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  355. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  356. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  357. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  358. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  359. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  360. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  361. package/src/session-runtime/services/agent-tool/worker-index.mjs +28 -8
  362. package/src/session-runtime/services/agent-tool.mjs +4 -0
  363. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  364. package/src/session-runtime/services/provider-admin.mjs +77 -0
  365. package/src/session-runtime/session-create/session-options.mjs +7 -5
  366. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  367. package/src/session-runtime/session-transcript.mjs +4 -5
  368. package/src/session-runtime/session-turn-api.mjs +3 -9
  369. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
  370. package/src/session-runtime/setup-tool/executor.mjs +23 -5
  371. package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
  372. package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
  373. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
  374. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  375. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  376. package/src/session-runtime/turn/side-question-ops.mjs +1 -4
  377. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
  378. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
  379. package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
  380. package/src/session-runtime/turn/turn-run.mjs +1 -36
  381. package/src/session-runtime/usage-stats-api.mjs +4 -1
  382. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  383. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  384. package/src/session-runtime/workspace/project-branches.mjs +28 -36
  385. package/src/session-runtime/workspace/transition-steps.mjs +96 -95
  386. package/src/session-runtime/workspace/transitions.mjs +248 -68
  387. package/src/standalone/channel-transport.mjs +3 -4
  388. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  389. package/src/standalone/daemon-pg-stop.mjs +1 -3
  390. package/src/standalone/daemon-session-control.mjs +88 -0
  391. package/src/standalone/daemon-stored-session-views.mjs +23 -3
  392. package/src/standalone/daemon.mjs +2 -0
  393. package/src/standalone/local-session-runtime.mjs +11 -12
  394. package/src/standalone/session-protocol.mjs +7 -0
  395. package/src/standalone/session-runtime-inline-host.mjs +2 -0
  396. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  397. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  398. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  399. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  400. package/src/standalone/session-service/agent-tree.mjs +28 -2
  401. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  402. package/src/standalone/session-service/entries.mjs +1 -0
  403. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  404. package/src/standalone/session-service/quota-resume.mjs +28 -13
  405. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  406. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  407. package/src/standalone/session-tool-output.mjs +82 -0
  408. package/src/tui/app/app-view.jsx +2 -1
  409. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  410. package/src/tui/app/provider-setup-picker.mjs +15 -3
  411. package/src/tui/app/slash-commands.mjs +6 -0
  412. package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
  413. package/src/tui/components/Spinner.jsx +4 -0
  414. package/src/tui/components/SpinnerByline.jsx +21 -2
  415. package/src/tui/components/status-line/local-line.mjs +10 -2
  416. package/src/tui/dist/index.mjs +478 -251
  417. package/src/tui/session/active-tool-summary.mjs +1 -1
  418. package/src/tui/session/context-state.mjs +0 -3
  419. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  420. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  421. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  422. package/src/tui/session/quota-resume.mjs +140 -61
  423. package/src/tui/session/session-api/commands.mjs +4 -10
  424. package/src/tui/session/session-api/controls.mjs +12 -0
  425. package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
  426. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  427. package/src/tui/session/session-api/lifecycle.mjs +13 -11
  428. package/src/tui/session/session-api/media.mjs +2 -0
  429. package/src/tui/session/session-api/routes.mjs +81 -57
  430. package/src/tui/session/session-api/settings.mjs +3 -3
  431. package/src/tui/session/session-api/worktree.mjs +3 -2
  432. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  433. package/src/tui/session/session-flow/drain.mjs +6 -4
  434. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  435. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  436. package/src/tui/session/session-flow/queue.mjs +1 -1
  437. package/src/tui/session/tool-approval.mjs +17 -8
  438. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  439. package/src/tui/session/tui-steering-persist.mjs +3 -5
  440. package/src/tui/session/turn-quiet.mjs +53 -0
  441. package/src/tui/session/turn-stream.mjs +5 -1
  442. package/src/tui/session/turn.mjs +38 -31
  443. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  444. package/src/tui/spinner-meta.mjs +10 -0
  445. package/src/tui/spinner-verbs.mjs +3 -0
  446. package/src/ui/statusline.mjs +13 -3
  447. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  448. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  449. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  450. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -302
  451. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  452. package/src/session-runtime/turn/share-ops.mjs +0 -77
  453. package/src/tui/session/cross-surface-share.mjs +0 -406
  454. package/src/tui/session/live-share/delta.mjs +0 -153
  455. package/src/tui/session/live-share/mirror.mjs +0 -106
  456. package/src/tui/session/live-share/owner.mjs +0 -254
  457. package/src/tui/session/live-share/retry.mjs +0 -54
  458. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  459. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  460. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  461. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  462. package/src/tui/session/live-share/viewer.mjs +0 -99
  463. package/src/tui/session/live-share/wire.mjs +0 -44
  464. package/src/tui/session/live-share.mjs +0 -154
  465. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -34,6 +34,7 @@ export function createInternalToolExecutor({
34
34
  getWorkspaceApi,
35
35
  getSessionManager,
36
36
  getLifecycleApi,
37
+ executeSessionControl,
37
38
  }) {
38
39
  const handlers = {
39
40
  ...createBridgeToolHandlers({ rt }),
@@ -58,6 +59,7 @@ export function createInternalToolExecutor({
58
59
  getWorkspaceApi,
59
60
  getSessionManager,
60
61
  getLifecycleApi,
62
+ executeSessionControl,
61
63
  }),
62
64
  };
63
65
 
@@ -35,7 +35,6 @@ const SOURCE_RUNTIME_FIELDS = [
35
35
  'toolApprovalHook',
36
36
  '_providerPrefixGuardState',
37
37
  'activeTurnCheckpoint',
38
- 'remoteAttached',
39
38
  'deferredInitialRefreshPending',
40
39
  'pendingGoalReminder',
41
40
  'goalReminderRevision',
@@ -7,7 +7,6 @@ import {
7
7
  isAgentOnlySession,
8
8
  isRootLeadSession,
9
9
  } from '../../runtime/agent/orchestrator/session/store-summary-visibility.mjs';
10
- import { listSessionHeartbeatMtimes } from '../../runtime/agent/orchestrator/session/store/paths-heartbeat.mjs';
11
10
  import {
12
11
  sessionMessageText,
13
12
  isSessionPreviewNoise,
@@ -58,23 +57,25 @@ function previewOf(s) {
58
57
  return { preview, messageCount, realTurnCount };
59
58
  }
60
59
 
61
- export function leadSessionRow(s, heartbeatMtimes) {
62
- // Durable visibility is the catalog boundary. Apply it before the legacy
63
- // lead-shape heuristics so an explicitly agent-only child cannot leak just
64
- // because its owner field looks ordinary.
65
- if (isAgentOnlySession(s)) return null;
60
+ /** `working`: this session's turn is running in the daemon right now. */
61
+ export function leadSessionRow(s, working = false) {
62
+ const agentSession = isAgentOnlySession(s) || isAgentOwner(s);
66
63
  const owner = clean(s.owner || 'user').toLowerCase();
67
64
  // A root Lead can carry Agent ownership plus a self-link after recovery;
68
65
  // it remains an ordinary resumable session, not a child dispatch.
69
- if (!isRootLeadSession(s) && owner && !VISIBLE_OWNERS.includes(owner)) return null;
66
+ if (!agentSession && !isRootLeadSession(s) && owner && !VISIBLE_OWNERS.includes(owner)) return null;
70
67
  const sourceType = clean(s.sourceType || '').toLowerCase();
71
68
  // One-shot `mixdog exec` runs are never resumable conversations.
72
69
  if (sourceType === 'exec') return null;
73
- if (!isLeadShaped(s, owner, sourceType)) return null;
70
+ if (!agentSession && !isLeadShaped(s, owner, sourceType)) return null;
74
71
  const { preview, messageCount, realTurnCount } = previewOf(s);
75
72
  if (!preview && messageCount === 0) return null;
76
73
  return {
77
74
  id: s.id,
75
+ agent: s.agent || null,
76
+ owner,
77
+ visibility: isAgentOnlySession(s) ? 'agent-only' : 'ordinary',
78
+ ownerSessionId: s.ownerSessionId || s.parentSessionId || null,
78
79
  // Durable provenance the desktop uses to tell a real conversation from
79
80
  // resume scratch or synthetic-only rows when no title source survives.
80
81
  ...(realTurnCount === null ? {} : { realTurnCount }),
@@ -91,12 +92,10 @@ export function leadSessionRow(s, heartbeatMtimes) {
91
92
  messageCount,
92
93
  title: cleanSessionPreview(s.title || '', 100),
93
94
  preview,
94
- // Working indicator: the .hb sidecar ALONE is the liveness signal. Its
95
- // deletion at turn end IS the completion signal, so the persisted
96
- // lastHeartbeatAt JSON field (refreshed by the final save) must not be
97
- // folded in — it pinned desktop spinners on for the full 2-minute TTL
98
- // after a turn had already finished.
99
- heartbeatAt: Number(heartbeatMtimes.get(s.id)) || 0,
95
+ // Working indicator: the in-memory runtime state ALONE is the liveness
96
+ // signal. The persisted lastHeartbeatAt JSON field (refreshed by the final
97
+ // save) must not be folded in — it outlives the turn it describes.
98
+ ...(working ? { working: true } : {}),
100
99
  desktopSession: s.desktopSession || null,
101
100
  // Automation origin: lets the desktop group schedule/webhook runner
102
101
  // sessions under the sidebar Automations section instead of Recent.
@@ -108,9 +107,8 @@ export function leadSessionRow(s, heartbeatMtimes) {
108
107
  }
109
108
 
110
109
  export function listLeadSessions(mgr, options = {}) {
111
- const heartbeatMtimes = listSessionHeartbeatMtimes();
112
110
  return mgr
113
111
  .listSessions({ refreshFromStorage: options?.refreshFromStorage === true })
114
- .map((s) => leadSessionRow(s, heartbeatMtimes))
112
+ .map((s) => leadSessionRow(s, mgr.isSessionTurnInFlight?.(s.id) === true))
115
113
  .filter(Boolean);
116
114
  }
@@ -1,18 +1,19 @@
1
1
  /**
2
- * session-switch/session-delete.mjs — deleting a catalogued session together
3
- * with its linked agent children, and releasing the work a closing session
4
- * owns (shared with the context switch).
2
+ * session-switch/session-delete.mjs — deleting one catalogued session (Lead
3
+ * or agent), and releasing the execution work a closing session owns
4
+ * (shared with the context switch).
5
5
  */
6
6
  import { clean } from '../../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
7
7
  import { forgetSessionSearch } from '../../../runtime/session-search/session-search-ingest.mjs';
8
8
  import { leadSessionRow } from '../session-catalog.mjs';
9
- import { getStoreDir } from '../../../runtime/agent/orchestrator/session/store/paths-heartbeat.mjs';
9
+ import { getStoreDir } from '../../../runtime/agent/orchestrator/session/store/session-paths.mjs';
10
10
  import {
11
11
  STORED_SESSION_UNREADABLE,
12
12
  _storedSessionFromFile,
13
13
  } from '../../../runtime/agent/orchestrator/session/store/serialize.mjs';
14
14
  import { SESSION_ID_PATTERN } from '../shared.mjs';
15
15
  import { replacementSessionCwd } from '../../workspace/workspace-state.mjs';
16
+ import { isHistoricalAutomaticClosure } from '../../../runtime/agent/orchestrator/session/historical-session-closure.mjs';
16
17
 
17
18
  export function createSessionDelete(deps, { cancelBackgroundTasks }) {
18
19
  const {
@@ -26,42 +27,22 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
26
27
  invalidatePreSessionToolSurface,
27
28
  } = deps;
28
29
 
29
- // Cancel the work a closing session owns: background tasks, agent workers,
30
- // and its gateway status route.
30
+ // Release this execution session, not independent sessions it delegated to.
31
31
  function releaseSessionWork(sessionId, reason) {
32
32
  try {
33
- cancelBackgroundTasks({ reason, notify: false, callerSessionId: sessionId });
34
- } catch {}
35
- try {
36
- agentTool?.closeAll?.(reason, { callerSessionId: sessionId });
33
+ cancelBackgroundTasks({ reason, notify: false, executionSessionId: sessionId });
37
34
  } catch {}
38
35
  statusRoutes?.clearGatewaySessionRoute?.(sessionId);
39
36
  }
40
37
 
41
- function ownedAgentSessionIds(sessionId) {
42
- try {
43
- const candidates = mgr.listOwnedAgentSessionIds?.(sessionId);
44
- if (!Array.isArray(candidates)) return [];
45
- return [
46
- ...new Set(
47
- candidates
48
- .map(clean)
49
- .filter((childId) => childId && childId !== sessionId && SESSION_ID_PATTERN.test(childId))
50
- ),
51
- ];
52
- } catch {
53
- /* parent deletion remains available if child enumeration fails */
54
- return [];
55
- }
56
- }
57
-
58
38
  // Availability is one strict read of the session's own file, filtered like
59
- // the Lead catalog (an unreadable, foreign, closed or non-Lead record is not
60
- // deletable). No catalog rebuild, no folder scan.
61
- function isAvailableLead(sessionId) {
39
+ // the session catalog (an unreadable, foreign, closed or non-catalogued
40
+ // record is not deletable). No catalog rebuild, no folder scan.
41
+ function isAvailableSession(sessionId) {
62
42
  const stored = _storedSessionFromFile(getStoreDir(), `${sessionId}.json`);
63
- if (!stored || stored === STORED_SESSION_UNREADABLE || stored.closed === true) return false;
64
- return leadSessionRow(stored, new Map()) !== null;
43
+ if (!stored || stored === STORED_SESSION_UNREADABLE) return false;
44
+ if (stored.closed === true && !isHistoricalAutomaticClosure(stored)) return false;
45
+ return leadSessionRow(stored) !== null;
65
46
  }
66
47
 
67
48
  // The deleted task's worktree: the autoCleanup setting decides (clean and
@@ -75,33 +56,25 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
75
56
  async function deleteSession(id) {
76
57
  const sessionId = clean(id);
77
58
  if (!sessionId || !SESSION_ID_PATTERN.test(sessionId)) return false;
78
- if (!isAvailableLead(sessionId)) return false;
79
- const childIds = ownedAgentSessionIds(sessionId);
59
+ if (!isAvailableSession(sessionId)) return false;
80
60
  const current = getSession();
81
61
  const cleanupReason = 'desktop-session-delete';
82
62
  if (current?.id !== sessionId) {
83
63
  // A turn can still be running in a session that is no longer current.
84
64
  // Stop its runtime first (controller abort, shells, generation bump) and
85
- // release its lead row, agents and tasks, so nothing can write it back.
65
+ // release its worker row and its own background tasks, so nothing can
66
+ // write it back. Sessions it delegated to are independent and keep running.
86
67
  if (mgr.closeSession(sessionId, cleanupReason, { tombstone: false }) !== true) return false;
87
68
  agentTool?.forgetLeadSession?.(sessionId);
88
69
  releaseSessionWork(sessionId, cleanupReason);
89
70
  const deleted = mgr.deleteSession(sessionId, { fenceWrites: true }) === true;
90
71
  if (!deleted) return false;
91
72
  void forgetSessionSearch(sessionId);
92
- // The parent is already irreversibly gone, so child cleanup is
93
- // best-effort and idempotent. Any vetoed child becomes sweep-eligible
94
- // because its retained-parent proof disappeared with the parent.
95
- for (const childId of childIds) {
96
- try {
97
- mgr.deleteSession(childId, { fenceWrites: true });
98
- } catch {}
99
- }
100
73
  void releaseDeletedWorktree(sessionId);
101
74
  return true;
102
75
  }
103
- // Leaving a worktree-bound Lead: the replacement starts in the Project
104
- // folder, and the worktree can go once nothing runs in it.
76
+ // Leaving a worktree-bound current session: the replacement starts in the
77
+ // Project folder, and the worktree can go once nothing runs in it.
105
78
  const projectFolder = replacementSessionCwd(current);
106
79
  releaseSessionWork(sessionId, cleanupReason);
107
80
  // Active sessions retain a tombstone until the normal sweep. Unlinking
@@ -113,14 +86,6 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
113
86
  mgr.fenceSessionWrites?.(sessionId);
114
87
  agentTool?.forgetLeadSession?.(sessionId);
115
88
  void forgetSessionSearch(sessionId);
116
- // Active parent deletion uses the same durable tombstone boundary for
117
- // every linked child. Their files then mature with the parent instead of
118
- // disappearing while the parent task is still retained.
119
- for (const childId of childIds) {
120
- try {
121
- mgr.closeSession(childId, cleanupReason, { tombstone: true });
122
- } catch {}
123
- }
124
89
  setSession(null);
125
90
  if (projectFolder) await deps.applyResolvedCwd?.(projectFolder);
126
91
  invalidateContextStatusCache();
@@ -4,7 +4,7 @@
4
4
  * session-switch/: session-delete (delete + work release), context-switch
5
5
  * (switch + new), resume.
6
6
  */
7
- import { getStoreDir } from '../../runtime/agent/orchestrator/session/store/paths-heartbeat.mjs';
7
+ import { getStoreDir } from '../../runtime/agent/orchestrator/session/store/session-paths.mjs';
8
8
  import { toolSpecForMode } from '../../runtime/agent/orchestrator/runtime-core/effort.mjs';
9
9
  import { listLeadSessions } from './session-catalog.mjs';
10
10
  import { createSessionDelete } from './session-switch/session-delete.mjs';
@@ -12,7 +12,11 @@ export { SESSION_ID_PATTERN } from '../../runtime/agent/orchestrator/runtime-cor
12
12
  // message there, not yet in session.messages, so it must also be checked or a
13
13
  // first-turn exit could still burn a real session.
14
14
  export function isScratchConversation(messages, liveTurnMessages) {
15
- return !hasUserConversationMessage(messages) && !hasUserConversationMessage(liveTurnMessages);
15
+ return [messages, liveTurnMessages].every(
16
+ (items) =>
17
+ !hasUserConversationMessage(items) &&
18
+ !(Array.isArray(items) && items.some((message) => message?.meta?.transcript?.completion))
19
+ );
16
20
  }
17
21
 
18
22
  export function isScratchSession(session) {
@@ -22,11 +26,6 @@ export function isScratchSession(session) {
22
26
  export function createSurfaceSessionCloser(mgr) {
23
27
  return function closeSurfaceSession(session, reason, options) {
24
28
  if (!session?.id) return false;
25
- // A remote-attached session is only a viewer handle owned by this surface.
26
- // Closing it through the shared manager bumps the durable generation and
27
- // invalidates the real owner's in-flight turn. Viewer exits therefore
28
- // detach locally; only the process that owns the runtime may close it.
29
- if (session.remoteAttached === true) return true;
30
29
  return mgr.closeSession(session.id, reason, options);
31
30
  };
32
31
  }
@@ -60,21 +60,22 @@ export function closeOwnSession(deps, closeSurfaceSession, reason) {
60
60
  return ok;
61
61
  }
62
62
 
63
- /** Plant the ordinary manager/store tombstone barrier for a canonical
64
- * child session without running whole-process teardown. */
65
- export function closeCanonicalSession(deps, reason = 'canonical-session-close') {
63
+ /** Fence a canonical runtime without deleting its conversation.
64
+ * Explicit deletion may request a tombstone; blank scratch follows ordinary policy. */
65
+ export function closeCanonicalSession(deps, reason = 'canonical-session-close', options = {}) {
66
66
  const { getSession, setSession, mgr, invalidateContextStatusCache, beginCanonicalClose, finishCanonicalClose } = deps;
67
67
  // Already terminal: closing is idempotent and keeps the address.
68
68
  if (deps.isCanonicallyClosed?.() === true) return true;
69
69
  const session = getSession?.();
70
- if (!session?.id || session.remoteAttached === true) return false;
70
+ if (!session?.id) return false;
71
71
  // Fence execution admission BEFORE the manager close: that close cancels the
72
72
  // session's shells synchronously, and their completions must not be able to
73
73
  // enqueue model work or create a conversation.
74
74
  const fence = beginCanonicalClose?.(session.id);
75
75
  let closed = false;
76
76
  try {
77
- closed = mgr.closeSession(session.id, reason, { tombstone: true }) === true;
77
+ closed =
78
+ mgr.closeSession(session.id, reason, { tombstone: options.tombstone ?? isScratchSession(session) }) === true;
78
79
  } finally {
79
80
  // Terminal after a durable close; admission restored when it failed.
80
81
  finishCanonicalClose?.(fence, closed);
@@ -13,7 +13,7 @@ import { abortRuntime, closeCanonicalSession, closeOwnSession, dispatchSessionEn
13
13
  import { settleAll, settleDetached, startRuntimeStops, startWorkStops } from './teardown/runtime-stops.mjs';
14
14
 
15
15
  const CLOSE_ALL_DEADLINE_MS = 5000;
16
- const PROCESS_EXIT_REASON =/exit|quit|shutdown|sighup|sigint|sigterm/;
16
+ const PROCESS_EXIT_REASON = /exit|quit|shutdown|sighup|sigint|sigterm/;
17
17
  const WARMUP_TIMER_KEYS = [
18
18
  'providerSetupWarmupTimer',
19
19
  'providerWarmupTimer',
@@ -114,7 +114,7 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
114
114
  // A task that dies for a reason its owner never asked for must still be reported.
115
115
  cancelBackgroundTasks(
116
116
  scope.scopedTeardown
117
- ? { reason, notify: true, callerSessionId: scope.closingSessionId }
117
+ ? { reason, notify: true, executionSessionId: scope.closingSessionId }
118
118
  : { reason, notify: false }
119
119
  );
120
120
  } catch {}
@@ -196,24 +196,15 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
196
196
  // session-pinned intent so the resumed session can reclaim it.
197
197
  preserveRemoteIntent: true,
198
198
  });
199
- // Agent workers die with a REAL teardown only (process exit, explicit
200
- // close). A keepBackgroundWork dispose (daemon idle eviction) reclaims
201
- // memory and must leave workers/rows for the re-materialized owner.
202
- // Scoped teardown closes only THIS session's workers — the worker index
203
- // is shared across every Lead in the process.
199
+ // Only process-wide teardown closes delegated sessions. Session-local
200
+ // disposal already stopped its own execution work above.
204
201
  let closing = null;
205
202
  while (indexDisposal) await indexDisposal;
206
- if (scope.teardownReapsWork) {
207
- // Every close runs its OWN scope's closeAll: a scoped close for one Lead
208
- // never stands in for a process-wide close. Closing produces final index
209
- // writes (settled rows, tombstones); the deadline only bounds how long
210
- // teardown waits and does not stop the close.
203
+ if (scope.teardownReapsWork && !scope.scopedTeardown) {
211
204
  const settled = () => {
212
205
  outstandingCloses.delete(closing);
213
206
  };
214
- closing = new Promise((resolve) =>
215
- resolve(agentTool.closeAll(reason, scope.scopedTeardown ? { callerSessionId: scope.closingSessionId } : {}))
216
- ).then(settled, settled);
207
+ closing = new Promise((resolve) => resolve(agentTool.closeAll(reason, {}))).then(settled, settled);
217
208
  outstandingCloses.add(closing);
218
209
  try {
219
210
  await withTeardownDeadline(closing, CLOSE_ALL_DEADLINE_MS, false);
@@ -259,7 +250,7 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
259
250
  }
260
251
 
261
252
  return {
262
- closeCanonicalSession: (reason) => closeCanonicalSession(deps, reason),
253
+ closeCanonicalSession: (reason, options) => closeCanonicalSession(deps, reason, options),
263
254
  close,
264
255
  abort: (reason) => abortRuntime(deps, reason),
265
256
  };
@@ -52,6 +52,14 @@ export function createMediaApi() {
52
52
  async setMediaDefault(input) {
53
53
  return (await defaults()).setMediaDefault(input || {});
54
54
  },
55
+ // Settings → Built-in → Media generation: the default generator the media
56
+ // tool uses per kind when the chat does not name one.
57
+ async getMediaPins() {
58
+ return (await defaults()).getMediaPins();
59
+ },
60
+ async setMediaPin(input) {
61
+ return (await defaults()).setMediaPin(input || {});
62
+ },
55
63
  async startMediaJob(input) {
56
64
  return (await jobs()).startMediaJob(input || {});
57
65
  },
@@ -0,0 +1,60 @@
1
+ /**
2
+ * route-ownership.mjs — who a route selection belongs to.
3
+ *
4
+ * A runtime holds one conversation at a time; reset, resume, new-session and
5
+ * close replace it, or leave none. Every such transition advances the session
6
+ * generation. A selection captures the generation when it is enqueued and
7
+ * holds a lease on it: once the generation has moved, the selection's route
8
+ * side effects (adopt, refresh completion, pending registration, session
9
+ * updates, display rollback) are no-ops, and the current route stands.
10
+ */
11
+
12
+ const sessionOwner = (session) => (session ? (session.id ?? session) : null);
13
+
14
+ /** Make `holder.session` advance `holder.sessionGeneration` whenever another
15
+ * conversation (or none) is installed. Re-installing the same conversation
16
+ * (a refreshed object for the same id) is not a transition. */
17
+ export function trackSessionGeneration(holder) {
18
+ let session = holder.session ?? null;
19
+ let generation = 0;
20
+ Object.defineProperty(holder, 'session', {
21
+ enumerable: true,
22
+ configurable: true,
23
+ get: () => session,
24
+ set: (next) => {
25
+ const installed = next ?? null;
26
+ if (sessionOwner(installed) !== sessionOwner(session)) generation += 1;
27
+ session = installed;
28
+ },
29
+ });
30
+ Object.defineProperty(holder, 'sessionGeneration', {
31
+ enumerable: true,
32
+ configurable: true,
33
+ get: () => generation,
34
+ });
35
+ return holder;
36
+ }
37
+
38
+ /** A selection's hold on the generation it was enqueued under. The token is
39
+ * compared strictly; an absent token is a token like any other. */
40
+ export function openRouteLease(getGeneration, token = getGeneration()) {
41
+ const valid = () => getGeneration() === token;
42
+ return {
43
+ token,
44
+ valid,
45
+ /** The one way a selection touches route or session state: `effect` runs
46
+ * only if the lease holds at this very point, else `otherwise()` stands.
47
+ * Anything after an `await` (even one that resolved without error) must
48
+ * come through here, since a transition can run between the awaited call
49
+ * returning and its caller continuing. */
50
+ run: (effect, otherwise) => (valid() ? effect() : otherwise()),
51
+ };
52
+ }
53
+
54
+ /** A selection that is not addressed to a conversation (a default for new
55
+ * sessions) belongs to no session and survives every transition. */
56
+ export const UNOWNED_LEASE = Object.freeze({
57
+ token: undefined,
58
+ valid: () => true,
59
+ run: (effect) => effect(),
60
+ });
@@ -35,12 +35,13 @@ export function createRoutePersistence(deps) {
35
35
  hasSecrets: getConfigHasSecrets(),
36
36
  });
37
37
  },
38
- persistAdoptedModelSettings(route, { keepMainModel = false } = {}) {
38
+ persistAdoptedModelSettings(route, { keepMainModel } = {}) {
39
39
  // saveModelSettings is in-memory only. persistLeadRoute debounce-writes
40
40
  // the adopted config (including modelSettings). If the lead preset cannot
41
41
  // be normalized, still debounce-persist so effort/fast are not memory-only.
42
42
  const leadRoute =
43
- keepMainModel || tunesNonMainModel(getRoute(), route, resolveRoute(getConfig(), {}))
43
+ keepMainModel === true ||
44
+ (keepMainModel !== false && tunesNonMainModel(getRoute(), route, resolveRoute(getConfig(), {})))
44
45
  ? null
45
46
  : persistLeadRoute(route);
46
47
  if (!leadRoute) saveConfigAndAdopt(getConfig());