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
@@ -3,11 +3,12 @@
3
3
  // caller's spec, creation of the runtime behind it, and the descriptor linked
4
4
  // into the agent registry. Running a turn on that child is ./agent-turns.mjs.
5
5
 
6
- export function createAgentChildFactory({ registry, rehydrateAgentSessions, createSession }) {
6
+ export function createAgentChildFactory({ registry, rehydrateAgentSessions, createSession, entryForSession }) {
7
7
  return async function createAgentChild({ spec = {}, tag = null } = {}) {
8
8
  await rehydrateAgentSessions();
9
9
  const parentSessionId = String(spec.parentSessionId || '').trim();
10
10
  if (!parentSessionId) throw new TypeError('agent child parentSessionId is required');
11
+ const parentEpoch = registry.assertAdmission(parentSessionId);
11
12
  const ownerSessionId = String(
12
13
  spec.ownerSessionId || registry.get(parentSessionId)?.ownerSessionId || parentSessionId
13
14
  );
@@ -29,6 +30,7 @@ export function createAgentChildFactory({ registry, rehydrateAgentSessions, crea
29
30
  sourceType: spec.sourceType || 'agent',
30
31
  sourceName: spec.sourceName || spec.agent || 'agent',
31
32
  clientHostPid: spec.clientHostPid || null,
33
+ ...(preset.fallbacks !== undefined ? { routeFallbacks: preset.fallbacks } : {}),
32
34
  };
33
35
  const created = await createSession({
34
36
  cwd: spec.cwd || process.cwd(),
@@ -45,6 +47,22 @@ export function createAgentChildFactory({ registry, rehydrateAgentSessions, crea
45
47
  toolMode: 'full',
46
48
  sessionProfile,
47
49
  });
50
+ try {
51
+ registry.assertAdmission(parentSessionId, parentEpoch);
52
+ } catch (error) {
53
+ // The parent was cancelled while the runtime was being created: close it
54
+ // like any cancelled child instead of leaving it unlinked and open.
55
+ try {
56
+ const entry = await entryForSession?.(created.sessionId, {
57
+ cwd: spec.cwd || process.cwd(),
58
+ provider,
59
+ model,
60
+ toolMode: 'full',
61
+ });
62
+ await entry?.runtime?.closeCanonicalSession?.('parent cancelled during agent creation', { tombstone: false });
63
+ } catch {}
64
+ throw error;
65
+ }
48
66
  const descriptor = registry.linkAgentDescriptor({
49
67
  id: created.sessionId,
50
68
  ...sessionProfile,
@@ -6,6 +6,8 @@ export const SESSION_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
6
6
  export function createAgentRegistry() {
7
7
  const agentSessions = new Map();
8
8
  const agentChildren = new Map();
9
+ const cancellationCounts = new Map();
10
+ const cancellationEpochs = new Map();
9
11
 
10
12
  function linkAgentDescriptor(descriptor) {
11
13
  const sessionId = String(descriptor?.id || '').trim();
@@ -54,6 +56,27 @@ export function createAgentRegistry() {
54
56
  }
55
57
 
56
58
  return {
59
+ assertAdmission(id, epoch = cancellationEpochs.get(id) || 0) {
60
+ if (cancellationCounts.has(id) || (cancellationEpochs.get(id) || 0) !== epoch) {
61
+ throw new Error(`agent session ${id} was cancelled during admission`);
62
+ }
63
+ return epoch;
64
+ },
65
+ beginCancellation(ids) {
66
+ for (const id of ids) {
67
+ cancellationCounts.set(id, (cancellationCounts.get(id) || 0) + 1);
68
+ cancellationEpochs.set(id, (cancellationEpochs.get(id) || 0) + 1);
69
+ }
70
+ return () => {
71
+ for (const id of ids) {
72
+ const remaining = (cancellationCounts.get(id) || 0) - 1;
73
+ if (remaining > 0) cancellationCounts.set(id, remaining);
74
+ else cancellationCounts.delete(id);
75
+ }
76
+ };
77
+ },
78
+ isCancelling: (id) => cancellationCounts.has(id),
79
+ cancellationEpoch: (id) => cancellationEpochs.get(id) || 0,
57
80
  linkAgentDescriptor,
58
81
  agentDescendantSessionIds,
59
82
  get: (sessionId) => agentSessions.get(String(sessionId || '').trim()),
@@ -68,6 +91,8 @@ export function createAgentRegistry() {
68
91
  clear() {
69
92
  agentSessions.clear();
70
93
  agentChildren.clear();
94
+ cancellationCounts.clear();
95
+ cancellationEpochs.clear();
71
96
  },
72
97
  };
73
98
  }
@@ -14,7 +14,12 @@ export function createAgentTurns({
14
14
  takeWatchdogStop,
15
15
  takeCancelTranscript,
16
16
  }) {
17
- const createAgentChild = createAgentChildFactory({ registry, rehydrateAgentSessions, createSession });
17
+ const createAgentChild = createAgentChildFactory({
18
+ registry,
19
+ rehydrateAgentSessions,
20
+ createSession,
21
+ entryForSession,
22
+ });
18
23
 
19
24
  // The turn was stopped (progress watchdog or cancellation): rethrow its error
20
25
  // carrying the assistant text the turn produced, so the owner still gets a
@@ -35,6 +40,7 @@ export function createAgentTurns({
35
40
  async function runAgentTurn({ session, prompt, context = null, onToolResult, onTerminalResult } = {}) {
36
41
  await rehydrateAgentSessions();
37
42
  const sessionId = String(session?.id || session || '').trim();
43
+ const cancelEpoch = registry.assertAdmission(sessionId);
38
44
  const descriptor = registry.get(sessionId);
39
45
  if (!descriptor || descriptor.closed) {
40
46
  throw new Error(`agent session ${sessionId || '(empty)'} is closed`);
@@ -46,6 +52,7 @@ export function createAgentTurns({
46
52
  toolMode: 'full',
47
53
  });
48
54
  const target = entry.runtime.submitAndWait;
55
+ registry.assertAdmission(sessionId, cancelEpoch);
49
56
  if (typeof target !== 'function') {
50
57
  throw new TypeError('session runtime must implement submitAndWait');
51
58
  }
@@ -55,6 +62,7 @@ export function createAgentTurns({
55
62
  // Transcript length before this turn: where a watchdog stop's partial
56
63
  // output starts.
57
64
  const { messageCount: messageStart } = await entry.runtime.readModelMessages(Number.MAX_SAFE_INTEGER);
65
+ registry.assertAdmission(sessionId, cancelEpoch);
58
66
  descriptor.status = 'running';
59
67
  descriptor.stage = 'running';
60
68
  descriptor.updatedAt = Date.now();
@@ -109,9 +109,34 @@ export function createAgentTree({
109
109
  canRun: (session) => Boolean(registry.get(session?.id)),
110
110
  createChild: createAgentChild,
111
111
  runTurn: runAgentTurn,
112
+ /** A model or tuning change for a reused child goes through the session's
113
+ * own route API: saved at once, applied from the next turn (never refused
114
+ * because a turn is running). `route` may be partial; the route write
115
+ * completes it against the latest selected route. The descriptor follows
116
+ * the selected route. */
117
+ async setRoute({ session, route }) {
118
+ const descriptor = registry.get(session?.id);
119
+ if (!descriptor || descriptor.closed) throw new Error('agent session is closed');
120
+ const entry = await entryForSession(descriptor.id, {
121
+ cwd: descriptor.cwd,
122
+ provider: descriptor.provider,
123
+ model: descriptor.model,
124
+ toolMode: 'full',
125
+ });
126
+ try {
127
+ const applied = await entry.runtime.setRoute({ ...route, sessionOnly: true });
128
+ descriptor.provider = applied?.provider || route.provider || descriptor.provider;
129
+ descriptor.model = applied?.model || route.model || descriptor.model;
130
+ descriptor.updatedAt = Date.now();
131
+ return applied;
132
+ } finally {
133
+ retainUnwatched(entry, 'agent route change');
134
+ }
135
+ },
112
136
  async enqueueTurn({ session, prompt, context = null }) {
113
137
  const descriptor = registry.get(session?.id);
114
138
  if (!descriptor || descriptor.closed) throw new Error('agent session is closed');
139
+ const cancelEpoch = registry.assertAdmission(descriptor.id);
115
140
  const runtime = sessionOwner(descriptor.id)?.runtime;
116
141
  if (!runtime || !stateBusy(runtime.getState())) return null;
117
142
  const accepted = await runtime.submitAsync(String(prompt || ''), {
@@ -122,6 +147,7 @@ export function createAgentTree({
122
147
  transcriptMeta: { sender: 'lead' },
123
148
  });
124
149
  if (accepted === false) throw new Error('agent follow-up was not accepted');
150
+ registry.assertAdmission(descriptor.id, cancelEpoch);
125
151
  return { queueDepth: runtime.getState()?.queued?.length ?? null };
126
152
  },
127
153
  });
@@ -167,9 +193,9 @@ export function createAgentTree({
167
193
  if (handoff) descriptor.lastHandoff = handoff;
168
194
  return handoff;
169
195
  },
170
- async closeSession(sessionId, reason = 'agent session closed') {
196
+ async closeSession(sessionId, reason = 'agent session closed', options = {}) {
171
197
  await rehydrateAgentSessions();
172
- return cancelAgentTree(sessionId, reason);
198
+ return cancelAgentTree(sessionId, reason, options);
173
199
  },
174
200
  unloadSessionRuntime: (sessionId) => {
175
201
  progress.delete(sessionId);
@@ -6,6 +6,7 @@
6
6
  // converge on one runtime.
7
7
 
8
8
  export function createSessionLoads({
9
+ pendingViewers,
9
10
  sessionExists,
10
11
  log,
11
12
  assertAvailable,
@@ -20,12 +21,21 @@ export function createSessionLoads({
20
21
  const sessionLoads = new Map(); // sessionId -> Promise<entry>
21
22
 
22
23
  function getOrCreateSessionEntry(sessionId, create) {
23
- const owner = sessionOwner(sessionId);
24
- if (owner) return Promise.resolve(owner);
25
24
  const inFlight = sessionLoads.get(sessionId);
26
25
  if (inFlight) return inFlight;
27
26
  const loading = Promise.resolve()
28
- .then(create)
27
+ .then(async () => {
28
+ const owner = sessionOwner(sessionId);
29
+ if (owner) {
30
+ if ((await owner.runtime.isSessionTerminal?.()) !== true) return owner;
31
+ if (owner.subscribers?.size) {
32
+ if (!pendingViewers.has(sessionId)) pendingViewers.set(sessionId, new Set());
33
+ for (const subscriber of owner.subscribers) pendingViewers.get(sessionId).add(subscriber);
34
+ }
35
+ await destroy(owner, 'replace terminal runtime', { keepBackgroundWork: true, announce: false });
36
+ }
37
+ return create();
38
+ })
29
39
  .finally(() => {
30
40
  if (sessionLoads.get(sessionId) === loading) sessionLoads.delete(sessionId);
31
41
  });
@@ -84,11 +94,12 @@ export function createSessionLoads({
84
94
  * flight), or null where answering would take a fresh load. */
85
95
  async function hostedEntryForSession(sessionId) {
86
96
  assertAvailable();
97
+ if (sessionLoads.has(sessionId)) return sessionLoads.get(sessionId);
87
98
  const owner = sessionOwner(sessionId);
88
- if (owner) return owner;
99
+ if (owner) return (await owner.runtime.isSessionTerminal?.()) === true ? null : owner;
89
100
  const external = await bindExternalSessionView(sessionId);
90
101
  const acquiredOwner = sessionOwner(sessionId);
91
- if (acquiredOwner) return acquiredOwner;
102
+ if (acquiredOwner) return (await acquiredOwner.runtime.isSessionTerminal?.()) === true ? null : acquiredOwner;
92
103
  if (external?.runtime?.externalAction === true) return external;
93
104
  return sessionLoads.get(sessionId) || null;
94
105
  }
@@ -70,6 +70,7 @@ export function createSessionEntries({
70
70
  publishExternalSessionState,
71
71
  });
72
72
  const loads = createSessionLoads({
73
+ pendingViewers,
73
74
  sessionExists,
74
75
  log,
75
76
  assertAvailable: lifecycle.assertAvailable,
@@ -386,3 +386,42 @@ export async function loadLiveTranscriptHead(entry, sessionId, readStoredSession
386
386
  view.headOlder = from > 0 || stored.transcriptHasOlder === true;
387
387
  return true;
388
388
  }
389
+
390
+ /** A one-shot range must not grow or rebudget an attached desktop's window. */
391
+ export async function readTranscriptRange(entry, sessionId, readStoredSession, { offset, limit }) {
392
+ if (
393
+ !Number.isSafeInteger(offset) ||
394
+ offset < 0 ||
395
+ !Number.isInteger(limit) ||
396
+ limit < 1 ||
397
+ limit > 100 ||
398
+ !Number.isSafeInteger(offset + limit)
399
+ )
400
+ throw new TypeError('invalid transcript range');
401
+ const requested = offset + limit;
402
+ let snapshot;
403
+ if (entry) {
404
+ const state = entry.runtime.getState();
405
+ const isolated = { runtime: { getState: () => state } };
406
+ requestLiveTranscriptWindow(isolated, { limit: requested, byteBudget: null, pageBase: 0 });
407
+ windowTranscriptSnapshot(isolated, state);
408
+ isolated.transcriptView.paged = true;
409
+ await loadLiveTranscriptHead(isolated, sessionId, readStoredSession);
410
+ snapshot = windowTranscriptSnapshot(isolated, state);
411
+ } else {
412
+ snapshot = await readStoredSession(sessionId, { transcriptItemLimit: requested });
413
+ }
414
+ if (!snapshot) throw new Error(`session ${sessionId} is not available`);
415
+ const source = snapshot.items || [];
416
+ if (offset >= source.length && snapshot.transcriptHasOlder) {
417
+ throw new Error('session: requested history is not available in the retained projection');
418
+ }
419
+ const end = Math.max(0, source.length - offset);
420
+ const start = Math.max(0, end - limit);
421
+ return {
422
+ sessionId,
423
+ offset,
424
+ items: sanitizeForWire(source.slice(start, end)),
425
+ hasOlder: start > 0 || snapshot.transcriptHasOlder === true,
426
+ };
427
+ }
@@ -8,8 +8,6 @@
8
8
  // again, and the session's own lane runs the retry under the entry's
9
9
  // generation. Overdue entries run as soon as the scheduler starts.
10
10
 
11
- import { isAgentOnlySession } from '../../runtime/shared/quota-resume-store.mjs';
12
-
13
11
  /** A still-exhausted reading is re-taken once, this much later. */
14
12
  export const QUOTA_RESUME_RETRY_MS = 5 * 60_000;
15
13
  /** A busy session is re-checked this much later, without spending an attempt. */
@@ -32,19 +30,33 @@ async function resumeDueEntry(entry, { store, materializeSession, readQuotaUsabl
32
30
  return 'unavailable';
33
31
  }
34
32
  if (!isCurrent(store, entry)) return 'cancelled';
35
- // A delegated agent child never owns a resume (the Lead decides retries), so
36
- // an entry persisted for one never fires, whatever wrote it.
37
- if (isAgentOnlySession({ id: sessionId, ...runtime?.session })) {
38
- store.cancelQuotaResumeEntry(sessionId, { generation });
39
- return 'agent-session';
40
- }
41
33
  let usable = false;
34
+ const currentRoute = () => {
35
+ const snapshot = runtime.getState?.() ?? {};
36
+ return {
37
+ // The selected route is what the next turn runs on; sessionProvider /
38
+ // sessionModel still hold the previous turn's after a deferred selection.
39
+ provider: snapshot.provider || snapshot.sessionProvider || runtime.session?.provider || entry.provider,
40
+ model: snapshot.model || snapshot.sessionModel || runtime.session?.model || entry.model,
41
+ };
42
+ };
43
+ const { provider, model } = currentRoute();
42
44
  try {
43
- usable = await readQuotaUsable(entry.provider, entry.model);
45
+ usable = await readQuotaUsable(provider, model);
44
46
  } catch (error) {
45
- log(`quota resume usage reading failed provider=${entry.provider}: ${error?.message || error}`);
47
+ log(`quota resume usage reading failed provider=${provider}: ${error?.message || error}`);
46
48
  }
47
49
  if (!isCurrent(store, entry)) return 'cancelled';
50
+ const selected = currentRoute();
51
+ if (selected.provider !== provider || selected.model !== model) {
52
+ // The reading belongs to the old route. Preserve the reservation and
53
+ // check the selected route on the normal busy-recheck cadence.
54
+ store.deferQuotaResumeEntry(sessionId, generation, {
55
+ resetAt: now() + QUOTA_RESUME_BUSY_RECHECK_MS,
56
+ attempts: entry.attempts,
57
+ });
58
+ return 'route-changed';
59
+ }
48
60
  if (!usable) {
49
61
  // One more reading five minutes on; after that the session falls back
50
62
  // to the user's own choice.
@@ -59,8 +71,8 @@ async function resumeDueEntry(entry, { store, materializeSession, readQuotaUsabl
59
71
  return 'exhausted';
60
72
  }
61
73
  const outcome =
62
- typeof runtime?.fireQuotaResume === 'function' ? runtime.fireQuotaResume({ generation }) : 'unsupported';
63
- if (outcome === 'busy') {
74
+ typeof runtime?.fireQuotaResume === 'function' ? await runtime.fireQuotaResume({ generation }) : 'unsupported';
75
+ if (outcome === 'busy' || outcome === 'rejected') {
64
76
  store.deferQuotaResumeEntry(sessionId, generation, {
65
77
  resetAt: now() + QUOTA_RESUME_BUSY_RECHECK_MS,
66
78
  attempts: entry.attempts,
@@ -117,7 +129,10 @@ export function createQuotaResumeScheduler({
117
129
  log(`quota resume session=${entry.sessionId} outcome=${outcome}`);
118
130
  } catch (error) {
119
131
  log(`quota resume failed session=${entry.sessionId}: ${error?.message || error}`);
120
- store.cancelQuotaResumeEntry(entry.sessionId, { generation: entry.generation });
132
+ store.deferQuotaResumeEntry(entry.sessionId, entry.generation, {
133
+ resetAt: now() + QUOTA_RESUME_RETRY_MS,
134
+ attempts: entry.attempts,
135
+ });
121
136
  }
122
137
  }
123
138
  })().finally(() => {
@@ -2,10 +2,17 @@
2
2
  // The generic runtime-action lane (read / configure allowlists) and the
3
3
  // session catalog listing.
4
4
  import { SESSION_CONFIGURE_ACTION_SET, SESSION_READ_ACTION_SET } from '../../session-protocol.mjs';
5
+ import { annotateSpan, markPhase } from '../../../runtime/shared/slow-span.mjs';
5
6
  import { sanitizeForWire } from '../../session-wire-values.mjs';
6
7
 
7
8
  /** Reads a session without a live runtime answers from disk (readStoredReview). */
8
- const STORED_REVIEW_ACTIONS = new Set(['getTurnReviewDiff', 'getSessionReviewDiff', 'getTurnChanges']);
9
+ const STORED_REVIEW_ACTIONS = new Set([
10
+ 'getTurnReviewDiff',
11
+ 'getSessionReviewDiff',
12
+ 'getTurnChanges',
13
+ 'getSessionReviewFilePatch',
14
+ 'getTurnReviewFilePatch',
15
+ ]);
9
16
 
10
17
  /** One compact description of an action result for the daemon log, never the payload itself. */
11
18
  function resultSummary(value) {
@@ -44,7 +51,8 @@ export function createSessionActionCalls(ctx) {
44
51
  assertAvailable();
45
52
  if (value === null) throw new Error(`session ${id} is not available`);
46
53
  log(`session action ${name} session=${id} result=${resultSummary(value)} (stored)`);
47
- return {
54
+ markPhase('load');
55
+ const result = {
48
56
  value: sanitizeForWire(value) ?? null,
49
57
  sessionId: id,
50
58
  reservedOnly: false,
@@ -52,6 +60,8 @@ export function createSessionActionCalls(ctx) {
52
60
  unchanged: true,
53
61
  ...(Number.isInteger(baseRevision) ? { revision: baseRevision } : {}),
54
62
  };
63
+ markPhase('project');
64
+ return result;
55
65
  }
56
66
 
57
67
  async function runSessionAction(
@@ -62,6 +72,7 @@ export function createSessionActionCalls(ctx) {
62
72
  const id = String(sessionId || '');
63
73
  if (!id) throw new TypeError('sessionId is required');
64
74
  const name = requireSessionAction(action, allowedActions);
75
+ annotateSpan(name);
65
76
  // Opening an earlier session asks for its review right away; loading the
66
77
  // whole runtime for that held the review bar (and the pane's reveal) for
67
78
  // seconds.
@@ -72,7 +83,9 @@ export function createSessionActionCalls(ctx) {
72
83
  assertAvailable(entry);
73
84
  const target = entry.runtime[name];
74
85
  if (typeof target !== 'function') throw new TypeError(`session action ${name} is unavailable`);
86
+ markPhase('load');
75
87
  const value = await target.apply(entry.runtime, Array.isArray(args) ? args : []);
88
+ markPhase('action');
76
89
  if (name === 'setCwd' && value) {
77
90
  try {
78
91
  const projects = await loadProjectStore();
@@ -89,11 +102,13 @@ export function createSessionActionCalls(ctx) {
89
102
  // Still unwatched: keep it on the retention clock exactly like a runtime
90
103
  // released by its view, so an untouched load cannot leak past the idle window.
91
104
  retainUnwatched(entry);
92
- return {
105
+ const result = {
93
106
  value: sanitizeForWire(value) ?? null,
94
107
  sessionId: responseSessionId(entry, id),
95
108
  ...bodyForClient(step, Number.isInteger(baseRevision) ? baseRevision : null),
96
109
  };
110
+ markPhase('project');
111
+ return result;
97
112
  }
98
113
 
99
114
  async function listSessionCatalog(options = {}) {
@@ -5,6 +5,7 @@
5
5
  // ./goal-recovery.mjs.
6
6
  import { createGoalRecovery } from './goal-recovery.mjs';
7
7
  import {
8
+ attachmentsForIntake,
8
9
  materializePromptSubmission,
9
10
  preparePromptSubmissionForProvider,
10
11
  } from '../../../runtime/attachments/store.mjs';
@@ -52,18 +53,28 @@ export function createSessionTurnCalls(ctx) {
52
53
  const entry = await entryForSession(id, openHints || {});
53
54
  const target = entry.runtime.submitAsync;
54
55
  if (typeof target !== 'function') throw new TypeError('session runtime must implement submitAsync');
55
- const intake = await preparePromptSubmissionForProvider(
56
- materializePromptSubmission(prompt, options || {}),
57
- { nativePdf: providerNativePdf(entry.runtime.provider || entry.runtime.session?.provider || '') }
58
- );
56
+ const intake = await preparePromptSubmissionForProvider(materializePromptSubmission(prompt, options || {}), {
57
+ nativePdf: providerNativePdf(entry.runtime.provider || entry.runtime.session?.provider || ''),
58
+ });
59
59
  // Await intake only: submitAsync resolves once the prompt is represented by
60
60
  // the queue/user row, while provider execution remains daemon-owned and
61
61
  // detached.
62
62
  let submissionOptions = intake.options;
63
- if (entry.runtime.externalAction === true) {
63
+ // Every send (desktop or paired device) reaches the engine here: the
64
+ // message records its attachments by content hash, so any device can open
65
+ // or download them by id later (and the store's census keeps the blobs).
66
+ const attachments = attachmentsForIntake(intake.prompt, intake.options);
67
+ if (attachments.length || entry.runtime.externalAction === true) {
64
68
  const transcriptMeta = intake.options?.transcriptMeta;
65
69
  const baseMeta = transcriptMeta && typeof transcriptMeta === 'object' ? transcriptMeta : {};
66
- submissionOptions = { ...intake.options, transcriptMeta: { ...baseMeta, sender: 'user' } };
70
+ submissionOptions = {
71
+ ...intake.options,
72
+ transcriptMeta: {
73
+ ...baseMeta,
74
+ ...(attachments.length ? { attachments } : {}),
75
+ ...(entry.runtime.externalAction === true ? { sender: 'user' } : {}),
76
+ },
77
+ };
67
78
  }
68
79
  const accepted = await Promise.resolve(target.call(entry.runtime, intake.prompt, submissionOptions));
69
80
  if (accepted === true) {
@@ -6,6 +6,7 @@ import { SESSION_READ_ACTION_SET } from '../../session-protocol.mjs';
6
6
  import { SESSION_ID_PATTERN } from '../agent-tree.mjs';
7
7
  import {
8
8
  loadLiveTranscriptHead,
9
+ readTranscriptRange,
9
10
  rebudgetTranscriptWindow,
10
11
  requestedHeldTranscript,
11
12
  requestedTranscriptWindow,
@@ -132,6 +133,11 @@ export function createSessionViewCalls(ctx) {
132
133
  if (!id) throw new TypeError('sessionId is required');
133
134
  const live = await liveEntryFor(id);
134
135
  assertAvailable(live);
136
+ if (params.transcriptRange) {
137
+ const range = await readTranscriptRange(live, id, readStoredSession, params.transcriptRange);
138
+ assertAvailable(live);
139
+ return { range };
140
+ }
135
141
  if (live) {
136
142
  return liveSessionReadResult(live, params, id, baseRevision);
137
143
  }
@@ -1,3 +1,5 @@
1
+ import { shortId, slowSpans } from '../runtime/shared/slow-span.mjs';
2
+
1
3
  const sessionServiceRoutes = ({ desktop, project, session }) => ({
2
4
  'desktop.init': (params, ctx) => desktop.init(params, ctx),
3
5
  'desktop.invoke': (params, ctx) => desktop.invoke(params, ctx),
@@ -32,13 +34,16 @@ export function createSessionServiceApi({
32
34
  getTurnBusyCount,
33
35
  getStatus,
34
36
  getExternalClientCount,
37
+ spans = slowSpans,
35
38
  }) {
36
39
  const routes = sessionServiceRoutes({ desktop, project, session });
37
40
  return {
38
41
  async handleCall(name, args = {}, ctx = null) {
39
42
  const route = routes[String(name || '')];
40
43
  if (!route) throw new Error(`unknown session service call ${name}`);
41
- return route(args || {}, ctx);
44
+ const params = args || {};
45
+ const sid = shortId(params.sessionId);
46
+ return spans.trace(sid ? `${name}#${sid}` : String(name), () => route(params, ctx));
42
47
  },
43
48
  ...methods,
44
49
  get size() {
@@ -3,5 +3,6 @@ export function diffSessionState(
3
3
  next: unknown,
4
4
  options?: { prepend?: boolean }
5
5
  ): Record<string, unknown> | null;
6
- export function applySessionStatePatch(previous: unknown, patch: unknown): Record<string, unknown>;
6
+ export function streamingPartialSuffix(before: unknown, after: unknown): string | null;
7
+ export function applySessionStatePatch(previous: unknown, patch: unknown): Record<string, unknown> | null;
7
8
  export function transcriptItemsDigest(items: readonly unknown[]): string;
@@ -7,16 +7,51 @@
7
7
  // `transcriptPrepend`) carries rows revealed ABOVE the previous list, an
8
8
  // older-history page: the previous rows then start `values.length` rows in,
9
9
  // and `itemsAppend.from` indexes the PREVIOUS list.
10
+ //
11
+ // `partialAppend` carries growth of the desktop-only `streamingPartial` (the
12
+ // unfinished streamed line) as just its new text: re-sending the whole line on
13
+ // every tick made a long unfinished line cost O(length²) on the wire. A
14
+ // decoder that predates it keeps its last partial, which the desktop join
15
+ // then ignores or shows behind — never wrong text.
10
16
  import { createHash } from 'node:crypto';
11
17
 
18
+ /** The text `after` appends to `before` when both are the same unfinished
19
+ * line (same row, same offset, same row identity), else null: a retraction,
20
+ * another row or a new line travels as a full replacement. */
21
+ export function streamingPartialSuffix(before, after) {
22
+ if (!before || !after || typeof before !== 'object' || typeof after !== 'object') return null;
23
+ const { text: beforeText, ...beforeRest } = before;
24
+ const { text: afterText, ...afterRest } = after;
25
+ if (typeof beforeText !== 'string' || typeof afterText !== 'string') return null;
26
+ if (afterText.length <= beforeText.length || !afterText.startsWith(beforeText)) return null;
27
+ // id, from and the row identity: everything but the text stays put.
28
+ if (JSON.stringify(beforeRest) !== JSON.stringify(afterRest)) return null;
29
+ return afterText.slice(beforeText.length);
30
+ }
31
+
32
+ function appendStreamingPartial(state, suffix) {
33
+ const held = state.streamingPartial;
34
+ if (!held || typeof held !== 'object' || typeof held.text !== 'string' || typeof suffix !== 'string') return false;
35
+ state.streamingPartial = { ...held, text: held.text + suffix };
36
+ return true;
37
+ }
38
+
12
39
  export function diffSessionState(previous, next, { prepend = false } = {}) {
13
40
  if (!previous || !next || typeof previous !== 'object' || typeof next !== 'object') return null;
14
41
  const set = {};
15
42
  const remove = [];
16
43
  let itemsAppend = null;
17
44
  let itemsPrepend = null;
45
+ let partialAppend = null;
18
46
  for (const [key, value] of Object.entries(next)) {
19
47
  if (previous[key] === value) continue;
48
+ if (key === 'streamingPartial') {
49
+ const suffix = streamingPartialSuffix(previous[key], value);
50
+ if (suffix !== null) {
51
+ partialAppend = { text: suffix };
52
+ continue;
53
+ }
54
+ }
20
55
  if (key === 'items' && Array.isArray(value) && Array.isArray(previous.items)) {
21
56
  let head = 0;
22
57
  if (prepend && previous.items.length > 0 && value[0] !== previous.items[0]) {
@@ -36,13 +71,18 @@ export function diffSessionState(previous, next, { prepend = false } = {}) {
36
71
  for (const key of Object.keys(previous)) {
37
72
  if (!(key in next)) remove.push(key);
38
73
  }
39
- return itemsPrepend ? { set, remove, itemsAppend, itemsPrepend } : { set, remove, itemsAppend };
74
+ const patch = itemsPrepend ? { set, remove, itemsAppend, itemsPrepend } : { set, remove, itemsAppend };
75
+ if (partialAppend) patch.partialAppend = partialAppend;
76
+ return patch;
40
77
  }
41
78
 
79
+ /** The patched state, or null when a `partialAppend` has no held line to grow
80
+ * (a broken chain the caller answers with a full resync, never lost text). */
42
81
  export function applySessionStatePatch(previous, patch) {
43
82
  const base = previous && typeof previous === 'object' ? previous : {};
44
83
  if (!patch || typeof patch !== 'object') return base;
45
84
  const next = { ...base, ...(patch.set || {}) };
85
+ if (Object.hasOwn(patch, 'partialAppend') && !appendStreamingPartial(next, patch.partialAppend?.text)) return null;
46
86
  if (patch.itemsAppend || patch.itemsPrepend) {
47
87
  const items = Array.isArray(base.items) ? base.items : [];
48
88
  const head = Array.isArray(patch.itemsPrepend?.values) ? patch.itemsPrepend.values : [];