mixdog 1.2.2 → 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 (692) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/gate-local.mjs +6 -4
  4. package/scripts/lib/gate-scheduler.mjs +29 -11
  5. package/scripts/probe-provider-catalog.mjs +31 -0
  6. package/scripts/provider-pingpong-live.mjs +599 -0
  7. package/scripts/session-sweep.mjs +5 -25
  8. package/src/agents/advisor/AGENT.md +1 -1
  9. package/src/agents/advisor/agent.json +1 -1
  10. package/src/agents/maintainer/AGENT.md +1 -1
  11. package/src/agents/maintainer/agent.json +1 -1
  12. package/src/agents/reviewer/AGENT.md +2 -4
  13. package/src/agents/security/AGENT.md +1 -2
  14. package/src/agents/writer/AGENT.md +2 -3
  15. package/src/defaults/shipped-history.json +11 -1
  16. package/src/defaults/skills/image/SKILL.md +21 -23
  17. package/src/defaults/skills/setup/SKILL.md +6 -1
  18. package/src/defaults/skills/setup/references/actions.md +44 -22
  19. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  20. package/src/headless-exec.mjs +15 -8
  21. package/src/lib/keychain-cjs.cjs +20 -15
  22. package/src/output-styles/common.md +11 -10
  23. package/src/rules/agent/AGENT.md +6 -4
  24. package/src/rules/lead/LEAD.md +7 -9
  25. package/src/rules/shared/45-destructive.md +4 -0
  26. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  28. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  29. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  30. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  31. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  32. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  33. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  34. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  35. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  36. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  37. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  38. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  39. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  40. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +3 -1
  41. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
  42. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +9 -9
  43. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  45. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +31 -15
  46. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  48. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  49. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  50. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  51. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  52. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  53. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
  54. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  55. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +10 -0
  56. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  57. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  58. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +131 -9
  59. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
  60. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +125 -8
  61. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +12 -62
  62. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +117 -41
  63. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  64. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
  65. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  66. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +39 -5
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  69. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  70. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  71. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +42 -11
  73. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +109 -6
  74. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +17 -4
  75. package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -2
  76. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +73 -7
  77. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +75 -6
  78. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  79. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  80. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  81. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +29 -5
  82. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  83. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +36 -13
  84. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +101 -11
  85. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  86. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  87. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  88. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +19 -14
  89. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +371 -41
  90. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
  91. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +97 -49
  92. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +81 -10
  93. package/src/runtime/agent/orchestrator/providers/gemini.mjs +35 -8
  94. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
  96. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  97. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  98. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +253 -42
  99. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  100. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  101. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +392 -0
  102. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  103. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  104. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  105. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  106. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  107. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +50 -22
  108. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +133 -21
  109. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  110. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  111. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  112. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  113. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +92 -16
  114. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -13
  115. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +133 -62
  117. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  118. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +39 -7
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +84 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +155 -0
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +40 -24
  128. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
  129. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  130. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +183 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +87 -6
  132. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  133. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
  134. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  135. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
  136. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
  137. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
  138. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -2
  139. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
  140. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  141. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  142. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +28 -5
  143. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  144. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  145. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
  146. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
  147. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  148. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  149. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
  150. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
  151. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
  152. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +72 -24
  153. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  154. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +50 -16
  155. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -19
  156. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  157. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -36
  158. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  159. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  160. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  161. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -9
  162. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +181 -0
  163. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +78 -70
  164. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +74 -0
  165. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +150 -10
  166. package/src/runtime/agent/orchestrator/providers/registry.mjs +13 -2
  167. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +7 -1
  168. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  169. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  170. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +164 -0
  171. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +522 -0
  172. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  173. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +195 -0
  174. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +104 -0
  175. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  176. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +24 -0
  177. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  178. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  179. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  180. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  181. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  182. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  183. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +16 -3
  184. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  185. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  186. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  187. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  188. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +178 -71
  189. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +102 -12
  190. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  191. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  192. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  193. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  194. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  195. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  196. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -11
  197. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  198. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  199. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +16 -93
  200. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  201. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  202. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +148 -0
  203. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  204. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  205. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  206. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  207. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  208. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +3 -2
  209. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  210. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  211. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  212. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +89 -1
  213. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  214. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  215. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  216. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -27
  217. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  218. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  219. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  220. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +24 -10
  221. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +135 -0
  222. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +31 -4
  223. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  224. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
  225. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +10 -10
  226. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  227. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  228. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  229. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +29 -5
  230. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  231. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +147 -0
  232. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -5
  233. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  234. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  235. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +23 -2
  236. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  237. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +54 -13
  238. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  239. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  240. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +11 -0
  241. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +22 -0
  242. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  243. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  244. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  245. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  246. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  247. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +231 -16
  248. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  249. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  250. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +47 -17
  251. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +26 -4
  252. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  253. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +36 -35
  254. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  255. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +6 -3
  256. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  257. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  258. package/src/runtime/agent/orchestrator/session/manager.mjs +4 -10
  259. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  260. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  261. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +17 -1
  262. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  263. package/src/runtime/agent/orchestrator/session/side-question.mjs +197 -0
  264. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +22 -15
  265. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  266. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  267. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  269. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  270. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  271. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  272. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +44 -37
  273. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  274. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  275. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  276. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  277. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -21
  278. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  279. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  280. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  281. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +4 -2
  282. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  283. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
  284. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  285. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +53 -115
  286. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
  287. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
  288. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  289. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  290. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +17 -10
  291. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  292. package/src/runtime/agent/orchestrator/session/store.mjs +22 -19
  293. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +12 -12
  294. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +38 -14
  295. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  296. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  297. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  298. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  299. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +79 -0
  300. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  301. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  302. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  303. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  304. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  305. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  306. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  307. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  308. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +218 -20
  309. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  310. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  311. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  312. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  313. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  314. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  315. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  316. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +247 -49
  317. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  318. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  319. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  320. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  321. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  322. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  323. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  324. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  325. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  326. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  327. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  328. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  329. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  330. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  331. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  332. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  333. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  334. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  335. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  336. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  337. package/src/runtime/attachments/store.d.mts +9 -0
  338. package/src/runtime/attachments/store.mjs +80 -9
  339. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  340. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  341. package/src/runtime/computer-bridge/action-schema.mjs +219 -196
  342. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  343. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  344. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  345. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  346. package/src/runtime/github/tool.mjs +208 -17
  347. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  348. package/src/runtime/media/catalog.mjs +4 -4
  349. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  350. package/src/runtime/media/defaults.mjs +37 -0
  351. package/src/runtime/media/jobs.mjs +12 -2
  352. package/src/runtime/media/lanes.mjs +12 -0
  353. package/src/runtime/media/tool-defs.mjs +15 -4
  354. package/src/runtime/media/tool.mjs +41 -12
  355. package/src/runtime/media/upstream-error.mjs +72 -6
  356. package/src/runtime/memory/index.mjs +1 -0
  357. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  358. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  359. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  360. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  361. package/src/runtime/memory/lib/pg/process.mjs +36 -33
  362. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  363. package/src/runtime/memory/lib/pg/supervisor.mjs +112 -4
  364. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  365. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  366. package/src/runtime/office/README.md +1 -1
  367. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  368. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  369. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  370. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  371. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  372. package/src/runtime/office/authoring/pptx-html-measure.mjs +3 -1
  373. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  374. package/src/runtime/office/authoring/xlsx-html-runner.mjs +3 -1
  375. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  376. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  377. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  378. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  379. package/src/runtime/office/core/office-sessions.mjs +5 -0
  380. package/src/runtime/office/core/office-transactions.mjs +3 -0
  381. package/src/runtime/office/core/office-write-ledger.mjs +94 -0
  382. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  383. package/src/runtime/office/index.mjs +29 -0
  384. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  385. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  386. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  387. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  388. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  389. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  390. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  391. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  392. package/src/runtime/shared/atomic-file.d.mts +1 -1
  393. package/src/runtime/shared/background-tasks.mjs +6 -1
  394. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  395. package/src/runtime/shared/bounded-line-diff.mjs +191 -0
  396. package/src/runtime/shared/browser-launch.mjs +15 -0
  397. package/src/runtime/shared/buffered-appender.mjs +18 -0
  398. package/src/runtime/shared/config.mjs +78 -18
  399. package/src/runtime/shared/err-text.mjs +48 -4
  400. package/src/runtime/shared/file-lock.mjs +6 -5
  401. package/src/runtime/shared/file-permissions.d.mts +6 -1
  402. package/src/runtime/shared/file-permissions.mjs +54 -6
  403. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  404. package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
  405. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  406. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  407. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  408. package/src/runtime/shared/loopback-listener.mjs +9 -0
  409. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  410. package/src/runtime/shared/model-route-chain.mjs +48 -0
  411. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  412. package/src/runtime/shared/pid-liveness.mjs +12 -0
  413. package/src/runtime/shared/provider-api-key.mjs +8 -0
  414. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  415. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  416. package/src/runtime/shared/quiet-progress.mjs +101 -0
  417. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  418. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  419. package/src/runtime/shared/remote-intent.mjs +2 -42
  420. package/src/runtime/shared/review-diff.mjs +52 -0
  421. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  422. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  423. package/src/runtime/shared/slow-span.mjs +121 -0
  424. package/src/runtime/shared/statusline/statusline-segments.mjs +52 -6
  425. package/src/runtime/shared/tool-card-model/card-header.mjs +7 -1
  426. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  427. package/src/runtime/shared/tool-card-model.mjs +5 -2
  428. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  429. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  430. package/src/runtime/shared/tool-primitives.mjs +13 -0
  431. package/src/runtime/shared/tool-result-summary.mjs +22 -1
  432. package/src/runtime/shared/tool-status.mjs +3 -2
  433. package/src/runtime/shared/tool-surface.mjs +20 -6
  434. package/src/runtime/shared/tool-work-units.mjs +54 -11
  435. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  436. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  437. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  438. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  439. package/src/runtime/shared/transcript-writer.mjs +24 -6
  440. package/src/runtime/shared/turn-changes.mjs +269 -100
  441. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  442. package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
  443. package/src/runtime/shared/turn-snapshot.mjs +865 -683
  444. package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
  445. package/src/runtime/shared/user-data-guard.mjs +262 -49
  446. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  447. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  448. package/src/runtime/shared/worktrees/carry.mjs +533 -0
  449. package/src/runtime/shared/worktrees/contract.mjs +60 -0
  450. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  451. package/src/runtime/shared/worktrees/file-recovery.mjs +84 -0
  452. package/src/runtime/shared/worktrees/git-head.mjs +214 -0
  453. package/src/runtime/shared/worktrees/git.mjs +8 -3
  454. package/src/runtime/shared/worktrees/include.mjs +125 -7
  455. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  456. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  457. package/src/runtime/shared/worktrees/manager.mjs +525 -31
  458. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  459. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  460. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  461. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  462. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  463. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  464. package/src/runtime/terminal-bridge/client.mjs +57 -20
  465. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  466. package/src/runtime/tidy/apply.mjs +47 -2
  467. package/src/runtime/tidy/run-engines.mjs +11 -5
  468. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  469. package/src/session-runtime/boot/apis.mjs +20 -6
  470. package/src/session-runtime/boot/config.mjs +2 -0
  471. package/src/session-runtime/boot/facade.mjs +4 -0
  472. package/src/session-runtime/boot/infrastructure.mjs +6 -1
  473. package/src/session-runtime/boot/session.mjs +3 -3
  474. package/src/session-runtime/boot/tools.mjs +7 -1
  475. package/src/session-runtime/conversation-import/service.mjs +1 -1
  476. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  477. package/src/session-runtime/goal-facade-api.mjs +2 -2
  478. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +91 -0
  479. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  480. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +15 -5
  481. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +137 -26
  482. package/src/session-runtime/internal-tool-executor.mjs +8 -2
  483. package/src/session-runtime/lifecycle/cold-heir.mjs +187 -0
  484. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  485. package/src/session-runtime/lifecycle/session-catalog.mjs +25 -18
  486. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  487. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +36 -48
  488. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  489. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  490. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  491. package/src/session-runtime/lifecycle/teardown.mjs +70 -14
  492. package/src/session-runtime/lifecycle-api.mjs +1 -0
  493. package/src/session-runtime/mcp-glue/connect.mjs +17 -5
  494. package/src/session-runtime/media-api.mjs +8 -0
  495. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  496. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  497. package/src/session-runtime/model-route/set-route.mjs +116 -36
  498. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  499. package/src/session-runtime/model-route-api.mjs +4 -2
  500. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  501. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  502. package/src/session-runtime/native-web-search.mjs +19 -9
  503. package/src/session-runtime/new-session-config.mjs +4 -2
  504. package/src/session-runtime/provider-auth/login.mjs +4 -0
  505. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  506. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  507. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  508. package/src/session-runtime/provider-models.mjs +1 -0
  509. package/src/session-runtime/provider-usage.mjs +4 -0
  510. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  511. package/src/session-runtime/route-resolution.mjs +3 -1
  512. package/src/session-runtime/runtime-core.mjs +4 -0
  513. package/src/session-runtime/runtime-facade.mjs +6 -0
  514. package/src/session-runtime/runtime-review-api.mjs +8 -2
  515. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  516. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  517. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  518. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  519. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  520. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  521. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  522. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  523. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  524. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  525. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  526. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  527. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  528. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  529. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  530. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +82 -13
  531. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  532. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  533. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  534. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  535. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  536. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  537. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  538. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  539. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  540. package/src/session-runtime/services/agent-tool/tag-registry.mjs +18 -10
  541. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  542. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  543. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  544. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  545. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  546. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  547. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  548. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  549. package/src/session-runtime/services/agent-tool/worker-index.mjs +74 -15
  550. package/src/session-runtime/services/agent-tool.mjs +7 -0
  551. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  552. package/src/session-runtime/services/channel-admin.mjs +19 -3
  553. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  554. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  555. package/src/session-runtime/services/provider-admin.mjs +158 -15
  556. package/src/session-runtime/session-create/session-options.mjs +7 -5
  557. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  558. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  559. package/src/session-runtime/session-transcript.mjs +4 -5
  560. package/src/session-runtime/session-turn-api.mjs +17 -14
  561. package/src/session-runtime/settings-builtin-tools-api.mjs +18 -6
  562. package/src/session-runtime/setup-tool/executor.mjs +57 -9
  563. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  564. package/src/session-runtime/setup-tool/settings-contract.mjs +18 -3
  565. package/src/session-runtime/setup-tool/tool-defs.mjs +25 -4
  566. package/src/session-runtime/skills-api.mjs +3 -5
  567. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  568. package/src/session-runtime/tool-surface.mjs +5 -1
  569. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  570. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  571. package/src/session-runtime/turn/session-ops.mjs +7 -5
  572. package/src/session-runtime/turn/side-question-ops.mjs +19 -0
  573. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +7 -1
  574. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +12 -3
  575. package/src/session-runtime/turn/turn-run/turn-settle.mjs +18 -2
  576. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  577. package/src/session-runtime/turn/turn-run.mjs +26 -45
  578. package/src/session-runtime/usage-stats-api.mjs +46 -11
  579. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  580. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  581. package/src/session-runtime/workspace/project-branches.mjs +35 -41
  582. package/src/session-runtime/workspace/transition-steps.mjs +215 -116
  583. package/src/session-runtime/workspace/transitions.mjs +428 -73
  584. package/src/standalone/channel-transport.mjs +3 -4
  585. package/src/standalone/daemon-agent-control.mjs +9 -1
  586. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  587. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  588. package/src/standalone/daemon-owner.mjs +17 -4
  589. package/src/standalone/daemon-pg-stop.mjs +49 -0
  590. package/src/standalone/daemon-session-control.mjs +88 -0
  591. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  592. package/src/standalone/daemon-stop-budget.mjs +18 -0
  593. package/src/standalone/daemon-stored-session-views.mjs +25 -3
  594. package/src/standalone/daemon-telemetry.mjs +19 -0
  595. package/src/standalone/daemon.mjs +63 -1
  596. package/src/standalone/desktop-service-registry.mjs +5 -0
  597. package/src/standalone/local-session-runtime.mjs +80 -30
  598. package/src/standalone/session-client.mjs +42 -0
  599. package/src/standalone/session-protocol.mjs +14 -0
  600. package/src/standalone/session-proxy/projection.mjs +41 -4
  601. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  602. package/src/standalone/session-runtime-inline-host.mjs +3 -0
  603. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  604. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  605. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  606. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  607. package/src/standalone/session-service/agent-tree.mjs +28 -2
  608. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  609. package/src/standalone/session-service/entries.mjs +1 -0
  610. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  611. package/src/standalone/session-service/quota-resume.mjs +28 -13
  612. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  613. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  614. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  615. package/src/standalone/session-service-api.mjs +6 -1
  616. package/src/standalone/session-state-patch.d.mts +2 -1
  617. package/src/standalone/session-state-patch.mjs +41 -1
  618. package/src/standalone/session-tool-output.mjs +82 -0
  619. package/src/tui/App.jsx +25 -0
  620. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  621. package/src/tui/app/app-view.jsx +2 -1
  622. package/src/tui/app/btw-controller.mjs +118 -0
  623. package/src/tui/app/create-app-pickers.mjs +2 -0
  624. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  625. package/src/tui/app/provider-setup-picker.mjs +15 -3
  626. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  627. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  628. package/src/tui/app/slash-commands.mjs +19 -3
  629. package/src/tui/app/slash-dispatch/session-commands.mjs +68 -6
  630. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  631. package/src/tui/app/use-global-key-input.mjs +5 -12
  632. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  633. package/src/tui/components/BtwPanel.jsx +53 -0
  634. package/src/tui/components/QuestionPanel.jsx +275 -0
  635. package/src/tui/components/Spinner.jsx +4 -0
  636. package/src/tui/components/SpinnerByline.jsx +21 -2
  637. package/src/tui/components/question-panel-model.mjs +156 -0
  638. package/src/tui/components/status-line/local-line.mjs +10 -2
  639. package/src/tui/dist/index.mjs +2897 -1722
  640. package/src/tui/session/active-tool-summary.mjs +1 -1
  641. package/src/tui/session/context-state.mjs +4 -5
  642. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  643. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  644. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  645. package/src/tui/session/quota-resume.mjs +140 -61
  646. package/src/tui/session/session-api/commands.mjs +14 -10
  647. package/src/tui/session/session-api/controls.mjs +14 -2
  648. package/src/tui/session/session-api/integrations.mjs +9 -2
  649. package/src/tui/session/session-api/lifecycle/dispose.mjs +3 -9
  650. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  651. package/src/tui/session/session-api/lifecycle.mjs +14 -11
  652. package/src/tui/session/session-api/media.mjs +2 -0
  653. package/src/tui/session/session-api/routes.mjs +81 -57
  654. package/src/tui/session/session-api/settings.mjs +9 -3
  655. package/src/tui/session/session-api/worktree.mjs +3 -2
  656. package/src/tui/session/session-api.mjs +1 -0
  657. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  658. package/src/tui/session/session-flow/drain.mjs +6 -4
  659. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  660. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  661. package/src/tui/session/session-flow/queue.mjs +1 -1
  662. package/src/tui/session/tool-approval.mjs +20 -8
  663. package/src/tui/session/transcript-spill.mjs +14 -7
  664. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  665. package/src/tui/session/tui-steering-persist.mjs +3 -5
  666. package/src/tui/session/turn-quiet.mjs +53 -0
  667. package/src/tui/session/turn-stream.mjs +179 -32
  668. package/src/tui/session/turn.mjs +50 -36
  669. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  670. package/src/tui/spinner-meta.mjs +10 -0
  671. package/src/tui/spinner-verbs.mjs +3 -0
  672. package/src/ui/statusline.mjs +13 -3
  673. package/src/workflows/default/WORKFLOW.md +3 -1
  674. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  675. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  676. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  677. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -246
  678. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  679. package/src/session-runtime/turn/share-ops.mjs +0 -77
  680. package/src/tui/session/cross-surface-share.mjs +0 -406
  681. package/src/tui/session/live-share/delta.mjs +0 -153
  682. package/src/tui/session/live-share/mirror.mjs +0 -106
  683. package/src/tui/session/live-share/owner.mjs +0 -254
  684. package/src/tui/session/live-share/retry.mjs +0 -54
  685. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  686. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  687. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  688. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  689. package/src/tui/session/live-share/viewer.mjs +0 -99
  690. package/src/tui/session/live-share/wire.mjs +0 -44
  691. package/src/tui/session/live-share.mjs +0 -154
  692. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -20,14 +20,14 @@ export function createSessionLifecycleApi(bag, { restoreTranscriptItems, oauthFl
20
20
  // work for a conversation that is being closed. A durable close that fails
21
21
  // restores admission with every accepted input intact; one that succeeds
22
22
  // leaves the session terminal and settles queued submissions explicitly.
23
- function closeCanonical(reason) {
23
+ function closeCanonical(reason, options) {
24
24
  const flags = bag.flags || {};
25
25
  const previous = flags.admission || 'open';
26
- if (previous === 'terminal') return runtime.closeCanonicalSession?.(reason) === true;
26
+ if (previous === 'terminal') return runtime.closeCanonicalSession?.(reason, options) === true;
27
27
  flags.admission = 'closing';
28
28
  let closed = false;
29
29
  try {
30
- closed = runtime.closeCanonicalSession?.(reason) === true;
30
+ closed = runtime.closeCanonicalSession?.(reason, options) === true;
31
31
  } catch (error) {
32
32
  flags.admission = previous;
33
33
  restoreAdmission();
@@ -50,13 +50,16 @@ export function createSessionLifecycleApi(bag, { restoreTranscriptItems, oauthFl
50
50
  }
51
51
 
52
52
  return {
53
+ isSessionTerminal: () => bag.flags?.admission === 'terminal' || runtime.isSessionTerminal?.() === true,
53
54
  resolveToolApproval: (id, decision = {}) => {
54
55
  const approved = decision === true || decision?.approved === true;
55
56
  return finishToolApproval(
56
57
  id,
57
58
  approved,
58
59
  decision?.reason || (approved ? 'approved by user' : 'denied by user'),
59
- typeof decision?.device === 'string' ? decision.device : ''
60
+ typeof decision?.device === 'string' ? decision.device : '',
61
+ decision?.answers,
62
+ typeof decision?.reply === 'string' ? decision.reply : undefined
60
63
  );
61
64
  },
62
65
  pushNotice,
@@ -82,8 +85,6 @@ export function createSessionLifecycleApi(bag, { restoreTranscriptItems, oauthFl
82
85
  throw new Error('latest turn did not fail on exhausted provider quota');
83
86
  }
84
87
  if (typeof runtime.continueSessionInModel !== 'function') throw new Error('runtime cannot continue in a model');
85
- // Continuing elsewhere supersedes waiting for this provider's reset.
86
- bag.supersedeQuotaResume?.(sessionId);
87
88
  bag.set({ commandBusy: true });
88
89
  try {
89
90
  const result = await runtime.continueSessionInModel(sessionId, route);
@@ -98,10 +99,12 @@ export function createSessionLifecycleApi(bag, { restoreTranscriptItems, oauthFl
98
99
  bag.flushEmitImmediate?.();
99
100
  }
100
101
  },
101
- // Desktop sidebar watcher hook: the daemon watches this directory so
102
- // heartbeat sidecar create/delete pushes instant working/dot updates.
103
- // Without it the watcher silently no-ops and the sidebar falls back to
104
- // the 60s safety poll (user: spinner kept spinning after the turn ended).
102
+ // Desktop sidebar watcher hook: the desktop host watches this directory,
103
+ // and a session record write (a turn starting or settling) schedules a
104
+ // debounced catalog refresh that re-reads `working` from the daemon's
105
+ // in-memory run state. Without it the watcher silently no-ops and the
106
+ // sidebar only refreshes on other store notifications (user: spinner kept
107
+ // spinning after the turn ended).
105
108
  sessionStoreDir: () => {
106
109
  try {
107
110
  return runtime.sessionStoreDir?.() || null;
@@ -115,7 +118,7 @@ export function createSessionLifecycleApi(bag, { restoreTranscriptItems, oauthFl
115
118
  deliverToolCompletion: (sessionId, text, meta = {}) =>
116
119
  runtime.deliverToolCompletion?.(sessionId, text, meta) === true,
117
120
 
118
- closeCanonicalSession: (reason = 'canonical-session-close') => closeCanonical(reason),
121
+ closeCanonicalSession: (reason = 'canonical-session-close', options) => closeCanonical(reason, options),
119
122
 
120
123
  bindSessionAddress: (sessionId) => runtime.bindSessionAddress?.(sessionId) === true,
121
124
 
@@ -122,6 +122,8 @@ export function createSessionMediaApi(bag) {
122
122
  listMediaLanes: () => runtime.listMediaLanes?.(),
123
123
  getMediaDefault: (kind) => runtime.getMediaDefault?.(kind),
124
124
  setMediaDefault: (input) => runtime.setMediaDefault?.(input),
125
+ getMediaPins: () => runtime.getMediaPins?.(),
126
+ setMediaPin: (input) => runtime.setMediaPin?.(input),
125
127
  listMediaAssets: (options) => runtime.listMediaAssets?.(options),
126
128
  readMediaAsset: (id, options) => runtime.readMediaAsset?.(id, options),
127
129
  cacheMediaThumbnail: (id, input) => runtime.cacheMediaThumbnail?.(id, input),
@@ -4,8 +4,7 @@
4
4
  * definitions, output style and orchestration mode.
5
5
  */
6
6
  import { modelSwitchItem } from '../../../runtime/agent/orchestrator/session/transcript-restore/restore.mjs';
7
- import { selectedModel, switchesSessionModel } from '../../../session-runtime/model-route/model-switch-target.mjs';
8
- import { latestQuotaFailure } from '../quota-resume.mjs';
7
+ import { selectedModel } from '../../../session-runtime/model-route/model-switch-target.mjs';
9
8
  import { createApiHelpers } from './shared.mjs';
10
9
 
11
10
  // Optimistic route preview: the requested provider/model/effort/fast are
@@ -50,6 +49,36 @@ function optimisticRoutePatch(requested = {}, current = {}) {
50
49
  return patch;
51
50
  }
52
51
 
52
+ const SESSION_ONLY_KEYS = new Set(['provider', 'model', 'effort', 'fast', 'autoEffort']);
53
+
54
+ /**
55
+ * A session-only request (an agent child's route) may name just the model, just
56
+ * the tuning, or both. Completed here, inside the serialized route write,
57
+ * against the latest selected route — so a Fast-only change keeps the effort a
58
+ * previous write selected. `unchanged` when it asks for nothing the selected
59
+ * route does not already have.
60
+ */
61
+ function completeSessionOnlyRequest(request, selected) {
62
+ const named = Boolean(request.provider || request.model);
63
+ const target = named ? request : { ...request, provider: selected.provider, model: selected.model };
64
+ const sameModel = target.provider === selected.provider && target.model === selected.model;
65
+ if (!sameModel) return { request: target, unchanged: false };
66
+ const unchanged =
67
+ Object.keys(request).every((key) => SESSION_ONLY_KEYS.has(key)) &&
68
+ (request.effort === undefined || request.effort === selected.effort) &&
69
+ (request.fast === undefined || request.fast === (selected.fast === true)) &&
70
+ (request.autoEffort === undefined || request.autoEffort === (selected.autoEffort !== false));
71
+ return {
72
+ unchanged,
73
+ request: {
74
+ ...(selected.effort ? { effort: selected.effort } : {}),
75
+ fast: selected.fast === true,
76
+ autoEffort: selected.autoEffort !== false,
77
+ ...target,
78
+ },
79
+ };
80
+ }
81
+
53
82
  /** The live divider of an in-place model switch (restored from message meta
54
83
  * after a reload); every switch path publishes it the same way. */
55
84
  export function publishModelSwitch(bag, modelSwitch) {
@@ -76,6 +105,8 @@ export function createSessionRouteApi(bag) {
76
105
  });
77
106
  let routeWrite = null;
78
107
  let routeSequence = 0;
108
+ // Whether this API (not another command) is the one holding commandBusy.
109
+ let routeLocked = false;
79
110
 
80
111
  // A preset selector previews as the preset's model, never as its id.
81
112
  const previewedRequest = (routeOpts) => {
@@ -84,86 +115,79 @@ export function createSessionRouteApi(bag) {
84
115
  return target.provider ? { ...routeOpts, ...target } : routeOpts;
85
116
  };
86
117
 
87
- // Auto-compact on model change (default on): compact on the CURRENT model,
88
- // whose cache and window still hold the history, before the switch. A model
89
- // stopped on its quota cannot run it; the next turn's auto-compaction on the
90
- // new model fits the history instead. A failure never blocks the switch.
91
- const compactBeforeModelSwitch = async () => {
92
- if (runtime.getCompactionSettings?.()?.onModelChange === false) return;
93
- if (latestQuotaFailure(getState().items)) return;
94
- if (typeof bag.compactBeforeModelSwitch !== 'function') return;
95
- set({
96
- commandStatus: { active: true, verb: 'Compacting conversation', startedAt: Date.now(), mode: 'compacting' },
97
- });
98
- flushEmitImmediate();
99
- try {
100
- await bag.compactBeforeModelSwitch();
101
- } catch {
102
- /* the switch goes ahead; next-turn auto-compaction fits the window */
103
- } finally {
104
- set({ commandStatus: null });
105
- }
106
- };
107
-
108
118
  const setRoute = async (opts) => {
109
- if (getState().commandBusy && !routeWrite) return false;
110
119
  const routeOpts = opts && typeof opts === 'object' ? opts : {};
111
- // Every user model choice on this surface (composer picker, /model,
112
- // presets, the TUI picker) switches the conversation itself in place.
113
- const switchesModel = switchesSessionModel(runtime, routeOpts);
114
- // A running turn keeps the route it started on.
115
- if (switchesModel && getState().busy) {
116
- throw new Error('The model cannot change while a response is running. Try again when it finishes.');
117
- }
118
- // Any route change supersedes waiting for the old route's quota reset.
119
- bag.supersedeQuotaResume?.(getState().sessionId);
120
+ // All model pickers save a selection for the conversation's next turn; a
121
+ // running turn keeps the session model it started on. A selection is never
122
+ // refused: another command's lock neither blocks it nor is released by it.
120
123
  const token = ++routeSequence;
121
124
  const previousWrite = routeWrite;
125
+ // The session generation this selection was made under. The write below
126
+ // waits behind earlier ones, so "current" is never read later: the runtime
127
+ // validates this token before every route side effect, and `settle` below
128
+ // is the only place the display is touched once the write has started.
129
+ const originGeneration = runtime.sessionGeneration;
130
+ const owned = () => runtime.sessionGeneration === originGeneration;
122
131
  const preview = optimisticRoutePatch(previewedRequest(routeOpts), getState());
123
132
  // Preview immediately, serialize persistence without dropping a later
124
133
  // click. Earlier completions cannot replace the newest visible choice.
125
- // A model switch previews once its pre-compaction (which republishes the
126
- // current route) is done.
127
- set({ commandBusy: true, ...(switchesModel ? {} : preview || {}) });
134
+ if (!getState().commandBusy) routeLocked = true;
135
+ set({ ...(routeLocked ? { commandBusy: true } : {}), ...(preview || {}) });
128
136
  flushEmitImmediate();
129
137
  const write = (async () => {
130
138
  if (previousWrite) await previousWrite.catch(() => {});
131
139
  const previousRoute = routeState();
140
+ // A stale selection only republishes the route that is actually
141
+ // selected; it never restores or announces its own session's state.
142
+ const settle = ({ failed = false, sync = false, modelSwitch = null } = {}) => {
143
+ const stillOwned = owned();
144
+ if (stillOwned) publishModelSwitch(bag, modelSwitch);
145
+ // A newer selection publishes the final route itself.
146
+ if (token !== routeSequence) return;
147
+ if (stillOwned && failed) {
148
+ if (preview) set({ ...previousRoute, stats: { ...getState().stats } });
149
+ return;
150
+ }
151
+ if (stillOwned && sync) syncContextStats({ allowEstimated: true });
152
+ publishRoute();
153
+ };
132
154
  try {
133
- // Explicit addressing applies the route to this session: an empty
134
- // one is initialized in place. Either way an established
135
- // conversation follows the user's choice in place.
155
+ // Keep the durable session address while deferring route application.
136
156
  const applyToCurrentSession = routeOpts.applyToCurrentSession === true;
137
- const keepMainModel = routeOpts.keepMainModel === true;
138
- const { applyToCurrentSession: _drop, keepMainModel: _keep, ...nextRoute } = routeOpts;
139
- if (switchesModel) {
140
- // The destination must be accepted before the history is compacted.
141
- await runtime.setRoute(nextRoute, { validateOnly: true });
142
- await compactBeforeModelSwitch();
143
- if (token === routeSequence && preview) {
144
- set(preview);
145
- flushEmitImmediate();
157
+ const keepMainModel = routeOpts.keepMainModel !== false;
158
+ const sessionOnly = routeOpts.sessionOnly === true;
159
+ const { applyToCurrentSession: _drop, keepMainModel: _keep, sessionOnly: _scope, ...requested } = routeOpts;
160
+ let nextRoute = requested;
161
+ if (sessionOnly) {
162
+ const completed = completeSessionOnlyRequest(requested, previousRoute);
163
+ if (completed.unchanged) {
164
+ // An earlier failed write skipped its rollback because this one is
165
+ // newer, so the shown route may still be that write's preview.
166
+ settle();
167
+ return previousRoute;
146
168
  }
169
+ nextRoute = completed.request;
147
170
  }
148
171
  const resolvedRoute = await runtime.setRoute(nextRoute, {
149
172
  applyToCurrentSession,
150
173
  keepMainModel,
174
+ ...(sessionOnly ? { sessionOnly } : {}),
175
+ ...(originGeneration !== undefined ? { originGeneration } : {}),
151
176
  switchEstablished: true,
177
+ deferUntilNextTurn: true,
178
+ });
179
+ settle({
180
+ sync: applyToCurrentSession || Boolean(resolvedRoute?.modelSwitch),
181
+ modelSwitch: resolvedRoute?.modelSwitch,
152
182
  });
153
- if (token === routeSequence) {
154
- if (applyToCurrentSession || resolvedRoute?.modelSwitch) syncContextStats({ allowEstimated: true });
155
- publishRoute();
156
- }
157
- publishModelSwitch(bag, resolvedRoute?.modelSwitch);
158
183
  return resolvedRoute;
159
184
  } catch (error) {
160
- if (token === routeSequence && preview) {
161
- set({ ...previousRoute, stats: { ...getState().stats } });
162
- }
185
+ settle({ failed: true });
163
186
  throw error;
164
187
  } finally {
165
188
  if (token === routeSequence) {
166
- set({ commandBusy: false });
189
+ if (routeLocked) set({ commandBusy: false });
190
+ routeLocked = false;
167
191
  // Publish the resolved route (or rollback) before an RPC reply
168
192
  // reads getState(), even while the display-frame clock is busy.
169
193
  flushEmitImmediate();
@@ -29,9 +29,9 @@ export function createSessionSettingsApi(bag) {
29
29
 
30
30
  return {
31
31
  // A model selector (/model, a preset) is the user's model choice like any
32
- // picker selection: the route surface switches an established
33
- // conversation in place (pre-compaction, busy refusal, divider). False
34
- // while another command holds the lock.
32
+ // picker selection: the route surface saves it for the conversation's
33
+ // next turn (a running turn keeps its model) and applies it there. Never
34
+ // refused: another command's lock does not block a selection.
35
35
  setModel: async (m) => (await bag.setSessionRoute({ model: m })) !== false,
36
36
  setEffort: withCommandLock(
37
37
  async (value) => {
@@ -106,6 +106,12 @@ export function createSessionSettingsApi(bag) {
106
106
  deferStatsRefresh();
107
107
  return next;
108
108
  }),
109
+ getSessionTitleSettings: () => {
110
+ return runtime.getSessionTitleSettings?.() || { aiSessionTitles: true };
111
+ },
112
+ setAiSessionTitles: withCommandLock(async (enabled) => {
113
+ return await runtime.setAiSessionTitles?.(enabled);
114
+ }),
109
115
  getToolModuleSettings: () => {
110
116
  return (
111
117
  runtime.getToolModuleSettings?.() || {
@@ -23,8 +23,7 @@
23
23
  * (expectedRevision: WORKTREE_REVISION_CONFLICT when the session moved on)
24
24
  * (WORKTREE_REMOVAL_INCOMPLETE: partly removed; call again to finish)
25
25
  * listWorktrees() → every managed worktree with its retention
26
- * pruneWorktrees() → reconcile report (never a retained worktree)
27
- */
26
+ * pruneWorktrees() → reconcile report (never a retained worktree) */
28
27
  import { worktreeError } from '../../../runtime/shared/worktrees/contract.mjs';
29
28
 
30
29
  /** Session actions of the Lead worktree feature (settings live in settings.mjs). */
@@ -34,6 +33,8 @@ export const SESSION_WORKTREE_ACTIONS = Object.freeze([
34
33
  'selectBranch',
35
34
  'selectProjectBranch',
36
35
  'mergeProjectBranch',
36
+ 'inspectProjectBranch',
37
+ 'manageProjectBranch',
37
38
  'requestWorktree',
38
39
  'mergeWorkspace',
39
40
  'removeWorktree',
@@ -33,6 +33,7 @@ export function createSessionApi(bag) {
33
33
  autoClear: await read(api.getAutoClear),
34
34
  compaction: await read(api.getCompactionSettings),
35
35
  recap: await read(api.getRecapSettings),
36
+ sessionTitles: await read(api.getSessionTitleSettings),
36
37
  toolModules: await read(api.getToolModuleSettings),
37
38
  channels: await read(api.getChannelSettings, { includeStatus: false }),
38
39
  systemShell: await read(api.getSystemShell),
@@ -196,10 +196,8 @@ export function createAutoClearOps(bag, { reset, kickDrain }) {
196
196
 
197
197
  // Same eligibility as a user submit, run before a completion wake turn so a
198
198
  // cold cache after a long idle is compacted first. Never throws: a skipped or
199
- // failed auto-clear must still let the wake run. A viewer mirroring another
200
- // surface's owner leaves compaction to that owner.
199
+ // failed auto-clear must still let the wake run.
201
200
  async function autoClearBeforeWake() {
202
- if (bag.liveShareMirroring?.() === true) return false;
203
201
  try {
204
202
  return await autoClearBeforeSubmit({ ignorePending: true });
205
203
  } catch {
@@ -89,6 +89,8 @@ export function turnOptionsForBatch(batch, steering) {
89
89
  return {
90
90
  promptSource: batchPromptSource(batch),
91
91
  retryFailedTurn: batch[0]?.retryFailedTurn === true,
92
+ retryTurnId: batch[0]?.retryTurnId || null,
93
+ retryAttemptId: batch[0]?.retryAttemptId || null,
92
94
  displayText: batch
93
95
  .map((entry) => entry.text)
94
96
  .filter((text) => String(text || '').trim())
@@ -148,7 +150,7 @@ export function createDrainLoop(
148
150
  // matching message under its own lock).
149
151
  function rewindFailedTurnRows(batch) {
150
152
  const entry = batch[0];
151
- if (entry?.retryFailedTurn !== true) return;
153
+ if (entry?.retryFailedTurn !== true || entry.retryTurnId) return;
152
154
  const rewound = rewoundFailedTurnItems(getState().items, entry.text);
153
155
  if (!rewound) return;
154
156
  set({
@@ -217,7 +219,7 @@ export function createDrainLoop(
217
219
  // but so do setModel/newSession/resume/etc). Running a turn concurrently
218
220
  // with a command that swaps or reroutes the live session is a race; the
219
221
  // commandBusy-release hook re-kicks drain once the command finishes.
220
- if (flags.autoClearRunning || getState().commandBusy) {
222
+ if (flags.autoClearRunning || flags.quotaResumePending || getState().commandBusy) {
221
223
  scheduleBlockedDrainRetry();
222
224
  return;
223
225
  }
@@ -253,7 +255,7 @@ export function createDrainLoop(
253
255
  // its pre-compaction, a reset) runs before the next turn starts. The
254
256
  // finally below re-enters drain(), which waits on the same gate, and
255
257
  // the commandBusy release re-kicks the queue.
256
- if (flags.autoClearRunning || getState().commandBusy) return;
258
+ if (flags.autoClearRunning || flags.quotaResumePending || getState().commandBusy) return;
257
259
  // Drain one priority/mode bucket at a time (unified command queue):
258
260
  // prompt steering stays editable and task notifications stay
259
261
  // non-editable but model-visible.
@@ -331,7 +333,7 @@ export function createDrainLoop(
331
333
  submissions.remember(submissionId);
332
334
  pending.push(entry);
333
335
  const needsDurableSteering =
334
- (getState().busy || getState().commandBusy || flags.autoClearRunning) &&
336
+ (getState().busy || getState().commandBusy || flags.autoClearRunning || flags.quotaResumePending) &&
335
337
  steering.shouldMirrorSteeringEntry(entry);
336
338
  const persistence = needsDurableSteering ? appendTuiSteeringPersist(steering.leadSessionId(), entry) : null;
337
339
  if (isQueuedEntryVisible(entry)) {
@@ -49,5 +49,7 @@ export function makeQueueEntry(text, options = {}, nextId) {
49
49
  // Retry of a failed turn: the transcript and the session rewind the
50
50
  // failed turn's unanswered prompt before this entry runs.
51
51
  retryFailedTurn: options.retryFailedTurn === true,
52
+ retryTurnId: options.retryTurnId || null,
53
+ retryAttemptId: options.retryAttemptId || null,
52
54
  };
53
55
  }
@@ -39,10 +39,11 @@ export function createTakeEntriesOps({ pending, pendingNotificationKeys, removeQ
39
39
  (entry.mode || 'prompt') === targetMode &&
40
40
  queuePriorityValue(entry.priority) === bestPriority
41
41
  ) {
42
+ if (batch.length > 0 && entry.retryTurnId) break;
42
43
  batch.push(entry);
43
44
  pending.splice(i, 1);
44
45
  if (entry.mode === 'task-notification' && entry.key) pendingNotificationKeys.delete(entry.key);
45
- if (batch.length >= limit) break;
46
+ if (entry.retryTurnId || batch.length >= limit) break;
46
47
  } else {
47
48
  i += 1;
48
49
  }
@@ -14,7 +14,7 @@ import { createTakeEntriesOps } from './queue/take-entries.mjs';
14
14
 
15
15
  // Submission-id memory for idempotent re-delivery. A prompt can legitimately
16
16
  // reach this queue TWICE when its transport retries across a failed response
17
- // (daemon view retry, live-share spool fallback after a missing ack). The id
17
+ // (daemon view retry after a missing ack). The id
18
18
  // the surface minted is the identity of the message, so a repeat of an id we
19
19
  // already queued is dropped instead of posting the prompt twice.
20
20
  const SUBMISSION_ID_MEMORY = 256;
@@ -12,24 +12,33 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
12
12
 
13
13
  function normalizeToolApprovalRequest(input = {}, id = nextId()) {
14
14
  const now = Date.now();
15
+ // An explicit `timeoutMs: null` means no wait limit (no timer, no expiry);
16
+ // any other missing/invalid value falls back to the session default.
17
+ const requestTimeoutMs =
18
+ input?.timeoutMs === null
19
+ ? null
20
+ : Number.isFinite(Number(input?.timeoutMs)) && Number(input.timeoutMs) > 0
21
+ ? Number(input.timeoutMs)
22
+ : timeoutMs;
15
23
  return {
16
24
  id,
17
25
  name: String(input?.name || input?.tool_name || 'tool'),
26
+ kind: typeof input?.kind === 'string' ? input.kind : '',
18
27
  args: input?.args ?? input?.tool_input ?? null,
19
28
  cwd: input?.cwd || null,
20
29
  sessionId: input?.sessionId || input?.session_id || null,
21
30
  toolCallId: input?.toolCallId || input?.tool_use_id || null,
22
31
  reason: String(input?.reason || input?.message || 'approval requested by hook').trim(),
23
32
  requestedAt: now,
24
- timeoutMs,
25
- expiresAt: now + timeoutMs,
33
+ timeoutMs: requestTimeoutMs,
34
+ expiresAt: requestTimeoutMs === null ? null : now + requestTimeoutMs,
26
35
  };
27
36
  }
28
37
  // Every request expires from ITS OWN requestedAt, queued or active. Arming
29
38
  // the timer only on presentation let a queued request sit past expiresAt
30
39
  // (retaining its promise and surfacing an obsolete approval later).
31
40
  function armToolApprovalTimeout(entry) {
32
- if (!entry || entry.timer) return;
41
+ if (!entry || entry.timer || entry.request?.expiresAt === null) return;
33
42
  const remainingMs = Math.max(0, Number(entry.request?.expiresAt || 0) - Date.now());
34
43
  entry.timer = setTimeout(() => {
35
44
  finishToolApproval(entry.id, false, 'approval timed out');
@@ -39,10 +48,13 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
39
48
  // Settle one entry: drop its timeout, then hand the waiter its answer. The
40
49
  // resolve stays guarded — a waiter whose caller already went away must never
41
50
  // take the rest of the queue down with it.
42
- function settleToolApproval(entry, approved, reason) {
51
+ function settleToolApproval(entry, approved, reason, answers, reply) {
43
52
  if (entry?.timer) clearTimeout(entry.timer);
53
+ const result = { approved, reason };
54
+ if (answers !== undefined) result.answers = answers;
55
+ if (reply !== undefined) result.reply = reply;
44
56
  try {
45
- entry.resolve({ approved, reason });
57
+ entry.resolve(result);
46
58
  } catch {}
47
59
  }
48
60
  function presentNextToolApproval() {
@@ -56,7 +68,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
56
68
  armToolApprovalTimeout(entry);
57
69
  set({ toolApproval: entry.request });
58
70
  }
59
- function finishToolApproval(id, approved, reason = '', device = '') {
71
+ function finishToolApproval(id, approved, reason = '', device = '', answers = undefined, reply = undefined) {
60
72
  const targetId = String(id || '');
61
73
  if (activeToolApproval && activeToolApproval.id === targetId) {
62
74
  const entry = activeToolApproval;
@@ -67,14 +79,14 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
67
79
  ? { id: targetId, approved: approved === true, device: String(device), at: Date.now() }
68
80
  : null;
69
81
  set({ toolApproval: null, toolApprovalResult });
70
- settleToolApproval(entry, approved === true, String(reason || ''));
82
+ settleToolApproval(entry, approved === true, String(reason || ''), answers, reply);
71
83
  presentNextToolApproval();
72
84
  return true;
73
85
  }
74
86
  const index = toolApprovalQueue.findIndex((entry) => entry.id === targetId);
75
87
  if (index >= 0) {
76
88
  const [entry] = toolApprovalQueue.splice(index, 1);
77
- settleToolApproval(entry, approved === true, String(reason || ''));
89
+ settleToolApproval(entry, approved === true, String(reason || ''), answers, reply);
78
90
  return true;
79
91
  }
80
92
  return false;
@@ -30,6 +30,13 @@ export { cleanupStaleTranscriptSpillDirs };
30
30
 
31
31
  let staleSpillSweepDone = false;
32
32
 
33
+ /** One sweep per process: it lists the whole temp directory synchronously. */
34
+ export function sweepStaleTranscriptSpillDirsOnce() {
35
+ if (staleSpillSweepDone) return;
36
+ staleSpillSweepDone = true;
37
+ cleanupStaleTranscriptSpillDirs();
38
+ }
39
+
33
40
  // Serialized pages deliberately release the old item object graph while
34
41
  // keeping every byte restorable. Only `items` is render-live and walkable.
35
42
  // This buffer owns the page list, the reading cursor and snapshots; the spill
@@ -47,12 +54,9 @@ export function createTranscriptSpillBuffer({
47
54
  try {
48
55
  writeOwnerRegistry();
49
56
  } catch {}
50
- // One sweep per process: it lists the whole temp directory synchronously,
51
- // and a buffer is created per session.
52
- if (!staleSpillSweepDone) {
53
- staleSpillSweepDone = true;
54
- cleanupStaleTranscriptSpillDirs();
55
- }
57
+ // A buffer is created per session; the sweep runs once per process (the
58
+ // daemon runs it in its post-ready warm-up).
59
+ sweepStaleTranscriptSpillDirsOnce();
56
60
  const pages = [];
57
61
  let cursor = null;
58
62
  let spillDir = null;
@@ -228,13 +232,16 @@ export function reindexItems(itemIndexById, items) {
228
232
  export function replaceSessionItemsState({ state, items, itemIndexById, preserveStreamingTail = false, extra = {} }) {
229
233
  const nextItems = Array.isArray(items) ? items : [];
230
234
  reindexItems(itemIndexById, nextItems);
231
- return {
235
+ const next = {
232
236
  ...state,
233
237
  ...extra,
234
238
  items: nextItems,
235
239
  structureRevision: (Number(state.structureRevision) || 0) + 1,
236
240
  streamingTail: preserveStreamingTail ? state.streamingTail : null,
237
241
  };
242
+ // The desktop's partial line belongs to the live row it continues.
243
+ if (!preserveStreamingTail && next.streamingPartial) next.streamingPartial = null;
244
+ return next;
238
245
  }
239
246
 
240
247
  // Shared by the live session runtime and focused transcript tests so revision/tail
@@ -4,7 +4,7 @@
4
4
  * that lets a host prove a longer text is an append of the same stream.
5
5
  */
6
6
  // Non-enumerable so the marker never enters persisted transcript items,
7
- // live-share JSON, or renderer snapshots. The desktop host reads the shared
7
+ // wire JSON, or renderer snapshots. The desktop host reads the shared
8
8
  // Symbol.for key before cloning and uses it to prove that a growing text is
9
9
  // an append, avoiding an O(total text) startsWith check on every frame.
10
10
  const streamingTailTextEpochKey = Symbol.for('mixdog.streaming-tail-text-epoch');
@@ -99,11 +99,9 @@ function normalizePendingStore(raw) {
99
99
  // FOREIGN bucket. This file is SHARED with the runtime/manager pending
100
100
  // -message spool, and every TUI write passes the whole store through
101
101
  // here. Flattening those rows to plain strings destroyed id,
102
- // enqueuedAt, options, structured content, the notification markers —
103
- // and the handoffAt/handoffPid parking stamp that is the only reason an
104
- // accepted-but-undelivered user message survives an owner crash. Rows
105
- // this process does not own are copied through UNCHANGED (array copy
106
- // only, so nothing here can alias-mutate them either).
102
+ // enqueuedAt, options, structured content and the notification markers.
103
+ // Rows this process does not own are copied through UNCHANGED (array
104
+ // copy only, so nothing here can alias-mutate them either).
107
105
  out.sessions[sid] = value.slice();
108
106
  const foreignTouched = Number(touchedRaw[sid]);
109
107
  // Carry an existing stamp only: inventing one would reset the runtime's
@@ -0,0 +1,53 @@
1
+ // The lead turn's quiet-time cue: polls the runtime's turn liveness while the
2
+ // turn runs and publishes `spinner.quiet` ({ since, wait, tool?, warnMs })
3
+ // once the turn has gone QUIET_PROGRESS_CUE_MS without counted progress, and
4
+ // clears it when progress resumes. The value is frozen for a whole silence, so
5
+ // a silence costs two publications, never one per tick. Display only.
6
+ import { displayProgressStage, quietProgress, lastProgressAt } from '../../runtime/shared/quiet-progress.mjs';
7
+ import { resolveAgentStallThresholds } from '../../runtime/agent/orchestrator/stall-policy.mjs';
8
+
9
+ const QUIET_POLL_MS = 1_000;
10
+
11
+ /** The lead's stall-watchdog warn point, in ms. */
12
+ export function leadStallWarnMs() {
13
+ return resolveAgentStallThresholds('lead').warn * 1000;
14
+ }
15
+
16
+ function sameQuiet(left, right) {
17
+ if (!left || !right) return !left && !right;
18
+ return left.since === right.since && left.wait === right.wait && left.tool === right.tool;
19
+ }
20
+
21
+ /** The quiet state a liveness snapshot implies at `now` (null: not quiet). */
22
+ export function turnQuietState(liveness, now, warnMs) {
23
+ if (!liveness || typeof liveness !== 'object' || typeof liveness.then === 'function') return null;
24
+ const quiet = quietProgress({
25
+ progressAt: lastProgressAt(liveness),
26
+ stage: displayProgressStage(liveness),
27
+ tool: liveness.currentTool,
28
+ now,
29
+ });
30
+ return quiet ? { ...quiet, warnMs } : null;
31
+ }
32
+
33
+ export function startQuietWatch({ runtime, getState, set, isCurrentTurn, warnMs = leadStallWarnMs() }) {
34
+ const timer = setInterval(() => {
35
+ if (!isCurrentTurn()) {
36
+ clearInterval(timer);
37
+ return;
38
+ }
39
+ const spinner = getState().spinner;
40
+ if (!spinner) return;
41
+ let liveness = null;
42
+ try {
43
+ liveness = runtime?.getTurnLiveness?.() ?? null;
44
+ } catch {
45
+ return;
46
+ }
47
+ const next = turnQuietState(liveness, Date.now(), warnMs);
48
+ if (sameQuiet(spinner.quiet ?? null, next)) return;
49
+ set({ spinner: { ...spinner, quiet: next } });
50
+ }, QUIET_POLL_MS);
51
+ timer.unref?.();
52
+ return () => clearInterval(timer);
53
+ }