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
@@ -11,6 +11,23 @@ import {
11
11
  readStoredGoalSnapshot,
12
12
  } from '../runtime/agent/orchestrator/runtime-core/goal-runtime.mjs';
13
13
 
14
+ /** Catalog rows with the daemon's in-memory turn activity overlaid: `working`
15
+ * on a session whose own turn is in flight, `agentWorking` on a Lead with an
16
+ * in-flight Agent session. Every session runs in this process, so the runtime
17
+ * state is the whole answer — storage carries no liveness. */
18
+ async function withRuntimeActivity(rows) {
19
+ // The import-free leaf holding the runtime map: no session manager graph.
20
+ const { inFlightSessionActivity } = await import('../runtime/agent/orchestrator/session/manager/runtime-state.mjs');
21
+ const { working, agentWorking } = inFlightSessionActivity();
22
+ if (!working.size) return rows;
23
+ return rows.map((row) => {
24
+ const own = working.has(row?.id);
25
+ const agents = agentWorking.has(row?.id);
26
+ if (!own && !agents) return row;
27
+ return { ...row, ...(own ? { working: true } : {}), ...(agents ? { agentWorking: true } : {}) };
28
+ });
29
+ }
30
+
14
31
  export function createStoredSessionViews({ desktopRuntime, dataDir }) {
15
32
  return {
16
33
  // Settled identity of the files a stored projection is built from; the
@@ -86,11 +103,14 @@ export function createStoredSessionViews({ desktopRuntime, dataDir }) {
86
103
  // ignored, full array). An authoritative refresh is never paged.
87
104
  const page = options.page && typeof options.page === 'object' ? options.page : null;
88
105
  if (page && !refreshFromStorage && store.listStoredSessionSummaryPage) {
89
- return store.listStoredSessionSummaryPage({ limit: page.limit, cursor: page.cursor });
106
+ const listed = await store.listStoredSessionSummaryPage({ limit: page.limit, cursor: page.cursor });
107
+ return { ...listed, sessions: await withRuntimeActivity(listed.sessions) };
90
108
  }
91
109
  // The async listing may answer from the session catalog DB.
92
- if (store.listStoredSessionSummariesAsync) return store.listStoredSessionSummariesAsync({ refreshFromStorage });
93
- return store.listStoredSessionSummaries({ refreshFromStorage });
110
+ const rows = store.listStoredSessionSummariesAsync
111
+ ? await store.listStoredSessionSummariesAsync({ refreshFromStorage })
112
+ : store.listStoredSessionSummaries({ refreshFromStorage });
113
+ return withRuntimeActivity(rows);
94
114
  },
95
115
  };
96
116
  }
@@ -91,6 +91,7 @@ import { createLagProfiler } from './daemon-lag-profiler.mjs';
91
91
  import { createChannelsRuntimeLoader } from './daemon-channels-loader.mjs';
92
92
  import { createDesktopRuntime } from './daemon-desktop-runtime.mjs';
93
93
  import { createCanonicalAgentControl } from './daemon-agent-control.mjs';
94
+ import { createSessionControl } from './daemon-session-control.mjs';
94
95
  import { flushAllIndexWrites } from '../session-runtime/services/agent-tool/index-write-queue.mjs';
95
96
  import { registerAutomationAgentTool } from '../session-runtime/automation-agents.mjs';
96
97
  import {
@@ -913,6 +914,7 @@ async function main() {
913
914
  log,
914
915
  measureBootPhase: bootPhases.measure,
915
916
  executeAgentControl: agentControl.execute,
917
+ executeSessionControl: createSessionControl({ getSessionService: () => sessionService }),
916
918
  });
917
919
  // Codex-style runtime: daemon routing and independent async session actors
918
920
  // share one V8 isolate and module graph. CPU-heavy work stays in bounded
@@ -15,6 +15,7 @@ import { createGoalContinuation } from '../tui/session/goal-continuation.mjs';
15
15
  import { createToolApproval } from '../tui/session/tool-approval.mjs';
16
16
  import { createToolCardResults } from '../tui/session/tool-card-results.mjs';
17
17
  import { createAgentJobFeed } from '../tui/session/agent-job-feed.mjs';
18
+ import { createWorktreeSetupNotices } from '../tui/session/worktree-setup-notice.mjs';
18
19
  import { createContextState } from '../tui/session/context-state.mjs';
19
20
  import { createSessionFlow } from '../tui/session/session-flow.mjs';
20
21
  import { createRunTurn } from '../tui/session/turn.mjs';
@@ -28,7 +29,7 @@ import { createActiveToolTracker } from '../tui/session/active-tool-summary.mjs'
28
29
  import { createTranscriptStore } from '../tui/session/transcript-store.mjs';
29
30
  import { createTranscriptIntake } from '../tui/session/transcript-intake.mjs';
30
31
  import { createNoticeSurface } from '../tui/session/notice-surface.mjs';
31
- import { attachCrossSurfaceShare } from '../tui/session/cross-surface-share.mjs';
32
+ import { rearmGoalContinuationOnSessionBoundaries } from '../tui/session/goal-continuation/session-boundary.mjs';
32
33
  import { createTranscriptRouteMetadata } from '../runtime/shared/transcript-metadata.mjs';
33
34
  import { formatDoctorReport, runDoctorChecks } from '../tui/app/doctor.mjs';
34
35
  // tuiDebug is an opt-in diagnostic trace for the hang chain (runTurn start/end,
@@ -109,7 +110,6 @@ export { parseBackgroundTaskEnvelope } from '../tui/session/agent-envelope.mjs';
109
110
  */
110
111
  export function createRuntimePulse({
111
112
  flags,
112
- liveShareMirroring,
113
113
  getState,
114
114
  getPublishedState,
115
115
  set,
@@ -138,13 +138,6 @@ export function createRuntimePulse({
138
138
  const pulse = () => {
139
139
  if (flags.disposed) return;
140
140
  if (flags.pendingSessionReset) return;
141
- // Attached viewer with a live pipe: the owner's frames are authoritative
142
- // for stats/agent/tool state. Recomputing them locally here would stomp
143
- // the mirror with this process's empty registries every 2s.
144
- if (liveShareMirroring()) {
145
- publishChanged({ ...routeState() });
146
- return;
147
- }
148
141
  syncContextStats({ allowEstimated: true });
149
142
  publishChanged({
150
143
  ...routeState(),
@@ -177,6 +170,7 @@ export async function createLocalSessionRuntime({
177
170
  sessionProfile,
178
171
  worktree,
179
172
  executeAgentControl,
173
+ executeSessionControl,
180
174
  } = {}) {
181
175
  const startedAt = performance.now();
182
176
  bootProfile('session:create:start', { provider: providerName, model, toolMode, remote });
@@ -209,6 +203,7 @@ export async function createLocalSessionRuntime({
209
203
  // Session creation worktree intent; consumed by the workspace transition scope.
210
204
  ...(worktree && typeof worktree === 'object' ? { worktree } : {}),
211
205
  ...(typeof executeAgentControl === 'function' ? { executeAgentControl } : {}),
206
+ ...(typeof executeSessionControl === 'function' ? { executeSessionControl } : {}),
212
207
  });
213
208
  bootProfile('session:create:runtime-ready', { ms: (performance.now() - startedAt).toFixed(1) });
214
209
  const runtimeCwd = runtime.cwd || process.cwd();
@@ -322,7 +317,6 @@ export async function createLocalSessionRuntime({
322
317
  );
323
318
  const runtimePulse = createRuntimePulse({
324
319
  flags,
325
- liveShareMirroring: () => bag.liveShareMirroring?.() === true,
326
320
  getState,
327
321
  getPublishedState,
328
322
  set,
@@ -374,9 +368,14 @@ export async function createLocalSessionRuntime({
374
368
  itemIndexById,
375
369
  });
376
370
  lifecycle.unsubscribeRuntimeNotifications = subscribeRuntimeNotifications();
371
+ if (typeof runtime.onWorktreeSetup === 'function') {
372
+ lifecycle.unsubscribeWorktreeSetup = runtime.onWorktreeSetup(
373
+ createWorktreeSetupNotices({ pushItem, patchItem, nextId })
374
+ );
375
+ }
377
376
  if (typeof runtime.onAgentStatusChange === 'function') {
378
377
  lifecycle.unsubscribeAgentStatus = runtime.onAgentStatusChange(() => {
379
- if (flags.disposed || flags.pendingSessionReset || bag.liveShareMirroring?.()) return;
378
+ if (flags.disposed || flags.pendingSessionReset) return;
380
379
  set({ ...agentStatusState({ force: true }) });
381
380
  bag.scheduleGoalContinuation?.();
382
381
  });
@@ -474,7 +473,7 @@ export async function createLocalSessionRuntime({
474
473
  bag.runTurn = createRunTurn(bag);
475
474
  bag.doctor = { runDoctorChecks, formatDoctorReport };
476
475
  const api = createSessionApi(bag);
477
- attachCrossSurfaceShare({ runtime, api, bag, flags, getState, getPublishedState, listeners, set });
476
+ rearmGoalContinuationOnSessionBoundaries({ api, bag });
478
477
  void Promise.resolve(bag.restoreLeadSteeringFromDisk())
479
478
  .catch(() => {})
480
479
  .finally(() => {
@@ -6,6 +6,8 @@
6
6
  */
7
7
 
8
8
  export const SESSION_READ_ACTIONS = Object.freeze([
9
+ 'inspectProjectBranch',
10
+ 'isSessionTerminal',
9
11
  'contextStatus',
10
12
  'getAgentDefinition',
11
13
  'getAutoClear',
@@ -18,6 +20,7 @@ export const SESSION_READ_ACTIONS = Object.freeze([
18
20
  'getDisabledSkills',
19
21
  'getMediaDefault',
20
22
  'getMediaJob',
23
+ 'getMediaPins',
21
24
  'getMcpServerConfig',
22
25
  'getMcpOAuthLoginStatus',
23
26
  'getOnboardingStatus',
@@ -71,6 +74,7 @@ export const SESSION_READ_ACTIONS = Object.freeze([
71
74
  'listProviders',
72
75
  'listWebSearchModels',
73
76
  'listThemes',
77
+ 'listShellJobs',
74
78
  'listWorkflows',
75
79
  'mcpStatus',
76
80
  'pluginsStatus',
@@ -194,6 +198,7 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
194
198
  'startLocalProviderModelMaintenance',
195
199
  'deleteLocalProviderModel',
196
200
  'setMediaDefault',
201
+ 'setMediaPin',
197
202
  'setModel',
198
203
  'setOutputStyle',
199
204
  'setPluginEnabled',
@@ -219,6 +224,7 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
219
224
  'startConversationImport',
220
225
  'startMediaJob',
221
226
  'stopShellJob',
227
+ 'releaseShellJob',
222
228
  'switchContext',
223
229
  'taskControl',
224
230
  'testWebhook',
@@ -233,6 +239,7 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
233
239
  'selectBranch',
234
240
  'selectProjectBranch',
235
241
  'mergeProjectBranch',
242
+ 'manageProjectBranch',
236
243
  'requestWorktree',
237
244
  'mergeWorkspace',
238
245
  'removeWorktree',
@@ -27,6 +27,7 @@ export function createInlineSessionRuntimeHost({
27
27
  await keychain.prewarmSecrets();
28
28
  },
29
29
  executeAgentControl = null,
30
+ executeSessionControl = null,
30
31
  } = {}) {
31
32
  let closed = false;
32
33
  let closePromise = null;
@@ -59,6 +60,7 @@ export function createInlineSessionRuntimeHost({
59
60
  ...options,
60
61
  ...(options.cwd ? {} : { cwd }),
61
62
  ...(typeof executeAgentControl === 'function' ? { executeAgentControl } : {}),
63
+ ...(typeof executeSessionControl === 'function' ? { executeSessionControl } : {}),
62
64
  });
63
65
  if (closed) {
64
66
  try {
@@ -24,7 +24,7 @@ export function createAgentCancellation({
24
24
  log,
25
25
  rememberCancelTranscript,
26
26
  }) {
27
- const agentCancelRuns = new Map();
27
+ const agentCloseRuns = new Map();
28
28
 
29
29
  /** The runtime entry that can close this descriptor: the live owner, else a
30
30
  * freshly loaded one (null when loading fails, which is logged). */
@@ -44,66 +44,108 @@ export function createAgentCancellation({
44
44
  }
45
45
  };
46
46
 
47
- function cancelAgentTree(sessionId, reason = 'agent session cancelled') {
48
- const id = String(sessionId || '').trim();
49
- if (!id) return Promise.resolve(false);
50
- const active = agentCancelRuns.get(id);
47
+ function closeOne(id, reason, options) {
48
+ const active = agentCloseRuns.get(id);
51
49
  if (active) return active;
52
50
  let run;
53
- run = (async () => {
54
- await rehydrateAgentSessions();
55
- cancelBackgroundTasks({
56
- surface: 'agent',
57
- callerSessionId: id,
58
- reason,
51
+ run = Promise.resolve()
52
+ .then(async () => {
53
+ cancelBackgroundTasks({
54
+ surface: 'agent',
55
+ callerSessionId: id,
56
+ reason,
57
+ });
58
+ cancelOwnAgentTasks(id, reason);
59
+ const descriptor = registry.get(id);
60
+ if (!descriptor) return false;
61
+ if ((await sessionOwner(id)?.runtime?.isSessionTerminal?.()) === true) return true;
62
+ const entry = await closableEntry(id, descriptor);
63
+ const closeCanonical = entry?.runtime?.closeCanonicalSession;
64
+ if (typeof closeCanonical !== 'function') {
65
+ throw new TypeError('session runtime must implement closeCanonicalSession');
66
+ }
67
+ // The close clears the transcript: capture a running turn's transcript
68
+ // first so the cancelled turn still hands off its partial output.
69
+ if (descriptor.status === 'running') {
70
+ try {
71
+ const { messages } = await entry.runtime.readModelMessages(0);
72
+ rememberCancelTranscript(id, messages);
73
+ } catch (error) {
74
+ log(`agent cancel transcript read failed session=${id}: ${error?.message || error}`);
75
+ }
76
+ }
77
+ const closed = await closeCanonical.call(entry.runtime, reason, { tombstone: options.tombstone === true });
78
+ if (closed !== true) throw new Error(`agent session ${id} could not be durably closed`);
79
+ descriptor.closed = options.tombstone === true;
80
+ descriptor.status = descriptor.closed ? 'closed' : 'cancelled';
81
+ descriptor.stage = descriptor.status;
82
+ descriptor.updatedAt = Date.now();
83
+ return true;
84
+ })
85
+ .finally(() => {
86
+ if (agentCloseRuns.get(id) === run) agentCloseRuns.delete(id);
59
87
  });
60
- const children = registry.childrenOf(id);
61
- await Promise.all(children.map((childId) => cancelAgentTree(childId, reason)));
62
- cancelOwnAgentTasks(id, reason);
63
- const descriptor = registry.get(id);
64
- if (!descriptor) return children.length > 0;
65
- if (descriptor.closed) return true;
66
- const entry = await closableEntry(id, descriptor);
67
- const closeCanonical = entry?.runtime?.closeCanonicalSession;
68
- if (typeof closeCanonical !== 'function') {
69
- throw new TypeError('session runtime must implement closeCanonicalSession');
70
- }
71
- // The close clears the transcript: capture a running turn's transcript
72
- // first so the cancelled turn still hands off its partial output.
73
- if (descriptor.status === 'running') {
88
+ agentCloseRuns.set(id, run);
89
+ return run;
90
+ }
91
+
92
+ async function cancelAgentTree(sessionId, reason = 'agent session cancelled', options = {}) {
93
+ const id = String(sessionId || '').trim();
94
+ if (!id) return false;
95
+ await rehydrateAgentSessions();
96
+ const seen = new Set();
97
+ const ordered = [];
98
+ const visit = (current) => {
99
+ if (seen.has(current)) return;
100
+ seen.add(current);
101
+ for (const child of registry.childrenOf(current)) visit(child);
102
+ ordered.push(current);
103
+ };
104
+ visit(id);
105
+ const release = registry.beginCancellation(ordered);
106
+ try {
107
+ let closed = false;
108
+ const failures = [];
109
+ // Descendant-first, one at a time; a failed member never skips the rest.
110
+ for (const current of ordered) {
74
111
  try {
75
- const { messages } = await entry.runtime.readModelMessages(0);
76
- rememberCancelTranscript(id, messages);
112
+ closed = (await closeOne(current, reason, options)) || closed;
77
113
  } catch (error) {
78
- log(`agent cancel transcript read failed session=${id}: ${error?.message || error}`);
114
+ log(`agent cancel failed session=${current}: ${error?.message || error}`);
115
+ failures.push(error);
79
116
  }
80
117
  }
81
- const closed = await closeCanonical.call(entry.runtime, reason);
82
- if (closed !== true) throw new Error(`agent session ${id} could not be durably closed`);
83
- descriptor.closed = true;
84
- descriptor.status = 'closed';
85
- descriptor.stage = 'closed';
86
- descriptor.updatedAt = Date.now();
87
- return true;
88
- })().finally(() => {
89
- if (agentCancelRuns.get(id) === run) agentCancelRuns.delete(id);
90
- });
91
- agentCancelRuns.set(id, run);
92
- return run;
118
+ if (failures.length === 1) throw failures[0];
119
+ if (failures.length) {
120
+ const details = failures.map((error) => error?.message || String(error)).join('; ');
121
+ throw new AggregateError(
122
+ failures,
123
+ `agent tree cancel failed for ${failures.length} of ${ordered.length} sessions: ${details}`
124
+ );
125
+ }
126
+ return closed;
127
+ } finally {
128
+ release();
129
+ }
93
130
  }
94
131
 
95
132
  async function cancelAgentDescendants(parentSessionId, reason = 'parent session cancelled') {
96
133
  await rehydrateAgentSessions();
97
134
  const parentId = String(parentSessionId || '');
98
- cancelBackgroundTasks({
99
- surface: 'agent',
100
- callerSessionId: parentId,
101
- reason,
102
- });
103
- const children = registry.childrenOf(parentId);
104
- if (!children.length) return false;
105
- await Promise.all(children.map((childId) => cancelAgentTree(childId, reason)));
106
- return true;
135
+ const release = registry.beginCancellation([parentId]);
136
+ try {
137
+ cancelBackgroundTasks({
138
+ surface: 'agent',
139
+ callerSessionId: parentId,
140
+ reason,
141
+ });
142
+ const children = registry.childrenOf(parentId);
143
+ if (!children.length) return false;
144
+ await Promise.all(children.map((childId) => cancelAgentTree(childId, reason)));
145
+ return true;
146
+ } finally {
147
+ release();
148
+ }
107
149
  }
108
150
 
109
151
  return { cancelAgentTree, cancelAgentDescendants };
@@ -3,11 +3,12 @@
3
3
  // caller's spec, creation of the runtime behind it, and the descriptor linked
4
4
  // into the agent registry. Running a turn on that child is ./agent-turns.mjs.
5
5
 
6
- export function createAgentChildFactory({ registry, rehydrateAgentSessions, createSession }) {
6
+ export function createAgentChildFactory({ registry, rehydrateAgentSessions, createSession, entryForSession }) {
7
7
  return async function createAgentChild({ spec = {}, tag = null } = {}) {
8
8
  await rehydrateAgentSessions();
9
9
  const parentSessionId = String(spec.parentSessionId || '').trim();
10
10
  if (!parentSessionId) throw new TypeError('agent child parentSessionId is required');
11
+ const parentEpoch = registry.assertAdmission(parentSessionId);
11
12
  const ownerSessionId = String(
12
13
  spec.ownerSessionId || registry.get(parentSessionId)?.ownerSessionId || parentSessionId
13
14
  );
@@ -29,6 +30,7 @@ export function createAgentChildFactory({ registry, rehydrateAgentSessions, crea
29
30
  sourceType: spec.sourceType || 'agent',
30
31
  sourceName: spec.sourceName || spec.agent || 'agent',
31
32
  clientHostPid: spec.clientHostPid || null,
33
+ ...(preset.fallbacks !== undefined ? { routeFallbacks: preset.fallbacks } : {}),
32
34
  };
33
35
  const created = await createSession({
34
36
  cwd: spec.cwd || process.cwd(),
@@ -45,6 +47,22 @@ export function createAgentChildFactory({ registry, rehydrateAgentSessions, crea
45
47
  toolMode: 'full',
46
48
  sessionProfile,
47
49
  });
50
+ try {
51
+ registry.assertAdmission(parentSessionId, parentEpoch);
52
+ } catch (error) {
53
+ // The parent was cancelled while the runtime was being created: close it
54
+ // like any cancelled child instead of leaving it unlinked and open.
55
+ try {
56
+ const entry = await entryForSession?.(created.sessionId, {
57
+ cwd: spec.cwd || process.cwd(),
58
+ provider,
59
+ model,
60
+ toolMode: 'full',
61
+ });
62
+ await entry?.runtime?.closeCanonicalSession?.('parent cancelled during agent creation', { tombstone: false });
63
+ } catch {}
64
+ throw error;
65
+ }
48
66
  const descriptor = registry.linkAgentDescriptor({
49
67
  id: created.sessionId,
50
68
  ...sessionProfile,
@@ -6,6 +6,8 @@ export const SESSION_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
6
6
  export function createAgentRegistry() {
7
7
  const agentSessions = new Map();
8
8
  const agentChildren = new Map();
9
+ const cancellationCounts = new Map();
10
+ const cancellationEpochs = new Map();
9
11
 
10
12
  function linkAgentDescriptor(descriptor) {
11
13
  const sessionId = String(descriptor?.id || '').trim();
@@ -54,6 +56,27 @@ export function createAgentRegistry() {
54
56
  }
55
57
 
56
58
  return {
59
+ assertAdmission(id, epoch = cancellationEpochs.get(id) || 0) {
60
+ if (cancellationCounts.has(id) || (cancellationEpochs.get(id) || 0) !== epoch) {
61
+ throw new Error(`agent session ${id} was cancelled during admission`);
62
+ }
63
+ return epoch;
64
+ },
65
+ beginCancellation(ids) {
66
+ for (const id of ids) {
67
+ cancellationCounts.set(id, (cancellationCounts.get(id) || 0) + 1);
68
+ cancellationEpochs.set(id, (cancellationEpochs.get(id) || 0) + 1);
69
+ }
70
+ return () => {
71
+ for (const id of ids) {
72
+ const remaining = (cancellationCounts.get(id) || 0) - 1;
73
+ if (remaining > 0) cancellationCounts.set(id, remaining);
74
+ else cancellationCounts.delete(id);
75
+ }
76
+ };
77
+ },
78
+ isCancelling: (id) => cancellationCounts.has(id),
79
+ cancellationEpoch: (id) => cancellationEpochs.get(id) || 0,
57
80
  linkAgentDescriptor,
58
81
  agentDescendantSessionIds,
59
82
  get: (sessionId) => agentSessions.get(String(sessionId || '').trim()),
@@ -68,6 +91,8 @@ export function createAgentRegistry() {
68
91
  clear() {
69
92
  agentSessions.clear();
70
93
  agentChildren.clear();
94
+ cancellationCounts.clear();
95
+ cancellationEpochs.clear();
71
96
  },
72
97
  };
73
98
  }
@@ -14,7 +14,12 @@ export function createAgentTurns({
14
14
  takeWatchdogStop,
15
15
  takeCancelTranscript,
16
16
  }) {
17
- const createAgentChild = createAgentChildFactory({ registry, rehydrateAgentSessions, createSession });
17
+ const createAgentChild = createAgentChildFactory({
18
+ registry,
19
+ rehydrateAgentSessions,
20
+ createSession,
21
+ entryForSession,
22
+ });
18
23
 
19
24
  // The turn was stopped (progress watchdog or cancellation): rethrow its error
20
25
  // carrying the assistant text the turn produced, so the owner still gets a
@@ -35,6 +40,7 @@ export function createAgentTurns({
35
40
  async function runAgentTurn({ session, prompt, context = null, onToolResult, onTerminalResult } = {}) {
36
41
  await rehydrateAgentSessions();
37
42
  const sessionId = String(session?.id || session || '').trim();
43
+ const cancelEpoch = registry.assertAdmission(sessionId);
38
44
  const descriptor = registry.get(sessionId);
39
45
  if (!descriptor || descriptor.closed) {
40
46
  throw new Error(`agent session ${sessionId || '(empty)'} is closed`);
@@ -46,6 +52,7 @@ export function createAgentTurns({
46
52
  toolMode: 'full',
47
53
  });
48
54
  const target = entry.runtime.submitAndWait;
55
+ registry.assertAdmission(sessionId, cancelEpoch);
49
56
  if (typeof target !== 'function') {
50
57
  throw new TypeError('session runtime must implement submitAndWait');
51
58
  }
@@ -55,6 +62,7 @@ export function createAgentTurns({
55
62
  // Transcript length before this turn: where a watchdog stop's partial
56
63
  // output starts.
57
64
  const { messageCount: messageStart } = await entry.runtime.readModelMessages(Number.MAX_SAFE_INTEGER);
65
+ registry.assertAdmission(sessionId, cancelEpoch);
58
66
  descriptor.status = 'running';
59
67
  descriptor.stage = 'running';
60
68
  descriptor.updatedAt = Date.now();
@@ -109,9 +109,34 @@ export function createAgentTree({
109
109
  canRun: (session) => Boolean(registry.get(session?.id)),
110
110
  createChild: createAgentChild,
111
111
  runTurn: runAgentTurn,
112
+ /** A model or tuning change for a reused child goes through the session's
113
+ * own route API: saved at once, applied from the next turn (never refused
114
+ * because a turn is running). `route` may be partial; the route write
115
+ * completes it against the latest selected route. The descriptor follows
116
+ * the selected route. */
117
+ async setRoute({ session, route }) {
118
+ const descriptor = registry.get(session?.id);
119
+ if (!descriptor || descriptor.closed) throw new Error('agent session is closed');
120
+ const entry = await entryForSession(descriptor.id, {
121
+ cwd: descriptor.cwd,
122
+ provider: descriptor.provider,
123
+ model: descriptor.model,
124
+ toolMode: 'full',
125
+ });
126
+ try {
127
+ const applied = await entry.runtime.setRoute({ ...route, sessionOnly: true });
128
+ descriptor.provider = applied?.provider || route.provider || descriptor.provider;
129
+ descriptor.model = applied?.model || route.model || descriptor.model;
130
+ descriptor.updatedAt = Date.now();
131
+ return applied;
132
+ } finally {
133
+ retainUnwatched(entry, 'agent route change');
134
+ }
135
+ },
112
136
  async enqueueTurn({ session, prompt, context = null }) {
113
137
  const descriptor = registry.get(session?.id);
114
138
  if (!descriptor || descriptor.closed) throw new Error('agent session is closed');
139
+ const cancelEpoch = registry.assertAdmission(descriptor.id);
115
140
  const runtime = sessionOwner(descriptor.id)?.runtime;
116
141
  if (!runtime || !stateBusy(runtime.getState())) return null;
117
142
  const accepted = await runtime.submitAsync(String(prompt || ''), {
@@ -122,6 +147,7 @@ export function createAgentTree({
122
147
  transcriptMeta: { sender: 'lead' },
123
148
  });
124
149
  if (accepted === false) throw new Error('agent follow-up was not accepted');
150
+ registry.assertAdmission(descriptor.id, cancelEpoch);
125
151
  return { queueDepth: runtime.getState()?.queued?.length ?? null };
126
152
  },
127
153
  });
@@ -167,9 +193,9 @@ export function createAgentTree({
167
193
  if (handoff) descriptor.lastHandoff = handoff;
168
194
  return handoff;
169
195
  },
170
- async closeSession(sessionId, reason = 'agent session closed') {
196
+ async closeSession(sessionId, reason = 'agent session closed', options = {}) {
171
197
  await rehydrateAgentSessions();
172
- return cancelAgentTree(sessionId, reason);
198
+ return cancelAgentTree(sessionId, reason, options);
173
199
  },
174
200
  unloadSessionRuntime: (sessionId) => {
175
201
  progress.delete(sessionId);
@@ -6,6 +6,7 @@
6
6
  // converge on one runtime.
7
7
 
8
8
  export function createSessionLoads({
9
+ pendingViewers,
9
10
  sessionExists,
10
11
  log,
11
12
  assertAvailable,
@@ -20,12 +21,21 @@ export function createSessionLoads({
20
21
  const sessionLoads = new Map(); // sessionId -> Promise<entry>
21
22
 
22
23
  function getOrCreateSessionEntry(sessionId, create) {
23
- const owner = sessionOwner(sessionId);
24
- if (owner) return Promise.resolve(owner);
25
24
  const inFlight = sessionLoads.get(sessionId);
26
25
  if (inFlight) return inFlight;
27
26
  const loading = Promise.resolve()
28
- .then(create)
27
+ .then(async () => {
28
+ const owner = sessionOwner(sessionId);
29
+ if (owner) {
30
+ if ((await owner.runtime.isSessionTerminal?.()) !== true) return owner;
31
+ if (owner.subscribers?.size) {
32
+ if (!pendingViewers.has(sessionId)) pendingViewers.set(sessionId, new Set());
33
+ for (const subscriber of owner.subscribers) pendingViewers.get(sessionId).add(subscriber);
34
+ }
35
+ await destroy(owner, 'replace terminal runtime', { keepBackgroundWork: true, announce: false });
36
+ }
37
+ return create();
38
+ })
29
39
  .finally(() => {
30
40
  if (sessionLoads.get(sessionId) === loading) sessionLoads.delete(sessionId);
31
41
  });
@@ -84,11 +94,12 @@ export function createSessionLoads({
84
94
  * flight), or null where answering would take a fresh load. */
85
95
  async function hostedEntryForSession(sessionId) {
86
96
  assertAvailable();
97
+ if (sessionLoads.has(sessionId)) return sessionLoads.get(sessionId);
87
98
  const owner = sessionOwner(sessionId);
88
- if (owner) return owner;
99
+ if (owner) return (await owner.runtime.isSessionTerminal?.()) === true ? null : owner;
89
100
  const external = await bindExternalSessionView(sessionId);
90
101
  const acquiredOwner = sessionOwner(sessionId);
91
- if (acquiredOwner) return acquiredOwner;
102
+ if (acquiredOwner) return (await acquiredOwner.runtime.isSessionTerminal?.()) === true ? null : acquiredOwner;
92
103
  if (external?.runtime?.externalAction === true) return external;
93
104
  return sessionLoads.get(sessionId) || null;
94
105
  }
@@ -70,6 +70,7 @@ export function createSessionEntries({
70
70
  publishExternalSessionState,
71
71
  });
72
72
  const loads = createSessionLoads({
73
+ pendingViewers,
73
74
  sessionExists,
74
75
  log,
75
76
  assertAvailable: lifecycle.assertAvailable,
@@ -386,3 +386,42 @@ export async function loadLiveTranscriptHead(entry, sessionId, readStoredSession
386
386
  view.headOlder = from > 0 || stored.transcriptHasOlder === true;
387
387
  return true;
388
388
  }
389
+
390
+ /** A one-shot range must not grow or rebudget an attached desktop's window. */
391
+ export async function readTranscriptRange(entry, sessionId, readStoredSession, { offset, limit }) {
392
+ if (
393
+ !Number.isSafeInteger(offset) ||
394
+ offset < 0 ||
395
+ !Number.isInteger(limit) ||
396
+ limit < 1 ||
397
+ limit > 100 ||
398
+ !Number.isSafeInteger(offset + limit)
399
+ )
400
+ throw new TypeError('invalid transcript range');
401
+ const requested = offset + limit;
402
+ let snapshot;
403
+ if (entry) {
404
+ const state = entry.runtime.getState();
405
+ const isolated = { runtime: { getState: () => state } };
406
+ requestLiveTranscriptWindow(isolated, { limit: requested, byteBudget: null, pageBase: 0 });
407
+ windowTranscriptSnapshot(isolated, state);
408
+ isolated.transcriptView.paged = true;
409
+ await loadLiveTranscriptHead(isolated, sessionId, readStoredSession);
410
+ snapshot = windowTranscriptSnapshot(isolated, state);
411
+ } else {
412
+ snapshot = await readStoredSession(sessionId, { transcriptItemLimit: requested });
413
+ }
414
+ if (!snapshot) throw new Error(`session ${sessionId} is not available`);
415
+ const source = snapshot.items || [];
416
+ if (offset >= source.length && snapshot.transcriptHasOlder) {
417
+ throw new Error('session: requested history is not available in the retained projection');
418
+ }
419
+ const end = Math.max(0, source.length - offset);
420
+ const start = Math.max(0, end - limit);
421
+ return {
422
+ sessionId,
423
+ offset,
424
+ items: sanitizeForWire(source.slice(start, end)),
425
+ hasOlder: start > 0 || snapshot.transcriptHasOlder === true,
426
+ };
427
+ }