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
@@ -0,0 +1,25 @@
1
+ /**
2
+ * src/session-runtime/turn/compaction-gate.mjs - serializes a model-scheduled
3
+ * compaction (session tool) with everything that follows its turn. The
4
+ * compaction is chained, never left dangling: `after(fn)` wraps a command so it
5
+ * waits for the compaction in flight, and the compaction itself only runs if
6
+ * the session it was scheduled for is still the live one.
7
+ */
8
+ export function createCompactionGate({ getSessionId, compact }) {
9
+ let tail = Promise.resolve();
10
+ const run = (sessionId) => {
11
+ tail = tail
12
+ .then(() => (getSessionId() === sessionId ? compact() : null))
13
+ .catch(() => {
14
+ /* best-effort: a scheduled compaction must never break teardown */
15
+ });
16
+ return tail;
17
+ };
18
+ const after =
19
+ (fn) =>
20
+ async (...args) => {
21
+ await tail;
22
+ return fn(...args);
23
+ };
24
+ return { run, after };
25
+ }
@@ -10,7 +10,6 @@ export function createSessionOps(deps) {
10
10
  const {
11
11
  getSession,
12
12
  setSession,
13
- getCurrentCwd,
14
13
  setMode,
15
14
  getActiveTurnCount,
16
15
  mgr,
@@ -18,7 +17,7 @@ export function createSessionOps(deps) {
18
17
  agentTool,
19
18
  invalidatePreSessionToolSurface,
20
19
  refreshEmptySessionToolPolicy,
21
- applyResolvedCwd,
20
+ switchProject,
22
21
  resolveCwdPath,
23
22
  agentStatusState,
24
23
  getReservedSessionId,
@@ -122,9 +121,12 @@ export function createSessionOps(deps) {
122
121
  return { messageCount: list.length, messages: list.slice(start) };
123
122
  }
124
123
 
125
- function setCwd(path) {
126
- applyResolvedCwd(resolveCwdPath(path), { persistProjectSelection: true });
127
- return getCurrentCwd();
124
+ // The desktop/remote Project switch: refused while a turn runs or the
125
+ // session works in a managed worktree (switchProject); resolves once the
126
+ // prompt refresh landed. Its target is a registered Project or the task
127
+ // workspace, classified by desktop membership.
128
+ async function setCwd(path) {
129
+ return switchProject(resolveCwdPath(path), { classifyByMembership: true });
128
130
  }
129
131
 
130
132
  return {
@@ -0,0 +1,19 @@
1
+ /**
2
+ * src/session-runtime/turn/side-question-ops.mjs - /btw side questions on the
3
+ * runtime's current session. They run beside an in-progress turn and touch no
4
+ * session state (see orchestrator/session/side-question.mjs).
5
+ */
6
+ import { askSideQuestion, cancelSideQuestion } from '../../runtime/agent/orchestrator/session/side-question.mjs';
7
+
8
+ export function createSideQuestionOps({ getSession, getReservedSessionId }) {
9
+ const sessionId = () => getSession()?.id || getReservedSessionId?.() || '';
10
+ return {
11
+ /** @returns {Promise<{ text: string }>} */
12
+ askSide: (question) => askSideQuestion(sessionId(), question),
13
+ /** Abort the side question of `targetSessionId` (the session it was
14
+ * asked in), or of the current session when omitted. */
15
+ cancelSide: (targetSessionId) => {
16
+ cancelSideQuestion(typeof targetSessionId === 'string' && targetSessionId ? targetSessionId : sessionId());
17
+ },
18
+ };
19
+ }
@@ -1,4 +1,5 @@
1
1
  import { isVisibleStreamProgress } from '../../../runtime/shared/stream-progress.mjs';
2
+ import { toolCallDisplayIdentity } from '../../../runtime/shared/tool-primitives.mjs';
2
3
 
3
4
  // The askSession callback bridge: caller callbacks pass through, with the
4
5
  // transcript, first-visible timing, title release and warmup arming folded in.
@@ -6,10 +7,13 @@ export function createAskCallbacks({ transcript, notifyFnForSession, scheduleSea
6
7
  function plannedToolCalls(session0, options) {
7
8
  return async (iter, calls) => {
8
9
  for (const call of calls || []) {
10
+ // A bridged call reports the tool it runs; the transcript keeps the wire call.
11
+ const identity = toolCallDisplayIdentity(call?.name, call?.arguments);
9
12
  hooks.emit('tool:planned', {
10
13
  sessionId: session0.id,
11
- name: call?.name || 'tool',
14
+ name: identity.name || 'tool',
12
15
  callId: call?.id || null,
16
+ ...(identity.via ? { via: identity.via } : {}),
13
17
  });
14
18
  }
15
19
  if (typeof options.onToolCall === 'function') {
@@ -71,6 +75,8 @@ export function createAskCallbacks({ transcript, notifyFnForSession, scheduleSea
71
75
  transcriptMeta: stampCheckpoint(options),
72
76
  promptSource: options.promptSource,
73
77
  retryFailedTurn: options.retryFailedTurn === true,
78
+ retryTurnId: options.retryTurnId,
79
+ retryAttemptId: options.retryAttemptId,
74
80
  onTextDelta: options.onTextDelta,
75
81
  onTextReset: options.onTextReset,
76
82
  onReasoningDelta: options.onReasoningDelta,
@@ -23,6 +23,7 @@ export function createTurnPreparation({
23
23
  assertSessionAdmission,
24
24
  prepareTurnWorkspace,
25
25
  admitTurnWorkspace,
26
+ applyPendingRoute,
26
27
  }) {
27
28
  const scopedMcpTools = (session) => scopedMcpToolsFor(session, getConfig());
28
29
 
@@ -49,9 +50,9 @@ export function createTurnPreparation({
49
50
  // Slower servers remain available through the late-tool path; a reconnect
50
51
  // in flight gets the same short TTFT grace BEFORE folding the catalog so it
51
52
  // cannot hold the provider request. No reconnect in flight → no-op.
52
- const awaitGrace = async () => {
53
+ const awaitGrace = async (options) => {
53
54
  try {
54
- await turn.awaitTurn(() => turn.timing.awaitMcpGrace());
55
+ await turn.awaitTurn(() => turn.timing.awaitMcpGrace(options));
55
56
  } catch {
56
57
  /* gate must never break the turn */
57
58
  }
@@ -64,7 +65,12 @@ export function createTurnPreparation({
64
65
  // One-shot: cleared before the fold so a throw still never re-runs it,
65
66
  // and a resumed session (flag unset) skips straight to the late path.
66
67
  session0.deferredInitialRefreshPending = false;
67
- await awaitGrace();
68
+ // A spawned agent runtime owns a fresh MCP scope whose connect starts at
69
+ // its boot, so the 0 ms default grace would hide every MCP tool from the
70
+ // agent's first (often only) turn. Agents are not on the user's TTFT
71
+ // path: wait for the initial connect within the server startup budget.
72
+ const agentOwned = session0.owner === 'agent' || session0.visibility === 'agent-only';
73
+ await awaitGrace({ untilConnected: agentOwned });
68
74
  try {
69
75
  refreshInitialDeferredMcpSurface(session0, scopedMcpTools(session0));
70
76
  } catch {
@@ -124,6 +130,9 @@ export function createTurnPreparation({
124
130
  throwIfAborted(turn.signal);
125
131
  assertSessionAdmission?.();
126
132
  }
133
+ const modelSwitch = applyPendingRoute?.();
134
+ options.onRouteApplied?.(getSession());
135
+ if (modelSwitch) options.onModelSwitch?.(modelSwitch);
127
136
  ensureSessionTranscriptWriter?.();
128
137
  transcript.appendUser(prompt);
129
138
  const session0 = getSession();
@@ -28,6 +28,8 @@ export function createTurnSettlement({
28
28
  setFirstTurnCompleted,
29
29
  scheduleProviderWarmup,
30
30
  scheduleProviderModelWarmup,
31
+ takePendingCompact,
32
+ runPendingCompact,
31
33
  }) {
32
34
  async function completeTurn(turn, session0, result) {
33
35
  throwIfAborted(turn.signal);
@@ -84,11 +86,16 @@ export function createTurnSettlement({
84
86
  turn.releaseFirstTitle?.();
85
87
  turn.emitTiming(turn.timing.status);
86
88
  turn.armHeavyRuntimeWarmup('turn-settled');
89
+ let settleError;
87
90
  try {
88
91
  await turn.snapshot.finish(turn.signal, turn.awaitTurn);
89
- } finally {
90
- // The turn no longer works in its checkout: transitions may proceed.
92
+ } catch (error) {
93
+ settleError = error;
94
+ }
95
+ try {
91
96
  turn.releaseWorkspace?.();
97
+ } catch (error) {
98
+ settleError = settleError ? new AggregateError([settleError, error], 'Turn cleanup failed.') : error;
92
99
  }
93
100
  try {
94
101
  turn.unregister?.();
@@ -99,6 +106,15 @@ export function createTurnSettlement({
99
106
  /* lead pool must never break turn teardown */
100
107
  }
101
108
  setActiveTurnCount(Math.max(0, getActiveTurnCount() - 1));
109
+ if (settleError) throw settleError;
110
+ // A compaction the model scheduled (session tool) runs once the turn is over.
111
+ // Only while the settled session is still the live one; otherwise it stays
112
+ // pending for that session and never compacts another. The runner chains
113
+ // the compaction so the next turn waits on it.
114
+ const settledId = turn.session0?.id;
115
+ if (getActiveTurnCount() === 0 && settledId && getSession()?.id === settledId && takePendingCompact?.(settledId)) {
116
+ runPendingCompact?.(settledId);
117
+ }
102
118
  if (!isFirstTurnCompleted()) {
103
119
  setFirstTurnCompleted(true);
104
120
  scheduleProviderWarmup();
@@ -38,11 +38,12 @@ export function createTurnTimingFactory({ getSession, awaitInitialMcpConnect, mc
38
38
  /* timing telemetry must never affect a turn */
39
39
  }
40
40
  };
41
- // Give an in-flight MCP connect only a short TTFT grace.
42
- timing.awaitMcpGrace = async () => {
41
+ // Give an in-flight MCP connect only a short TTFT grace. untilConnected
42
+ // waits for the initial connect bounded only by the server startup budget.
43
+ timing.awaitMcpGrace = async ({ untilConnected = false } = {}) => {
43
44
  const graceStartedAt = performance.now();
44
45
  try {
45
- await awaitInitialMcpConnect?.(mcpTurnGraceMs);
46
+ await awaitInitialMcpConnect?.(untilConnected ? undefined : mcpTurnGraceMs);
46
47
  } finally {
47
48
  timing.mcpWaitMs += performance.now() - graceStartedAt;
48
49
  }
@@ -1,6 +1,5 @@
1
1
  /**
2
- * src/session-runtime/turn/turn-run.mjs - one user turn end to end: viewer
3
- * forwarding, turn open (abort controller, timing, warmup arming), session
2
+ * src/session-runtime/turn/turn-run.mjs - one user turn end to end: turn open (abort controller, timing, warmup arming), session
4
3
  * preparation (workspace provisioning, then the worktree review snapshot), the
5
4
  * askSession callback bridge, and the settlement that always runs. The phases
6
5
  * live under turn-run/.
@@ -13,6 +12,7 @@ import { createSnapshotTrackerFactory } from './turn-run/snapshot-tracker.mjs';
13
12
  import { createTurnOpener } from './turn-run/turn-open.mjs';
14
13
  import { createTurnPreparation } from './turn-run/turn-prepare.mjs';
15
14
  import { createAskCallbacks } from './turn-run/ask-callbacks.mjs';
15
+ import { registerNativeWebSearchUsageSink } from '../native-web-search-usage.mjs';
16
16
  import { createTurnSettlement } from './turn-run/turn-settle.mjs';
17
17
 
18
18
  export function createTurnRunner(deps) {
@@ -48,18 +48,6 @@ export function createTurnRunner(deps) {
48
48
  deferComputerSessionRelease,
49
49
  });
50
50
 
51
- const enqueueRemoteAttachedPrompt = (prompt) => {
52
- const attachedSession = getSession();
53
- if (!attachedSession?.remoteAttached || !attachedSession.id) return false;
54
- try {
55
- // prompt may be a string or { content/text, id } so the submission id
56
- // survives spool fallback after a live-share ack miss.
57
- return Number(mgr.enqueueRemotePendingMessage?.(attachedSession.id, prompt)) > 0;
58
- } catch {
59
- return false;
60
- }
61
- };
62
-
63
51
  function getTurnLiveness() {
64
52
  const sessionId = getSession()?.id;
65
53
  if (!sessionId || typeof mgr.getSessionProgressSnapshot !== 'function') return null;
@@ -68,41 +56,35 @@ export function createTurnRunner(deps) {
68
56
  return { ...snapshot };
69
57
  }
70
58
 
71
- // Remote-attach: this surface is a viewer on a session that another live
72
- // process owns. Never run a turn here — persist the prompt into the shared
73
- // pending spool; the owner's injection poller submits it as a normal user
74
- // turn and this surface refreshes from disk.
75
- function forwardAttachedPrompt(attachedSession, prompt, options) {
76
- // Carry the submission id into the spool: the owner reuses it for the
77
- // queue entry and the settled user row, so the submitting surface's
78
- // optimistic bubble is reconciled with the mirrored row.
79
- const submissionId = String(options.id || '').trim();
80
- const delivered = enqueueRemoteAttachedPrompt(submissionId ? { content: prompt, id: submissionId } : prompt);
81
- return {
82
- // This branch is only a race-safe fallback for callers that reached
83
- // ask() before the live pipe was ready. Never manufacture an
84
- // assistant response: the owner's mirrored transcript is authoritative.
85
- result: { content: '', remoteAttached: true, delivered },
86
- session: attachedSession,
87
- };
88
- }
89
-
90
59
  async function runTurn(prompt, options) {
91
- const attachedSession = getSession();
92
- if (attachedSession?.remoteAttached) return forwardAttachedPrompt(attachedSession, prompt, options);
93
60
  const turn = openTurn(options);
94
61
  try {
95
62
  const session0 = await prepareSession(turn, prompt, options);
96
63
  const turnContext = await dispatchPromptSubmit(turn, session0, prompt, options);
97
- const result = await mgr.askSession(
98
- session0.id,
99
- prompt,
100
- turnContext || null,
101
- plannedToolCalls(session0, options),
102
- getCurrentCwd(),
103
- options.prefetch || null,
104
- askCallbacks(turn, session0, options)
105
- );
64
+ const callbacks = askCallbacks(turn, session0, options);
65
+ // Register only once askSession's session lock is held: the first
66
+ // provider send of this turn. A turn queued behind another on the same
67
+ // session id therefore never receives the running turn's search usage.
68
+ let releaseWebSearchUsage = null;
69
+ const providerSendStarted = callbacks.onProviderSendStarted;
70
+ callbacks.onProviderSendStarted = (...args) => {
71
+ releaseWebSearchUsage ??= registerNativeWebSearchUsageSink(session0.id, options.onNativeWebSearchUsage);
72
+ return providerSendStarted(...args);
73
+ };
74
+ let result;
75
+ try {
76
+ result = await mgr.askSession(
77
+ session0.id,
78
+ prompt,
79
+ turnContext || null,
80
+ plannedToolCalls(session0, options),
81
+ getCurrentCwd(),
82
+ options.prefetch || null,
83
+ callbacks
84
+ );
85
+ } finally {
86
+ releaseWebSearchUsage?.();
87
+ }
106
88
  return await completeTurn(turn, session0, result);
107
89
  } catch (error) {
108
90
  reportTurnError(turn, error);
@@ -113,7 +95,6 @@ export function createTurnRunner(deps) {
113
95
  }
114
96
 
115
97
  return {
116
- enqueueRemoteAttachedPrompt,
117
98
  getTurnLiveness,
118
99
  ask: (prompt, options = {}) => runWithCwdOverride(getCurrentCwd(), () => runTurn(prompt, options)),
119
100
  };
@@ -82,22 +82,43 @@ function accountsInUse(accountPool) {
82
82
  return inUse;
83
83
  }
84
84
 
85
- // Every id a session's spend was recorded under: its own, and the per-account
86
- // provider session each subscription account sent it under before account
87
- // sends recorded the visible session.
88
- function sessionUsageIds(sessionId, accountPool) {
89
- const ids = [sessionId];
85
+ // Each subscription provider's account ids, read once per request.
86
+ function accountScopes(accountPool) {
87
+ const scopes = [];
90
88
  for (const provider of ACCOUNT_PROVIDERS) {
91
89
  try {
92
- for (const account of accountPool(provider).accounts)
93
- ids.push(accountScopedSessionId(provider, account.id, sessionId));
90
+ scopes.push([provider, accountPool(provider).accounts.map((account) => account.id)]);
94
91
  } catch {
95
92
  /* an unreadable pool leaves that provider's older records out */
96
93
  }
97
94
  }
95
+ return scopes;
96
+ }
97
+
98
+ // Every id a session's spend was recorded under: its own, and the per-account
99
+ // provider session each subscription account sent it under before account
100
+ // sends recorded the visible session.
101
+ function sessionUsageIdsFor(scopes, sessionId) {
102
+ const ids = [sessionId];
103
+ for (const [provider, accounts] of scopes) {
104
+ for (const account of accounts) ids.push(accountScopedSessionId(provider, account, sessionId));
105
+ }
98
106
  return ids;
99
107
  }
100
108
 
109
+ // Other sessions a caller asks about beside its own (the composer island's
110
+ // agent sessions): bounded, distinct, never the caller's own id.
111
+ const MAX_SESSION_USAGE_IDS = 64;
112
+ function otherSessionIds(options, sessionId) {
113
+ const ids = Array.isArray(options?.sessionIds) ? options.sessionIds : [];
114
+ const unique = new Set();
115
+ for (const id of ids) {
116
+ if (typeof id === 'string' && id && id !== sessionId) unique.add(id);
117
+ if (unique.size >= MAX_SESSION_USAGE_IDS) break;
118
+ }
119
+ return [...unique];
120
+ }
121
+
101
122
  /** `null` = all time. `0` = today. Anything else is a trailing day count. */
102
123
  function normalizeDays(value) {
103
124
  if (value === null || value === undefined || value === 'all') return null;
@@ -213,15 +234,29 @@ export function createUsageStatsApi({
213
234
  return snapshot;
214
235
  },
215
236
 
216
- /** This runtime's session from its first request, compactions included; null before it has one. */
217
- async getSessionUsage() {
237
+ /**
238
+ * This runtime's session from its first request, compactions included; null before it has one.
239
+ * `sessionIds` adds the same totals for each named session (the agents it spawned) under
240
+ * `sessions`, each read by its own id only.
241
+ */
242
+ async getSessionUsage(options = {}) {
218
243
  const sessionId = getSessionId();
219
244
  if (!sessionId) return null;
220
245
  const store = ledger();
221
246
  if (!store) throw new Error('Usage ledger is unavailable');
222
247
  await store.settleWrites();
223
- const usage = await store.sessionUsageAsync(sessionUsageIds(sessionId, accountPool));
224
- return { sessionId, ...sessionUsageSnapshot(usage) };
248
+ const scopes = accountScopes(accountPool);
249
+ const usage = await store.sessionUsageAsync(sessionUsageIdsFor(scopes, sessionId));
250
+ const result = { sessionId, ...sessionUsageSnapshot(usage) };
251
+ const others = otherSessionIds(options, sessionId);
252
+ if (!others.length) return result;
253
+ const totals = await Promise.all(
254
+ others.map(async (id) => [
255
+ id,
256
+ sessionUsageSnapshot(await store.sessionUsageAsync(sessionUsageIdsFor(scopes, id))),
257
+ ])
258
+ );
259
+ return { ...result, sessions: Object.fromEntries(totals) };
225
260
  },
226
261
 
227
262
  /**
@@ -6,6 +6,7 @@ import { ensureProviderEnabled } from '../../runtime/agent/orchestrator/runtime-
6
6
  import { resolveRouteContextState, selectionFastCapable } from '../route-state.mjs';
7
7
  import { canonicalizeAgentRouteStorage, withAgentDisabled } from '../../runtime/shared/agent-route-config.mjs';
8
8
  import { agentEditorId } from './shared.mjs';
9
+ import { routeChain, validateRouteChainProviders } from '../../runtime/shared/model-route-chain.mjs';
9
10
 
10
11
  // Agent route persistence. Route-scope isolation: an agent route owns its
11
12
  // model AND its effort/fast, stored in config.agents[<id>]. The shared
@@ -109,7 +110,21 @@ export function createAgentRouteApi(deps) {
109
110
  }
110
111
  if (!clean(requested.provider)) return clearOverride(id);
111
112
  if (!clean(requested.model)) throw new Error('agent route requires provider and model');
112
- const routeToSave = normalizeWorkflowRoute(await resolveSelectedRoute(requested, stored));
113
+ const chain = routeChain({
114
+ ...requested,
115
+ fallbacks: hasOwn(requested, 'fallbacks') ? requested.fallbacks : stored.fallbacks,
116
+ });
117
+ validateRouteChainProviders(chain);
118
+ const storedChain = routeChain(stored);
119
+ const resolved = [];
120
+ for (const entry of chain) {
121
+ const previous = storedChain.find(
122
+ (candidate) => candidate.provider === entry.provider && candidate.model === entry.model
123
+ );
124
+ resolved.push(await resolveSelectedRoute(entry, previous || {}));
125
+ }
126
+ const [primary, ...fallbacks] = resolved;
127
+ const routeToSave = normalizeWorkflowRoute({ ...primary, fallbacks });
113
128
  if (!routeToSave) throw new Error('agent route requires provider and model');
114
129
  // Picking a model is also the "on" switch unless the request keeps it off.
115
130
  const nextConfig = withAgentDisabled(getConfig(), id, keepOff);
@@ -13,9 +13,11 @@
13
13
  * - Each worktree-bound Lead's execution root, which every worker of that Lead
14
14
  * runs in.
15
15
  */
16
- import { worktreeError } from '../../runtime/shared/worktrees/contract.mjs';
16
+ import { worktreeError, worktreeRefusal } from '../../runtime/shared/worktrees/contract.mjs';
17
17
  import { throwIfAborted } from '../../runtime/shared/worktrees/git.mjs';
18
18
  import { isWithin } from '../../runtime/shared/worktrees/paths.mjs';
19
+ import { tryAdmitWorkspaceActivity } from '../../runtime/shared/worktrees/activity-gate.mjs';
20
+ import { setTimeout as delay } from 'node:timers/promises';
19
21
 
20
22
  /** @type {Map<string, { txId: string, settled: Promise<void> }>} Lead session id → in-flight transition. */
21
23
  const transitions = new Map();
@@ -42,8 +44,8 @@ function once(fn) {
42
44
  let done = false;
43
45
  return () => {
44
46
  if (done) return;
45
- done = true;
46
47
  fn();
48
+ done = true;
47
49
  };
48
50
  }
49
51
 
@@ -78,21 +80,18 @@ export function beginWorkspaceTransition(sessionId, txId) {
78
80
  * admitted turn runs inside it, and (`transition`) while another change holds
79
81
  * an overlapping checkout; turns arriving meanwhile wait (admitTurn). The
80
82
  * holder's own turns are its own business (the Lead busy check).
83
+ * `hold: false` (an external checkout, never lock-blocked) only refuses.
81
84
  * @param {string|null} sessionId The changing session; '' / null for a session-less change.
82
85
  * @returns {() => void} Release.
83
86
  */
84
- export function holdCheckoutFolder(sessionId, folder) {
87
+ export function holdCheckoutFolder(sessionId, folder, { hold = true } = {}) {
85
88
  const id = key(sessionId);
86
89
  const users = new Set();
87
90
  for (const turn of turns.values()) {
88
91
  if (turn.sessionId !== id && within(folder, turn.cwd())) users.add(turn.sessionId);
89
92
  }
90
- if (users.size) {
91
- throw worktreeError('WORKTREE_BUSY_JOBS', 'Other sessions are working in the project folder.', {
92
- reason: 'folder-in-use',
93
- sessions: [...users],
94
- });
95
- }
93
+ if (users.size) throw worktreeRefusal('folder-in-use', { sessions: [...users] });
94
+ if (!hold) return () => {};
96
95
  if ([...folderHolds.values()].some((hold) => within(hold.folder, folder) || within(folder, hold.folder))) {
97
96
  throw worktreeError('WORKTREE_BUSY_JOBS', 'Another branch change is in progress in the project folder.', {
98
97
  reason: 'transition',
@@ -145,14 +144,44 @@ function settledOrAborted(promise, signal) {
145
144
  */
146
145
  export async function admitTurn({ sessionId, cwd, signal }) {
147
146
  const id = key(sessionId);
148
- for (let blocker = admissionBlocker(id, cwd); blocker; blocker = admissionBlocker(id, cwd)) {
147
+ for (;;) {
149
148
  throwIfAborted(signal);
150
- await settledOrAborted(blocker, signal);
149
+ const blocker = admissionBlocker(id, cwd);
150
+ if (blocker) {
151
+ await settledOrAborted(blocker, signal);
152
+ continue;
153
+ }
154
+ const release = tryAdmitWorkspaceActivity(id, cwd());
155
+ if (!release) {
156
+ await delay(100, undefined, { signal });
157
+ continue;
158
+ }
159
+ const token = Symbol('turn');
160
+ const leases = [release];
161
+ turns.set(token, { sessionId: id, cwd, leases });
162
+ return once(() => {
163
+ const errors = [];
164
+ for (const leave of leases) {
165
+ try {
166
+ leave();
167
+ } catch (error) {
168
+ errors.push(error);
169
+ }
170
+ }
171
+ turns.delete(token);
172
+ if (errors.length) throw new AggregateError(errors, 'Workspace admission could not be released.');
173
+ });
174
+ }
175
+ }
176
+
177
+ /** Keep the old root protected and acquire the destination before an admitted turn moves. */
178
+ export function retainAdmittedTurnWorkspace(sessionId, cwd) {
179
+ for (const turn of turns.values()) {
180
+ if (turn.sessionId !== key(sessionId) || turn.cwd() === cwd) continue;
181
+ const leave = tryAdmitWorkspaceActivity(sessionId, cwd);
182
+ if (!leave) throw worktreeRefusal('folder-in-use');
183
+ turn.leases.push(leave);
151
184
  }
152
- throwIfAborted(signal);
153
- const token = Symbol('turn');
154
- turns.set(token, { sessionId: id, cwd });
155
- return once(() => turns.delete(token));
156
185
  }
157
186
 
158
187
  /**
@@ -2,42 +2,32 @@
2
2
  * Session-less branch operations on a registered Project's folder (a New
3
3
  * Task draft, the source-control dock): its branch menu, a guarded checkout
4
4
  * and a guarded merge. They act only on a registered Project (a repository
5
- * subfolder Project included) and hold the checkout (withProjectFolder) while
6
- * git changes it.
5
+ * subfolder Project included): a checkout holds the folder (withProjectFolder)
6
+ * while git changes it, a merge takes the shared management path.
7
7
  */
8
8
  import { branchMenuEntries, projectWorkspace, worktreeError } from '../../runtime/shared/worktrees/contract.mjs';
9
+ import * as branchManagement from '../../runtime/shared/worktrees/branch-management.mjs';
9
10
 
10
11
  function requireText(value, name) {
11
12
  if (typeof value !== 'string' || !value.trim()) throw new TypeError(`${name} must be a non-empty string.`);
12
13
  return value.trim();
13
14
  }
14
15
 
15
- /**
16
- * WORKTREE_UNSUPPORTED_REPO when the project folder has no checked-out branch
17
- * to merge into; WORKTREE_TARGET_MISMATCH when the confirmed `target` (null:
18
- * none confirmed) is no longer the checked-out branch.
19
- */
20
- export function assertMergeTarget(currentBranch, target) {
21
- if (!currentBranch) {
22
- throw worktreeError('WORKTREE_UNSUPPORTED_REPO', 'The project folder has no checked-out branch to merge into.');
23
- }
24
- if (target !== null && target !== currentBranch) {
25
- throw worktreeError(
26
- 'WORKTREE_TARGET_MISMATCH',
27
- `The project folder is now on "${currentBranch}"; confirm the merge again.`,
28
- { target, current: currentBranch }
29
- );
30
- }
31
- }
32
-
33
16
  /**
34
17
  * @param {object} deps
35
18
  * @param {() => Promise<any>} deps.backend The managed-worktree backend.
36
19
  * @param {(path: string) => Promise<any>} deps.inspectProject
37
20
  * @param {(path: string) => Promise<string|null>} deps.findRegisteredProject
38
21
  * @param {<T>(sessionId: string|null, folder: string, fn: () => Promise<T>) => Promise<T>} deps.withProjectFolder
22
+ * @param {Function} deps.withManagementFolders The shared admission of every merge and cleanup.
39
23
  */
40
- export function createProjectBranchOps({ backend, inspectProject, findRegisteredProject, withProjectFolder }) {
24
+ export function createProjectBranchOps({
25
+ backend,
26
+ inspectProject,
27
+ findRegisteredProject,
28
+ withProjectFolder,
29
+ withManagementFolders,
30
+ }) {
41
31
  /** WORKTREE_PROJECT_UNKNOWN unless `projectPath` is a registered Project. */
42
32
  async function registeredProject(projectPath) {
43
33
  const path = requireText(projectPath, 'projectPath');
@@ -54,12 +44,14 @@ export function createProjectBranchOps({ backend, inspectProject, findRegistered
54
44
  const path = await registeredProject(projectPath);
55
45
  const project = await inspectProject(path);
56
46
  const menu = await (await backend()).listBranchOccupancy({ projectPath: path, sessionId: null });
47
+ const workspace = projectWorkspace({
48
+ projectPath: path,
49
+ repoCommonDir: project.repoCommonDir,
50
+ branch: project.currentBranch,
51
+ });
57
52
  return {
58
- workspace: projectWorkspace({
59
- projectPath: path,
60
- repoCommonDir: project.repoCommonDir,
61
- branch: project.currentBranch,
62
- }),
53
+ // Detached: branch null and the checked-out commit in baseCommit.
54
+ workspace: project.currentBranch ? workspace : { ...workspace, baseCommit: project.headCommit ?? null },
63
55
  branches: branchMenuEntries(menu.branches, menu.occupancy),
64
56
  occupancy: menu.occupancy,
65
57
  retainedWorktree: null,
@@ -112,25 +104,27 @@ export function createProjectBranchOps({ backend, inspectProject, findRegistered
112
104
  /**
113
105
  * Merge a local branch into a Project folder's checked-out branch with no
114
106
  * session: `target` is the branch the user confirmed and must still be
115
- * checked out (WORKTREE_TARGET_MISMATCH); refused while another session
116
- * works in that checkout, which is held (turn admission waits) until the
117
- * merge is done.
107
+ * checked out (WORKTREE_TARGET_MISMATCH). The same guarded path as the
108
+ * branch-row merge (manageProjectBranch): source and destination validated
109
+ * and both folders held.
118
110
  */
119
111
  async function mergeProjectBranch({ projectPath, branch, target } = {}) {
120
112
  const path = await registeredProject(projectPath);
121
- const source = requireText(branch, 'branch');
122
- const confirmedTarget = requireText(target, 'target');
123
- const project = await inspectProject(path);
124
- assertMergeTarget(project.currentBranch, confirmedTarget);
125
- return withProjectFolder(null, project.topLevel || path, async () =>
126
- (await backend()).mergeBranchIntoProject({
127
- projectPath: path,
128
- source,
129
- target: confirmedTarget,
130
- confirmed: true,
131
- })
113
+ return branchManagement.mergeConfirmedTarget(
114
+ { projectPath: path, branch: requireText(branch, 'branch'), target: requireText(target, 'target') },
115
+ withManagementFolders
132
116
  );
133
117
  }
134
118
 
135
- return { getProjectBranchMenu, selectProjectBranch, mergeProjectBranch };
119
+ async function inspectProjectBranch({ projectPath, branch } = {}) {
120
+ const path = await registeredProject(projectPath);
121
+ return branchManagement.inspectProjectBranch({ projectPath: path, branch: requireText(branch, 'branch') });
122
+ }
123
+
124
+ async function manageProjectBranch(input = {}) {
125
+ const path = await registeredProject(input.projectPath);
126
+ return branchManagement.manageProjectBranch({ ...input, projectPath: path }, withManagementFolders);
127
+ }
128
+
129
+ return { getProjectBranchMenu, selectProjectBranch, mergeProjectBranch, inspectProjectBranch, manageProjectBranch };
136
130
  }