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
@@ -41,6 +41,9 @@ export function resolveAgentSpawnPreset(config, args = {}) {
41
41
  type: 'agent',
42
42
  provider: agentRoute.provider,
43
43
  model: agentRoute.model,
44
+ ...(config.agents?.[agentName]?.fallbacks?.length
45
+ ? { fallbacks: config.agents[agentName].fallbacks.map(normalizeAgentRoute) }
46
+ : {}),
44
47
  effort: agentRoute.effort,
45
48
  fast: agentRoute.fast === true,
46
49
  ...(agentRoute.autoEffort === false ? { autoEffort: false } : {}),
@@ -61,15 +61,13 @@ export function createTagLookup({ tags, mgr, readWorkerRows, reaper, getLiveSess
61
61
  };
62
62
  for (const row of readWorkerRows(context)) addIndexRow(row);
63
63
  if (scanSessions) {
64
- const pendingTerminal = [];
65
64
  for (const session of mgr.listSessions({ includeClosed: false }) || []) {
66
65
  if (session?.closed === true) continue;
67
66
  const tag = agentTagOf(session);
68
67
  if (tag && reaper.tombstoneBlocksScan(session, tag, tombstones)) continue;
69
68
  add(session, tag);
70
- if (tag) reaper.scanUpsertSession(session, tag, tombstones, pendingTerminal);
69
+ if (tag) reaper.scanUpsertSession(session, tag, tombstones);
71
70
  }
72
- reaper.settleScannedTerminalRows(pendingTerminal);
73
71
  }
74
72
  for (const [tag, sessionId] of tags.entries()) {
75
73
  const session = getLiveSession(sessionId);
@@ -18,7 +18,6 @@ export function createTagRefresh({ tags, tagMaps, mgr, reaper, refreshTagsFromIn
18
18
  // Tags missing from the index are exactly the ones a reap just removed, so
19
19
  // the tombstone (not the still-open session record) decides whether this
20
20
  // scan may re-bind them.
21
- const pendingTerminal = [];
22
21
  for (const session of mgr.listSessions({ includeClosed: false }) || []) {
23
22
  if (isLeadPoolAgent(session?.agent)) continue;
24
23
  if (session?.closed === true) continue;
@@ -27,8 +26,7 @@ export function createTagRefresh({ tags, tagMaps, mgr, reaper, refreshTagsFromIn
27
26
  if (!sessionMatchesContext(session, context)) continue;
28
27
  if (reaper.tombstoneBlocksScan(session, tag, tombstones)) continue;
29
28
  tagMaps.bind(tag, session);
30
- reaper.scanUpsertSession(session, tag, tombstones, pendingTerminal);
29
+ reaper.scanUpsertSession(session, tag, tombstones);
31
30
  }
32
- reaper.settleScannedTerminalRows(pendingTerminal);
33
31
  };
34
32
  }
@@ -1,7 +1,7 @@
1
1
  // Tag registry: owns the tag maps (tag -> sessionId/agent/cwd) and every
2
2
  // resolution/mutation path — resolve/next/bind/forget and the session-index
3
3
  // refresh. Worker-index persistence lives in worker-index.mjs and terminal
4
- // tombstones/reap timers in terminal-reaper.mjs; the tag maps are shared by
4
+ // tombstones in terminal-reaper.mjs; the tag maps are shared by
5
5
  // reference so all three sides see the same live state.
6
6
  import { agentTagOf } from './helpers.mjs';
7
7
  import { createLeadWorkerIndex } from './lead-worker-index.mjs';
@@ -27,6 +27,7 @@ export function createTagRegistry({ dataDir, cfgMod, mgr }) {
27
27
  dataDir,
28
28
  cfgMod,
29
29
  workerRowFromSession: index.workerRowFromSession,
30
+ isSessionRunning: (sessionId) => mgr.isSessionTurnInFlight?.(sessionId) === true,
30
31
  });
31
32
 
32
33
  const { upsertLeadSession, updateLeadWorkerCwd, forgetLeadSession } = leadIndex;
@@ -66,7 +67,7 @@ export function createTagRegistry({ dataDir, cfgMod, mgr }) {
66
67
  return null;
67
68
  }
68
69
 
69
- const reaper = createTerminalReaper({ cfgMod, mgr, tagMaps, index, getLiveSession, tagForSession });
70
+ const reaper = createTerminalReaper({ cfgMod, mgr, tagMaps, index, getLiveSession });
70
71
 
71
72
  function wantsSessionScan(args = {}) {
72
73
  return args.recover === true || args.scanSessions === true || args.scan_sessions === true;
@@ -102,8 +103,6 @@ export function createTagRegistry({ dataDir, cfgMod, mgr }) {
102
103
  removeWorkerRow({ tag, sessionId });
103
104
  }
104
105
 
105
- reaper.recoverTerminalReaps();
106
-
107
106
  return {
108
107
  dispose,
109
108
  disposeAsync,
@@ -123,7 +122,6 @@ export function createTagRegistry({ dataDir, cfgMod, mgr }) {
123
122
  tags,
124
123
  tagAgents: tagMaps.tagAgents,
125
124
  tagCwds: tagMaps.tagCwds,
126
- reapTimers: reaper.reapTimers,
127
125
  wantsSessionScan,
128
126
  resolveTag,
129
127
  getLiveSession,
@@ -138,10 +136,6 @@ export function createTagRegistry({ dataDir, cfgMod, mgr }) {
138
136
  tombstoneTerminalSession: reaper.tombstoneTerminalSession,
139
137
  tagTombstoneForTag: reaper.tagTombstoneForTag,
140
138
  consumeTagTombstone: reaper.consumeTagTombstone,
141
- cancelReap: reaper.cancelReap,
142
- clearScheduledReaps: reaper.clearScheduledReaps,
143
- scheduleReap: reaper.scheduleReap,
144
- recoverTerminalReaps: reaper.recoverTerminalReaps,
145
139
  transitionStaleNonterminalRows: reaper.transitionStaleNonterminalRows,
146
140
  };
147
141
  }
@@ -1,13 +1,11 @@
1
1
  // Session-scan admission: whether a scan may (re)index a session, and how a
2
- // terminal session's frozen stamps translate into the reap deadline that the
3
- // scan then settles through the timers.
4
- import { agentTagOf, clean, stampMs } from '../helpers.mjs';
2
+ // terminal session's frozen stamps are re-emitted onto its row.
3
+ import { clean, stampMs } from '../helpers.mjs';
5
4
  import { isTerminalWorkerStatus } from '../worker-rows.mjs';
6
5
  import { ACTIVE_STAGES } from '../tool-def.mjs';
7
- import { resolveAgentTerminalReapMs } from '../../../../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
8
6
  import { sessionActivityAt } from './row-helpers.mjs';
9
7
 
10
- export function createScanAdmission({ cfgMod, mgr, index, tombstoneBlocksScan, timers }) {
8
+ export function createScanAdmission({ mgr, index, tombstoneBlocksScan }) {
11
9
  const { readWorkerRows, upsertWorkerSessionDeferred } = index;
12
10
 
13
11
  function scanSessionIsTerminal(session) {
@@ -23,7 +21,7 @@ export function createScanAdmission({ cfgMod, mgr, index, tombstoneBlocksScan, t
23
21
  /** Extra fields for a scan/rebind upsert of an already-terminal session. The
24
22
  * default row build stamps updatedAt = now and clears reapAt, which restarts
25
23
  * the lease from the read instead of from the work: a terminal session owns
26
- * its frozen stamps, and its deadline is derived from them. Returns null for
24
+ * its frozen stamps, which are kept as-is with no reap deadline. Returns null for
27
25
  * running/active sessions so they keep the normal (now-based) behavior. */
28
26
  function terminalScanExtra(session) {
29
27
  if (!scanSessionIsTerminal(session)) return null;
@@ -34,56 +32,25 @@ export function createScanAdmission({ cfgMod, mgr, index, tombstoneBlocksScan, t
34
32
  const stamp = new Date(terminalAtMs).toISOString();
35
33
  const sessionId = clean(session?.id);
36
34
  const existing = readWorkerRows().find((row) => clean(row.sessionId) === sessionId) || null;
37
- const reapMs = resolveAgentTerminalReapMs(
38
- cfgMod.loadConfig(),
39
- clean(existing?.provider) || clean(session?.provider)
40
- );
41
- // An existing lease is authoritative: a read must never extend or reset it.
42
- const existingReapMs = stampMs(existing?.reapAt);
43
- let reapAt = null;
44
- if (existingReapMs > 0) reapAt = new Date(existingReapMs).toISOString();
45
- else if (reapMs != null) reapAt = new Date(terminalAtMs + reapMs).toISOString();
46
35
  const finishedMs = stampMs(session?.finishedAt) || stampMs(existing?.finishedAt);
47
36
  return {
48
37
  // Stamps are re-emitted as ISO so a numeric session stamp cannot leak an
49
38
  // unparseable value into the row store.
50
39
  updatedAt: stamp,
51
40
  finishedAt: finishedMs > 0 ? new Date(finishedMs).toISOString() : stamp,
52
- reapAt,
41
+ reapAt: null,
53
42
  };
54
43
  }
55
44
 
56
45
  // Shared session-scan admission: returns false when the scan must not
57
46
  // resurrect this session, otherwise indexes it (terminal sessions with their
58
- // own stamps) and records any terminal deadline for settlement.
59
- function scanUpsertSession(session, tag, tombstones, pendingTerminal) {
47
+ // own stamps).
48
+ function scanUpsertSession(session, tag, tombstones) {
60
49
  if (tombstoneBlocksScan(session, tag, tombstones)) return false;
61
50
  const extra = terminalScanExtra(session);
62
51
  upsertWorkerSessionDeferred(session, tag, extra || {});
63
- if (extra?.reapAt) {
64
- pendingTerminal.push({
65
- tag: agentTagOf(session) || clean(tag),
66
- sessionId: clean(session.id),
67
- reapAt: extra.reapAt,
68
- });
69
- }
70
52
  return true;
71
53
  }
72
54
 
73
- /** Arm (or immediately run) the reap for rows a scan just (re)indexed. An
74
- * already-elapsed deadline is reaped now instead of buying a new window. */
75
- function settleScannedTerminalRows(pendingTerminal) {
76
- if (!pendingTerminal.length) return;
77
- const now = Date.now();
78
- for (const row of pendingTerminal) {
79
- const deadline = stampMs(row.reapAt);
80
- if (!deadline) continue;
81
- // reapTerminalRow -> tombstoneTerminalSession flushes the deferred upsert
82
- // first, so the row it matches on is the one this scan just wrote.
83
- if (deadline <= now) timers.reapTerminalRow(row);
84
- else if (!timers.isArmedFor(row.sessionId, row.reapAt)) timers.schedulePersistedReap(row);
85
- }
86
- }
87
-
88
- return { scanUpsertSession, settleScannedTerminalRows };
55
+ return { scanUpsertSession };
89
56
  }
@@ -1,5 +1,5 @@
1
1
  // Stale non-terminal rows: an index row whose session is gone and whose
2
- // heartbeat is older than the reap window becomes a tombstone so its tag is
2
+ // last row stamp is older than the reap window becomes a tombstone so its tag is
3
3
  // freed instead of blocking spawn forever.
4
4
  import { clean, positiveInt } from '../helpers.mjs';
5
5
  import { TAG_TOMBSTONE_TTL_MS, isLeadPoolAgent, workerRowTime } from '../worker-rows.mjs';
@@ -16,9 +16,9 @@ export function createStaleRowTransition({ cfgMod, tagMaps, index, getLiveSessio
16
16
  if (getLiveSession(clean(row.sessionId))) return false;
17
17
  const rowTime = workerRowTime(row);
18
18
  const reapMs = resolveAgentTerminalReapMs(cfgMod.loadConfig(), row.provider);
19
- // A row with no timestamp has no usable heartbeat at all. Explicitly
19
+ // A row with no timestamp has no usable stamp at all. Explicitly
20
20
  // disabled terminal reaping still gets the tombstone TTL as a finite
21
- // stale-heartbeat bound, so malformed/running index rows cannot block a
21
+ // staleness bound, so malformed/running index rows cannot block a
22
22
  // tag forever.
23
23
  return rowTime <= 0 || Date.now() - rowTime >= (reapMs ?? TAG_TOMBSTONE_TTL_MS);
24
24
  });
@@ -1,46 +1,29 @@
1
- // Terminal-session reaping for the agent tag registry: tag tombstones, the
2
- // scan admission guard they impose, the delayed reap timers and their
3
- // recovery after a restart. Reaping expires only the tag/runtime lease — the
4
- // session record stays open so the transcript remains visible from the parent
5
- // task. Each concern lives under ./terminal-reaper/; this file wires them.
1
+ // Terminal-session bookkeeping for the agent tag registry: tag tombstones, the
2
+ // scan admission guard they impose and stale worker-row transitions. Terminal
3
+ // sessions are never closed on a timer — the session record stays open so the
4
+ // transcript remains visible from the parent task. Each concern lives under
5
+ // ./terminal-reaper/; this file wires them.
6
6
  import { createTagTombstones } from './terminal-reaper/tombstones.mjs';
7
- import { createReapTimers } from './terminal-reaper/reap-timers.mjs';
8
7
  import { createScanAdmission } from './terminal-reaper/scan-admission.mjs';
9
8
  import { createStaleRowTransition } from './terminal-reaper/stale-rows.mjs';
10
9
 
11
- export function createTerminalReaper({ cfgMod, mgr, tagMaps, index, getLiveSession, tagForSession }) {
10
+ export function createTerminalReaper({ cfgMod, mgr, tagMaps, index, getLiveSession }) {
12
11
  const tombstones = createTagTombstones({ tagMaps, index });
13
- const timers = createReapTimers({
14
- cfgMod,
15
- mgr,
16
- index,
17
- getLiveSession,
18
- tagForSession,
19
- tombstoneTerminalSession: tombstones.tombstoneTerminalSession,
20
- });
21
12
  const scan = createScanAdmission({
22
- cfgMod,
23
13
  mgr,
24
14
  index,
25
15
  tombstoneBlocksScan: tombstones.tombstoneBlocksScan,
26
- timers,
27
16
  });
28
17
  const { transitionStaleNonterminalRows } = createStaleRowTransition({ cfgMod, tagMaps, index, getLiveSession });
29
18
 
30
19
  return {
31
- reapTimers: timers.reapTimers,
32
20
  tagTombstoneIndex: tombstones.tagTombstoneIndex,
33
21
  tombstoneBlocksScan: tombstones.tombstoneBlocksScan,
34
22
  scanUpsertSession: scan.scanUpsertSession,
35
- settleScannedTerminalRows: scan.settleScannedTerminalRows,
36
23
  forgetTerminalSession: tombstones.forgetTerminalSession,
37
24
  tombstoneTerminalSession: tombstones.tombstoneTerminalSession,
38
25
  tagTombstoneForTag: tombstones.tagTombstoneForTag,
39
26
  consumeTagTombstone: tombstones.consumeTagTombstone,
40
- clearScheduledReaps: timers.clearScheduledReaps,
41
- cancelReap: timers.cancelReap,
42
- scheduleReap: timers.scheduleReap,
43
- recoverTerminalReaps: timers.recoverTerminalReaps,
44
27
  transitionStaleNonterminalRows,
45
28
  };
46
29
  }
@@ -31,7 +31,6 @@ export function createTerminalTrace({ registry }) {
31
31
  if (!row) return false;
32
32
  registry.refreshTagsFromSessions({ context });
33
33
  const sessionId = clean(row.sessionId);
34
- if (sessionId) registry.cancelReap(sessionId);
35
34
  registry.forgetTerminalSession(value, sessionId);
36
35
  return true;
37
36
  }
@@ -53,6 +53,13 @@ export const AGENT_TOOL = {
53
53
  file: { type: 'string', description: 'Path to task text; alternative to prompt/message for spawn/send.' },
54
54
  cwd: { type: 'string', description: 'Project directory for a new or respawned agent.' },
55
55
  context: { type: 'string', description: 'Extra context for the spawn/send turn.' },
56
+ model: {
57
+ type: 'string',
58
+ description:
59
+ "Spawn only, and only when the user explicitly names a model: runs this one spawn on it instead of the agent's preset route, which stays the default (omit otherwise). Id, display name, or words of it; ambiguous or unknown names fail with candidates. The agent still supplies role and permissions.",
60
+ },
61
+ provider: { type: 'string', description: 'Narrows model to one provider; requires model.' },
62
+ effort: { type: 'string', description: 'Reasoning effort for an explicit model.' },
56
63
  },
57
64
  required: ['type'],
58
65
  additionalProperties: false,
@@ -1,9 +1,6 @@
1
1
  // worker-index/row-liveness.mjs
2
2
  // Whether an active-looking row still has a live worker behind it, and how a
3
- // row settles back to idle when it does not.
4
- import { statSync } from 'node:fs';
5
- import { resolve } from 'node:path';
6
-
3
+ // row settles (idle, or failed when its runtime died) when it does not.
7
4
  import { resolveAgentTerminalReapMs } from '../../../../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
8
5
  import { clean, positiveInt, runtimeAlive } from '../helpers.mjs';
9
6
 
@@ -25,24 +22,33 @@ export const isActiveWorkerRow = (row) =>
25
22
  * with that process (daemon restart), so the flag must not stick. */
26
23
  export const isStaleApprovalWait = (row) => Boolean(row?.awaitingUser) && !runtimeAlive(row.runtimePid);
27
24
 
28
- export function createRowLiveness({ dataDir, cfgMod }) {
29
- function heartbeatFresh(sessionId, now) {
30
- const id = clean(sessionId);
31
- if (!dataDir || !id) return false;
32
- try {
33
- const mtimeMs = statSync(resolve(dataDir, 'sessions', `${id}.hb`)).mtimeMs || 0;
34
- return mtimeMs > 0 && now - mtimeMs <= WORKER_POOL_FRESH_MS;
35
- } catch {
36
- return false;
37
- }
38
- }
25
+ /** The process that ran the row's turn is gone (a restart or crash ended it). */
26
+ export const runtimeDied = (row) => Boolean(positiveInt(row?.runtimePid)) && !runtimeAlive(row.runtimePid);
27
+
28
+ /** The row's turn ended because the process running it went away. */
29
+ export const PROCESS_RESTART_FAILURE = 'process-restart';
39
30
 
40
- /** Active status, but its runtime pid is dead, or neither its heartbeat nor
41
- * its own update stamp is fresh. */
31
+ /** The row's turn was stopped by the progress (stall) watchdog. */
32
+ export const WATCHDOG_STALL_FAILURE = 'stalled';
33
+
34
+ /** A turn's settled row status and failure reason: a watchdog stop is a
35
+ * failure whatever partial output it handed back (`finalStatus` may still
36
+ * read `idle` for the job's sake); everything else keeps `finalStatus`. */
37
+ export function settledWorkerStatus(finalStatus, stalled) {
38
+ return stalled
39
+ ? { status: 'failed', stage: 'failed', failureReason: WATCHDOG_STALL_FAILURE }
40
+ : { status: finalStatus, stage: finalStatus };
41
+ }
42
+
43
+ /** `isSessionRunning(sessionId)`: the daemon's in-memory answer to whether
44
+ * that session's turn is in flight (every session runs in this process). */
45
+ export function createRowLiveness({ cfgMod, isSessionRunning = () => false }) {
46
+ /** Active status, but its runtime pid is dead, or its turn is not running
47
+ * here and its own update stamp is not fresh either. */
42
48
  function isStaleActive(row, now) {
43
49
  if (!isActiveWorkerRow(row)) return false;
44
- if (positiveInt(row.runtimePid) && !runtimeAlive(row.runtimePid)) return true;
45
- if (heartbeatFresh(row.sessionId, now)) return false;
50
+ if (runtimeDied(row)) return true;
51
+ if (isSessionRunning(clean(row.sessionId))) return false;
46
52
  const updated = Date.parse(clean(row.updatedAt)) || 0;
47
53
  return !(updated > 0 && now - updated <= WORKER_POOL_FRESH_MS);
48
54
  }
@@ -74,5 +80,11 @@ export function createRowLiveness({ dataDir, cfgMod }) {
74
80
  };
75
81
  }
76
82
 
77
- return { isStaleActive, idleRow };
83
+ /** The row settled as failed: its turn never finished, and `failureReason`
84
+ * says why. Stamps settle exactly as idleRow's. */
85
+ function failedRow(row, now, failureReason, touch = false) {
86
+ return { ...idleRow(row, now, touch), status: 'failed', stage: 'failed', failureReason };
87
+ }
88
+
89
+ return { isStaleActive, idleRow, failedRow };
78
90
  }
@@ -52,6 +52,9 @@ export function normalizeWorkerRows(value) {
52
52
  cwd: clean(row.cwd) || null,
53
53
  task_id: clean(row.task_id || row.taskId) || null,
54
54
  error: clean(row.error) || null,
55
+ // Why a `failed` row failed (row-liveness, a watchdog stop). Always
56
+ // present, so a later whole-row write clears a stale reason.
57
+ failureReason: clean(row.failureReason) || null,
55
58
  permission: clean(row.permission) || null,
56
59
  toolPermission: clean(row.toolPermission) || null,
57
60
  messages: positiveInt(row.messages) || 0,
@@ -101,14 +104,14 @@ export function workerRowFromSession(session, fallbackTag = '', extra = {}, getS
101
104
  // Turn dispatch stamps this; terminal upserts leave it null and the
102
105
  // merge in applyWorkerRowUpsert preserves the running turn's value.
103
106
  turnStartedAt: clean(extra.turnStartedAt) || null,
104
- // Active/new work clears the previous lease. Terminal settlement writes
105
- // the new absolute deadline immediately afterwards via scheduleReap().
107
+ // Kept for compatibility with older worker rows; no timer consumes it.
106
108
  reapAt: clean(extra.reapAt) || null,
107
109
  clientHostPid: positiveInt(extra.clientHostPid) || positiveInt(session?.clientHostPid),
108
110
  runtimePid: positiveInt(extra.runtimePid) || process.pid,
109
111
  cwd: clean(session?.cwd) || clean(extra.cwd) || null,
110
112
  task_id: clean(extra.task_id || extra.taskId) || null,
111
113
  error: clean(extra.error) || null,
114
+ failureReason: clean(extra.failureReason) || null,
112
115
  permission: clean(session?.permission) || null,
113
116
  toolPermission: clean(session?.toolPermission) || null,
114
117
  messages: Array.isArray(session?.messages) ? session.messages.length : 0,
@@ -18,7 +18,13 @@ import {
18
18
  registerApprovalWaitWriter,
19
19
  } from './worker-index/approval-wait.mjs';
20
20
  import { createMutationBatch } from './worker-index/mutation-batch.mjs';
21
- import { createRowLiveness, isActiveWorkerRow, isStaleApprovalWait } from './worker-index/row-liveness.mjs';
21
+ import {
22
+ createRowLiveness,
23
+ isActiveWorkerRow,
24
+ isStaleApprovalWait,
25
+ PROCESS_RESTART_FAILURE,
26
+ runtimeDied,
27
+ } from './worker-index/row-liveness.mjs';
22
28
  import { normalizeWorkerRows, workerRowFromSession } from './worker-index/row-shape.mjs';
23
29
  import { acquireWorkerRowStore } from './worker-index/row-store.mjs';
24
30
  import { findTagTombstone, tagTombstoneKey, tombstoneBlocksWork } from '../../../runtime/shared/agent-reap-state.mjs';
@@ -35,9 +41,13 @@ export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCw
35
41
  unreconciled.clear();
36
42
  for (const id of ids) reconcileAwaitingUser(id);
37
43
  });
38
- const liveness = createRowLiveness({ dataDir, cfgMod });
39
- // Rows this process marked active; settled to idle on exit so a crash of
40
- // the host never leaves them "running" forever.
44
+ const liveness = createRowLiveness({
45
+ cfgMod,
46
+ isSessionRunning: (sessionId) => mgr.isSessionTurnInFlight?.(sessionId) === true,
47
+ });
48
+ // Rows this process marked active; settled as failed on exit (their turn
49
+ // dies with the process) so a crash of the host never leaves them
50
+ // "running" forever.
41
51
  const activeWorkerKeys = new Set();
42
52
 
43
53
  function readWorkerRows(context = {}) {
@@ -144,13 +154,17 @@ export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCw
144
154
  for (const key of keys) {
145
155
  const current = byKey.get(key);
146
156
  if (!current || positiveInt(current.runtimePid) !== process.pid) continue;
147
- if (isActiveWorkerRow(current)) byKey.set(key, liveness.idleRow(current, now, true));
157
+ if (isActiveWorkerRow(current)) {
158
+ byKey.set(key, liveness.failedRow(current, now, PROCESS_RESTART_FAILURE, true));
159
+ }
148
160
  }
149
161
  });
150
162
  }
151
163
 
152
- // Startup recovery: stale active rows settle to idle, and an approval wait
153
- // left behind by a runtime that is gone (daemon restart) is cleared.
164
+ // Startup recovery: stale active rows settle — as failed when the process
165
+ // that ran their turn is gone (the turn never finished), otherwise to idle —
166
+ // and an approval wait left behind by a runtime that is gone (daemon
167
+ // restart) is cleared.
154
168
  function recoverStaleWorkerRows() {
155
169
  const now = Date.now();
156
170
  const rows = store.readAll();
@@ -162,7 +176,13 @@ export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCw
162
176
  for (const row of staleActive) {
163
177
  const key = workerRowKey(row);
164
178
  const current = byKey.get(key);
165
- if (current && liveness.isStaleActive(current, now)) byKey.set(key, liveness.idleRow(current, now));
179
+ if (!current || !liveness.isStaleActive(current, now)) continue;
180
+ byKey.set(
181
+ key,
182
+ runtimeDied(current)
183
+ ? liveness.failedRow(current, now, PROCESS_RESTART_FAILURE)
184
+ : liveness.idleRow(current, now)
185
+ );
166
186
  }
167
187
  });
168
188
  }
@@ -42,6 +42,9 @@ export function createStandaloneAgent({
42
42
  sessionSurface = null,
43
43
  awaitKeychainPrewarm = async () => {},
44
44
  isKeychainPrewarmReady = () => true,
45
+ // Provider model catalog for user-pinned spawn models; absent on surfaces
46
+ // without one, where only exact provider + model pass.
47
+ listProviderModels = null,
45
48
  }) {
46
49
  const canUseSessionSurface = (session) =>
47
50
  typeof sessionSurface?.runTurn === 'function' && sessionSurface.canRun?.(session) !== false;
@@ -105,6 +108,7 @@ export function createStandaloneAgent({
105
108
  sendFlow,
106
109
  closeFlow,
107
110
  terminalTrace,
111
+ listProviderModels,
108
112
  });
109
113
 
110
114
  function getStatus(context = {}) {
@@ -18,6 +18,8 @@ export function getProgressWatchdogState(mgr, sessionId) {
18
18
  registered: Boolean(state?.linked && !state.controller.signal.aborted),
19
19
  lastCheckedAt: state?.lastCheckedAt || null,
20
20
  error: state?.error || null,
21
+ // The policy this session's watchdog actually enforces.
22
+ policy: state?.watchdogPolicy || null,
21
23
  };
22
24
  }
23
25