mixdog 1.2.3 → 1.2.5

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 (469) 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/mobile-release.mjs +5 -4
  5. package/scripts/probe-provider-catalog.mjs +31 -0
  6. package/scripts/provider-pingpong-live.mjs +128 -38
  7. package/scripts/session-sweep.mjs +5 -25
  8. package/src/agents/maintainer/AGENT.md +1 -1
  9. package/src/agents/maintainer/agent.json +1 -1
  10. package/src/agents/reviewer/AGENT.md +2 -4
  11. package/src/agents/security/AGENT.md +1 -2
  12. package/src/agents/writer/AGENT.md +2 -3
  13. package/src/defaults/shipped-history.json +7 -1
  14. package/src/defaults/skills/image/SKILL.md +21 -23
  15. package/src/lib/keychain-cjs.cjs +13 -11
  16. package/src/output-styles/common.md +2 -1
  17. package/src/rules/agent/AGENT.md +7 -5
  18. package/src/rules/lead/LEAD.md +13 -13
  19. package/src/rules/shared/45-destructive.md +4 -0
  20. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  21. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  22. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  23. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  24. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  25. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  26. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
  28. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  29. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  30. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2 -5
  31. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -0
  32. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  33. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  34. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +81 -10
  35. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
  36. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
  37. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
  38. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
  39. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
  40. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  41. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  42. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  43. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  44. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +41 -11
  46. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
  47. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
  48. package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
  49. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
  50. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
  51. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
  52. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
  53. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
  54. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
  55. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  56. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  57. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +6 -1
  58. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
  59. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
  60. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
  61. package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
  62. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  63. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
  64. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
  65. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  66. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
  67. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
  68. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  69. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
  70. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
  72. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  74. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
  75. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
  76. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
  78. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
  79. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  80. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
  81. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  82. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +3 -1
  83. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
  84. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
  85. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
  86. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
  87. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
  88. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
  89. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
  90. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
  91. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
  92. package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
  93. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
  94. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
  95. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
  96. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
  97. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
  98. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  99. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
  100. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  101. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  102. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  103. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +3 -1
  104. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  105. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
  106. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
  107. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
  108. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  109. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  110. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  111. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  112. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  113. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -11
  114. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  115. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
  116. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  117. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
  118. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  119. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  120. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  121. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +1 -1
  122. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  123. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  124. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -4
  125. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
  126. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -27
  127. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  128. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  129. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  130. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +4 -1
  131. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
  132. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
  133. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  134. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
  135. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
  136. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  137. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
  138. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
  139. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
  140. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  141. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  142. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +21 -1
  143. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
  144. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  145. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
  146. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
  147. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  148. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  149. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  150. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  151. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +29 -8
  152. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  153. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  154. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +32 -14
  155. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
  156. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
  157. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  158. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
  159. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  160. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
  161. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  162. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
  163. package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
  164. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
  165. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  167. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  169. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +5 -11
  172. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  173. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  174. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  175. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -32
  176. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  177. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  178. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  179. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  181. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +160 -212
  182. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
  183. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  184. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  185. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +7 -8
  186. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  187. package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
  188. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
  189. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
  190. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  191. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
  192. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  193. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  194. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  195. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  196. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  197. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +204 -10
  198. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  199. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  200. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  201. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  202. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  203. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  205. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +200 -17
  206. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  207. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  208. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  209. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  210. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  211. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  212. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  213. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  214. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  215. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  216. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  217. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  218. package/src/runtime/attachments/store.d.mts +9 -0
  219. package/src/runtime/attachments/store.mjs +80 -9
  220. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  221. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  222. package/src/runtime/computer-bridge/action-schema.mjs +178 -178
  223. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  224. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  225. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  226. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  227. package/src/runtime/github/tool.mjs +118 -17
  228. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  229. package/src/runtime/media/catalog.mjs +4 -4
  230. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  231. package/src/runtime/media/defaults.mjs +37 -0
  232. package/src/runtime/media/jobs.mjs +12 -2
  233. package/src/runtime/media/lanes.mjs +12 -0
  234. package/src/runtime/media/tool-defs.mjs +15 -4
  235. package/src/runtime/media/tool.mjs +41 -12
  236. package/src/runtime/media/upstream-error.mjs +72 -6
  237. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  238. package/src/runtime/memory/lib/pg/process.mjs +5 -7
  239. package/src/runtime/memory/lib/pg/supervisor.mjs +4 -1
  240. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  241. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  242. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  243. package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
  244. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  245. package/src/runtime/office/core/office-write-ledger.mjs +1 -5
  246. package/src/runtime/office/index.mjs +2 -3
  247. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  248. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  249. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  250. package/src/runtime/shared/atomic-file.d.mts +1 -1
  251. package/src/runtime/shared/background-tasks.mjs +6 -1
  252. package/src/runtime/shared/bounded-line-diff.mjs +11 -2
  253. package/src/runtime/shared/browser-launch.mjs +15 -0
  254. package/src/runtime/shared/err-text.mjs +42 -4
  255. package/src/runtime/shared/file-lock.mjs +6 -5
  256. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  257. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  258. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  259. package/src/runtime/shared/model-route-chain.mjs +48 -0
  260. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  261. package/src/runtime/shared/pid-liveness.mjs +12 -0
  262. package/src/runtime/shared/provider-api-key.mjs +6 -0
  263. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  264. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  265. package/src/runtime/shared/quiet-progress.mjs +101 -0
  266. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  267. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  268. package/src/runtime/shared/remote-intent.mjs +2 -42
  269. package/src/runtime/shared/slow-span.mjs +8 -1
  270. package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
  271. package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
  272. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  273. package/src/runtime/shared/tool-result-summary.mjs +16 -2
  274. package/src/runtime/shared/tool-status.mjs +3 -2
  275. package/src/runtime/shared/tool-surface.mjs +2 -3
  276. package/src/runtime/shared/tool-work-units.mjs +22 -15
  277. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  278. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  279. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  280. package/src/runtime/shared/transcript-writer.mjs +14 -4
  281. package/src/runtime/shared/turn-changes.mjs +2 -1
  282. package/src/runtime/shared/turn-snapshot.mjs +11 -3
  283. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  284. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  285. package/src/runtime/shared/worktrees/carry.mjs +6 -4
  286. package/src/runtime/shared/worktrees/contract.mjs +27 -1
  287. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  288. package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
  289. package/src/runtime/shared/worktrees/git-head.mjs +22 -13
  290. package/src/runtime/shared/worktrees/include.mjs +125 -7
  291. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  292. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  293. package/src/runtime/shared/worktrees/manager.mjs +378 -32
  294. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  295. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  296. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  297. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  298. package/src/runtime/terminal-bridge/client.mjs +14 -10
  299. package/src/session-runtime/boot/apis.mjs +7 -1
  300. package/src/session-runtime/boot/config.mjs +2 -0
  301. package/src/session-runtime/boot/facade.mjs +3 -0
  302. package/src/session-runtime/boot/session.mjs +3 -2
  303. package/src/session-runtime/boot/tools.mjs +3 -0
  304. package/src/session-runtime/conversation-import/service.mjs +1 -1
  305. package/src/session-runtime/goal-facade-api.mjs +2 -2
  306. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
  307. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
  308. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
  309. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  310. package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
  311. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
  312. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
  313. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  314. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  315. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  316. package/src/session-runtime/lifecycle/teardown.mjs +7 -16
  317. package/src/session-runtime/media-api.mjs +8 -0
  318. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  319. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  320. package/src/session-runtime/model-route/set-route.mjs +114 -34
  321. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  322. package/src/session-runtime/model-route-api.mjs +4 -2
  323. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  324. package/src/session-runtime/native-web-search.mjs +9 -8
  325. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  326. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  327. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  328. package/src/session-runtime/provider-models.mjs +1 -0
  329. package/src/session-runtime/provider-usage.mjs +4 -0
  330. package/src/session-runtime/route-resolution.mjs +3 -1
  331. package/src/session-runtime/runtime-core.mjs +4 -0
  332. package/src/session-runtime/runtime-facade.mjs +6 -0
  333. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  334. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  335. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  336. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  337. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  338. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  339. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  340. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  341. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  342. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  343. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  344. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  345. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +9 -6
  346. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  347. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  348. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  349. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  350. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  351. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  352. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  353. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  354. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  355. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -9
  356. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  357. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  358. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  359. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  360. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  361. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  362. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  363. package/src/session-runtime/services/agent-tool/worker-index.mjs +28 -8
  364. package/src/session-runtime/services/agent-tool.mjs +4 -0
  365. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  366. package/src/session-runtime/services/provider-admin.mjs +77 -0
  367. package/src/session-runtime/session-create/session-options.mjs +7 -5
  368. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  369. package/src/session-runtime/session-transcript.mjs +4 -5
  370. package/src/session-runtime/session-turn-api.mjs +3 -9
  371. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
  372. package/src/session-runtime/setup-tool/executor.mjs +23 -5
  373. package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
  374. package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
  375. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
  376. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  377. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  378. package/src/session-runtime/turn/side-question-ops.mjs +1 -4
  379. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
  380. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
  381. package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
  382. package/src/session-runtime/turn/turn-run.mjs +1 -36
  383. package/src/session-runtime/usage-stats-api.mjs +4 -1
  384. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  385. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  386. package/src/session-runtime/workspace/project-branches.mjs +28 -36
  387. package/src/session-runtime/workspace/transition-steps.mjs +96 -95
  388. package/src/session-runtime/workspace/transitions.mjs +248 -68
  389. package/src/standalone/channel-transport.mjs +3 -4
  390. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  391. package/src/standalone/daemon-pg-stop.mjs +1 -3
  392. package/src/standalone/daemon-session-control.mjs +88 -0
  393. package/src/standalone/daemon-stored-session-views.mjs +23 -3
  394. package/src/standalone/daemon.mjs +2 -0
  395. package/src/standalone/desktop-service-registry.mjs +32 -5
  396. package/src/standalone/local-session-runtime.mjs +11 -12
  397. package/src/standalone/session-protocol.mjs +7 -0
  398. package/src/standalone/session-runtime-inline-host.mjs +2 -0
  399. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  400. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  401. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  402. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  403. package/src/standalone/session-service/agent-tree.mjs +28 -2
  404. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  405. package/src/standalone/session-service/entries.mjs +1 -0
  406. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  407. package/src/standalone/session-service/quota-resume.mjs +28 -13
  408. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  409. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  410. package/src/standalone/session-tool-output.mjs +82 -0
  411. package/src/tui/app/app-view.jsx +2 -1
  412. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  413. package/src/tui/app/provider-setup-picker.mjs +15 -3
  414. package/src/tui/app/slash-commands.mjs +6 -0
  415. package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
  416. package/src/tui/components/Spinner.jsx +4 -0
  417. package/src/tui/components/SpinnerByline.jsx +21 -2
  418. package/src/tui/components/status-line/local-line.mjs +10 -2
  419. package/src/tui/dist/index.mjs +529 -270
  420. package/src/tui/session/active-tool-summary.mjs +1 -1
  421. package/src/tui/session/context-state.mjs +0 -3
  422. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  423. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  424. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  425. package/src/tui/session/quota-resume.mjs +140 -61
  426. package/src/tui/session/session-api/commands.mjs +4 -10
  427. package/src/tui/session/session-api/controls.mjs +12 -0
  428. package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
  429. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  430. package/src/tui/session/session-api/lifecycle.mjs +13 -11
  431. package/src/tui/session/session-api/media.mjs +2 -0
  432. package/src/tui/session/session-api/routes.mjs +81 -57
  433. package/src/tui/session/session-api/settings.mjs +3 -3
  434. package/src/tui/session/session-api/worktree.mjs +3 -2
  435. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  436. package/src/tui/session/session-flow/drain.mjs +6 -4
  437. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  438. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  439. package/src/tui/session/session-flow/queue.mjs +1 -1
  440. package/src/tui/session/tool-approval.mjs +17 -8
  441. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  442. package/src/tui/session/tui-steering-persist.mjs +3 -5
  443. package/src/tui/session/turn-quiet.mjs +53 -0
  444. package/src/tui/session/turn-stream.mjs +5 -1
  445. package/src/tui/session/turn.mjs +38 -31
  446. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  447. package/src/tui/spinner-meta.mjs +10 -0
  448. package/src/tui/spinner-verbs.mjs +3 -0
  449. package/src/ui/statusline.mjs +13 -3
  450. package/src/ui/streaming-markdown-heal.mjs +70 -18
  451. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  452. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  453. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  454. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -302
  455. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  456. package/src/session-runtime/turn/share-ops.mjs +0 -77
  457. package/src/tui/session/cross-surface-share.mjs +0 -406
  458. package/src/tui/session/live-share/delta.mjs +0 -153
  459. package/src/tui/session/live-share/mirror.mjs +0 -106
  460. package/src/tui/session/live-share/owner.mjs +0 -254
  461. package/src/tui/session/live-share/retry.mjs +0 -54
  462. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  463. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  464. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  465. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  466. package/src/tui/session/live-share/viewer.mjs +0 -99
  467. package/src/tui/session/live-share/wire.mjs +0 -44
  468. package/src/tui/session/live-share.mjs +0 -154
  469. 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
@@ -165,6 +165,8 @@ export class DesktopServiceRegistry {
165
165
  moduleUrl: requestedModule,
166
166
  instance,
167
167
  subscribers: new Set(),
168
+ visibilityEpochs: new Map(),
169
+ nextVisibilityEpoch: 0,
168
170
  };
169
171
  this.#servicesById.set(requestedId, record);
170
172
  this.#servicesByModule.set(requestedModule, record);
@@ -187,7 +189,14 @@ export class DesktopServiceRegistry {
187
189
  const service = await this.#initialize(params);
188
190
  if (this.#closed) throw new Error('session service is closed');
189
191
  const token = subscriberToken(ctx);
190
- if (token) service.subscribers.add(token);
192
+ if (token) {
193
+ service.subscribers.add(token);
194
+ // The adapter outlives desktop processes, whose request counters restart.
195
+ // Allocate the ordering namespace here, not from a client's wall clock.
196
+ if (!service.visibilityEpochs.has(token)) {
197
+ service.visibilityEpochs.set(token, ++service.nextVisibilityEpoch);
198
+ }
199
+ }
191
200
  this.#syncModelProxyPresence();
192
201
  return { desktopId: service.desktopId };
193
202
  }
@@ -215,14 +224,23 @@ export class DesktopServiceRegistry {
215
224
  }
216
225
 
217
226
  async invoke({ desktopId, method, args = [] } = {}, ctx = null) {
218
- const { service } = this.#requireSubscribed(desktopId, ctx);
227
+ const { service, token } = this.#requireSubscribed(desktopId, ctx);
219
228
  const name = String(method || '');
220
229
  if (!name) throw new TypeError('desktop service method is required');
230
+ let callArgs = Array.isArray(args) ? args : [];
231
+ if (name === 'setVisibleSessions' && token) {
232
+ const epoch = service.visibilityEpochs.get(token);
233
+ if (epoch === undefined) {
234
+ service.subscribers.delete(token);
235
+ throw new Error('desktop service client is not initialized');
236
+ }
237
+ callArgs = [callArgs[0], callArgs[1], epoch];
238
+ }
221
239
  // `[slow-op] desktop.invoke` names the call it timed: a desktop operation
222
240
  // (Git reads) or a session capability, not only the generic route.
223
241
  const target = name === 'invokeDesktopOperation' || name === 'invokeCapability' ? String(args?.[0] || '') : '';
224
242
  annotateSpan(target ? `${name}:${target}` : name);
225
- return sanitizeForWire(await service.instance.invoke(name, Array.isArray(args) ? args : [])) ?? null;
243
+ return sanitizeForWire(await service.instance.invoke(name, callArgs)) ?? null;
226
244
  }
227
245
 
228
246
  async control({ desktopId, message } = {}, ctx = null) {
@@ -241,7 +259,7 @@ export class DesktopServiceRegistry {
241
259
  async unsubscribe({ desktopId } = {}, ctx = null) {
242
260
  const service = this.#require(desktopId);
243
261
  const token = subscriberToken(ctx);
244
- if (token) service.subscribers.delete(token);
262
+ if (token) await this.#releaseSubscriber(service, token);
245
263
  this.#syncModelProxyPresence();
246
264
  return { ok: true, unsubscribed: true };
247
265
  }
@@ -250,11 +268,20 @@ export class DesktopServiceRegistry {
250
268
  const token = String(clientToken || '');
251
269
  if (!token) return;
252
270
  for (const service of this.#servicesById.values()) {
253
- service.subscribers.delete(token);
271
+ void this.#releaseSubscriber(service, token).catch((error) => {
272
+ this.#log(`desktop visibility release failed: ${error?.message || error}`);
273
+ });
254
274
  }
255
275
  this.#syncModelProxyPresence();
256
276
  }
257
277
 
278
+ async #releaseSubscriber(service, token) {
279
+ service.subscribers.delete(token);
280
+ const epoch = service.visibilityEpochs.get(token);
281
+ service.visibilityEpochs.delete(token);
282
+ if (epoch !== undefined) await service.instance.releaseClient?.(epoch);
283
+ }
284
+
258
285
  notifySessionRuntimeReleased(sessionId, reason) {
259
286
  // An evicted session has NO session subscribers. Its desktop resources
260
287
  // still belong to the desktop service and must be notified on that lane.
@@ -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);