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,17 @@
1
+ // The phase a provider timeout names on its `timeoutPhase` field. A provider
2
+ // stamps it where the timer that fired is known; retry policy and error
3
+ // presentation read it instead of matching the timeout's message text.
4
+ export const TIMEOUT_PHASE = Object.freeze({
5
+ // The response headers did not arrive in the first-byte window.
6
+ HEADERS: 'headers',
7
+ // The headers arrived, the first chunk did not.
8
+ FIRST_CHUNK: 'first-chunk',
9
+ // A stream that already produced output went silent.
10
+ IDLE: 'idle',
11
+ });
12
+
13
+ /** A timeout before the model produced anything: headers or first chunk. */
14
+ export function isFirstByteTimeout(err) {
15
+ const phase = err?.timeoutPhase;
16
+ return phase === TIMEOUT_PHASE.HEADERS || phase === TIMEOUT_PHASE.FIRST_CHUNK;
17
+ }
@@ -0,0 +1,35 @@
1
+ export type QuietWaitKind = 'provider' | 'thinking' | 'model' | 'tool' | 'slot' | 'cancel' | '';
2
+
3
+ export const MODEL_THINKING_STAGE: 'model_thinking';
4
+ export function awaitingModelResponse(liveness: unknown): boolean;
5
+ export function displayProgressStage(liveness: unknown): string | null;
6
+
7
+ export interface QuietProgress {
8
+ since: number;
9
+ wait: QuietWaitKind;
10
+ tool?: string;
11
+ }
12
+
13
+ export interface QuietProgressParts {
14
+ quietMs: number;
15
+ minutes: number;
16
+ wait: QuietWaitKind;
17
+ tool: string;
18
+ escalated: boolean;
19
+ }
20
+
21
+ export const QUIET_PROGRESS_CUE_MS: number;
22
+ export function lastProgressAt(liveness: unknown): number;
23
+ export function quietWaitKind(stage: unknown): QuietWaitKind;
24
+ export function quietProgress(options: {
25
+ progressAt: unknown;
26
+ stage: unknown;
27
+ tool?: unknown;
28
+ now?: number;
29
+ }): QuietProgress | null;
30
+ export function quietProgressParts(
31
+ quiet: { since?: unknown; wait?: unknown; tool?: unknown } | null | undefined,
32
+ now: number,
33
+ warnMs?: unknown
34
+ ): QuietProgressParts | null;
35
+ export function quietProgressLabel(parts: QuietProgressParts | null): string;
@@ -0,0 +1,101 @@
1
+ // Quiet-time cue for a running turn: how long it has gone without progress
2
+ // the stall watchdog counts, and what it is waiting on. Display only — the
3
+ // watchdog's abort policy lives in stall-policy.mjs and is never read or
4
+ // changed here. Shared by the TUI spinner, the desktop live status line and
5
+ // the desktop agent rows, so every surface says the same thing.
6
+
7
+ /** A running turn with no counted progress for this long reads "quiet".
8
+ * Lenient on purpose: effort-mode models can think for minutes without a
9
+ * single semantic delta (stall-policy.mjs, the semantic-idle notes), so the
10
+ * cue stays neutral text; only the watchdog's own warn point escalates it. */
11
+ export const QUIET_PROGRESS_CUE_MS = 120_000;
12
+
13
+ /** The newest progress stamp of a runtime liveness entry or progress
14
+ * snapshot: the same signals the stall watchdog counts (stage changes,
15
+ * semantic stream deltas, tool starts and tool heartbeats, the turn start). */
16
+ export function lastProgressAt(liveness) {
17
+ if (!liveness || typeof liveness !== 'object') return 0;
18
+ return Math.max(
19
+ Number(liveness.lastProgressAt) || 0,
20
+ Number(liveness.lastStreamDeltaAt) || 0,
21
+ Number(liveness.toolStartedAt) || 0,
22
+ Number(liveness.askStartedAt) || 0
23
+ );
24
+ }
25
+
26
+ /** The stage a provider reports once its request is on the wire and the
27
+ * response headers are still pending. The runtime keeps the turn in
28
+ * `requesting` and records the send time (`requestSentAt`); the display stage
29
+ * below reads "model thinking" from that record. */
30
+ export const MODEL_THINKING_STAGE = 'model_thinking';
31
+
32
+ /** Request sent, response headers (transport) not yet received — read from
33
+ * a runtime liveness entry or progress snapshot. */
34
+ export function awaitingModelResponse(liveness) {
35
+ if (!liveness || typeof liveness !== 'object' || liveness.stage !== 'requesting') return false;
36
+ const sentAt = Number(liveness.requestSentAt) || 0;
37
+ return sentAt > 0 && !((Number(liveness.lastTransportAt) || 0) >= sentAt);
38
+ }
39
+
40
+ /** The stage a surface shows: `model_thinking` while the request waits for
41
+ * its headers, otherwise the runtime stage. */
42
+ export function displayProgressStage(liveness) {
43
+ if (awaitingModelResponse(liveness)) return MODEL_THINKING_STAGE;
44
+ return typeof liveness?.stage === 'string' ? liveness.stage : null;
45
+ }
46
+
47
+ const WAIT_BY_STAGE = {
48
+ connecting: 'provider',
49
+ requesting: 'provider',
50
+ [MODEL_THINKING_STAGE]: 'thinking',
51
+ streaming: 'model',
52
+ tool_running: 'tool',
53
+ resource_wait: 'slot',
54
+ cancelling: 'cancel',
55
+ };
56
+
57
+ /** What a quiet turn waits on, from its runtime stage ('' when unknown). */
58
+ export function quietWaitKind(stage) {
59
+ return WAIT_BY_STAGE[String(stage || '')] || '';
60
+ }
61
+
62
+ /** The quiet state of a running turn at `now`, or null while it is not
63
+ * quiet. `since` is the frozen progress stamp, so the value stays identical
64
+ * for the whole silence and publishing it costs one update per silence. */
65
+ export function quietProgress({ progressAt, stage, tool = null, now = Date.now() }) {
66
+ const since = Number(progressAt) || 0;
67
+ if (!since || now - since < QUIET_PROGRESS_CUE_MS) return null;
68
+ const wait = quietWaitKind(stage);
69
+ return { since, wait, ...(wait === 'tool' && tool ? { tool: String(tool) } : {}) };
70
+ }
71
+
72
+ /** Display parts of a quiet state at `now`: whole quiet minutes, and whether
73
+ * the silence reached the watchdog's warn point (`warnMs`, 0 = none). */
74
+ export function quietProgressParts(quiet, now, warnMs = 0) {
75
+ const since = Number(quiet?.since) || 0;
76
+ if (!since) return null;
77
+ const quietMs = Math.max(0, now - since);
78
+ if (quietMs < QUIET_PROGRESS_CUE_MS) return null;
79
+ return {
80
+ quietMs,
81
+ minutes: Math.floor(quietMs / 60_000),
82
+ wait: String(quiet.wait || ''),
83
+ tool: typeof quiet.tool === 'string' ? quiet.tool : '',
84
+ escalated: Number(warnMs) > 0 && quietMs >= Number(warnMs),
85
+ };
86
+ }
87
+
88
+ const WAIT_TEXT = {
89
+ provider: 'waiting on provider',
90
+ thinking: 'model thinking',
91
+ model: 'waiting on model',
92
+ slot: 'waiting for a slot',
93
+ cancel: 'stopping',
94
+ };
95
+
96
+ /** The TUI's lowercase English cue: `quiet for 2m · waiting on provider`. */
97
+ export function quietProgressLabel(parts) {
98
+ if (!parts) return '';
99
+ const wait = parts.wait === 'tool' ? `running ${parts.tool || 'a tool'}` : WAIT_TEXT[parts.wait] || '';
100
+ return [`quiet for ${parts.minutes}m`, wait].filter(Boolean).join(' · ');
101
+ }
@@ -131,6 +131,32 @@ export function listQuotaResumeEntries() {
131
131
  return [...load().entries.values()];
132
132
  }
133
133
 
134
+ /** Rekey a proven legacy execution and its Goal together; invalidate old fires. */
135
+ export function rekeyQuotaResumeTurn(sessionId, fromTurnKey, toTurnKey) {
136
+ const current = load();
137
+ const id = text(sessionId);
138
+ const from = text(fromTurnKey);
139
+ const to = text(toTurnKey);
140
+ if (!id || !from || !to || from === to) return false;
141
+ const entry = current.entries.get(id);
142
+ const suspension = current.suspensions.get(id);
143
+ const moveEntry = entry?.turnKey === from;
144
+ const moveGoal = suspension?.turnKey === from;
145
+ if (!moveEntry && !moveGoal) return false;
146
+ const next = {
147
+ ...current,
148
+ generation: current.generation + Number(moveEntry),
149
+ entries: new Map(current.entries),
150
+ suspensions: new Map(current.suspensions),
151
+ };
152
+ if (moveEntry) next.entries.set(id, normalizeEntry({ ...entry, turnKey: to, generation: next.generation }));
153
+ if (moveGoal) next.suspensions.set(id, normalizeSuspension({ ...suspension, turnKey: to }));
154
+ persist(next);
155
+ state = next;
156
+ notify(id);
157
+ return true;
158
+ }
159
+
134
160
  /** The session snapshot's `quotaResume` value for an entry (or null). */
135
161
  export function publicQuotaResume(entry) {
136
162
  if (!entry) return null;
@@ -244,7 +270,12 @@ export function isAgentOnlySession(session) {
244
270
  const lower = (value) => text(value).toLowerCase();
245
271
  if (lower(session.visibility) === 'agent-only') return true;
246
272
  const parentId = text(session.parentSessionId || session.ownerSessionId);
247
- return lower(session.owner) === 'agent' && lower(session.agent) !== 'lead' && parentId !== '' && parentId !== text(session.id);
273
+ return (
274
+ lower(session.owner) === 'agent' &&
275
+ lower(session.agent) !== 'lead' &&
276
+ parentId !== '' &&
277
+ parentId !== text(session.id)
278
+ );
248
279
  }
249
280
 
250
281
  /** Global setting, default on. */
@@ -61,3 +61,47 @@ export function readRowsForDisplay(text) {
61
61
  }
62
62
  return out.join('\n');
63
63
  }
64
+
65
+ /** Decode one contiguous model-facing read window, never display metadata.
66
+ * Unknown or disjoint views are not safe substitutes for file text. Per-line
67
+ * clipping is not visible in the text: the read executor reports it
68
+ * structurally, never inferred from row content.
69
+ * The display format does not preserve original byte size or final newline.
70
+ */
71
+ export function readSourceWindow(text) {
72
+ if (typeof text !== 'string') return null;
73
+ if (/^<system-reminder>File exists but has empty contents: [^\n]*<\/system-reminder>$/.test(text))
74
+ return { content: '', totalLines: 0, startLine: 1, endLine: 0, truncated: false };
75
+ const emptyRange = /^\(no lines in range; file has (\d+) lines\)$/.exec(text);
76
+ if (emptyRange)
77
+ return { content: '', totalLines: Number(emptyRange[1]), startLine: null, endLine: null, truncated: false };
78
+ if (!RUN_MARKER_RE.test(text.split('\n', 1)[0])) return null;
79
+ const rows = [];
80
+ let totalLines;
81
+ let footer = null;
82
+ for (const line of readRowsForDisplay(text).split('\n')) {
83
+ const row = /^(\d+)→([\s\S]*)$/.exec(line);
84
+ if (row) {
85
+ if (footer) return null;
86
+ const number = Number(row[1]);
87
+ if (rows.length && number !== rows.at(-1).number + 1) return null;
88
+ rows.push({ number, content: row[2] });
89
+ continue;
90
+ }
91
+ const metadata = /^\[lines (\d+)-(\d+) of (\d+)(?:; pass offset:\d+ to continue)?\]$/.exec(line);
92
+ if (!metadata || footer) return null;
93
+ footer = metadata;
94
+ totalLines = Number(metadata[3]);
95
+ }
96
+ if (!rows.length) return null;
97
+ const startLine = rows[0].number;
98
+ const endLine = rows.at(-1).number;
99
+ if (footer && (Number(footer[1]) !== startLine || Number(footer[2]) !== endLine || totalLines < endLine)) return null;
100
+ return {
101
+ content: rows.map((row) => row.content).join('\n'),
102
+ ...(totalLines === undefined ? {} : { totalLines }),
103
+ startLine,
104
+ endLine,
105
+ truncated: totalLines === undefined || endLine < totalLines,
106
+ };
107
+ }
@@ -1,47 +1,7 @@
1
- // Durable channel-link record (channel-remote-intent.json), read-side.
2
- //
3
- // The daemon's channel transport OWNS this file (writes/clears it); everything
4
- // else only asks one question: "which session is pinned to the channel?".
5
- // That session reclaims its link on boot
6
- // instead of waiting for a manual toggle — the reconnect path that used to
7
- // look like the channel had silently unlinked itself.
8
- import { readFileSync } from 'node:fs';
9
- import { join, resolve } from 'node:path';
1
+ // Path of the durable channel-link record (channel-remote-intent.json).
2
+ import { join } from 'node:path';
10
3
  import { resolveRuntimeRoot } from './runtime-root.mjs';
11
4
 
12
5
  export function remoteIntentPath(root = resolveRuntimeRoot()) {
13
6
  return join(root, 'channel-remote-intent.json');
14
7
  }
15
-
16
- export function readRemoteIntent(path = remoteIntentPath()) {
17
- try {
18
- const value = JSON.parse(readFileSync(path, 'utf8'));
19
- const sessionId = String(value?.sessionId || '').trim();
20
- const transcriptPath = String(value?.transcriptPath || '').trim();
21
- if (!/^[A-Za-z0-9_-]+$/.test(sessionId) || !transcriptPath) return null;
22
- return {
23
- sessionId,
24
- transcriptPath,
25
- cwd: value?.cwd == null ? null : String(value.cwd),
26
- };
27
- } catch {
28
- return null;
29
- }
30
- }
31
-
32
- // cwd is compared only when the record carries one: the intent is session
33
- // pinned, and a resumed session keeps its id across restarts.
34
- export function remoteIntentMatchesSession(sessionId, cwd = null, path = undefined) {
35
- const id = String(sessionId || '').trim();
36
- if (!id) return false;
37
- const intent = readRemoteIntent(path);
38
- if (!intent || intent.sessionId !== id) return false;
39
- if (intent.cwd && cwd) {
40
- try {
41
- if (resolve(intent.cwd) !== resolve(cwd)) return false;
42
- } catch {
43
- return false;
44
- }
45
- }
46
- return true;
47
- }
@@ -1,5 +1,57 @@
1
1
  const TRUNCATED = '… [diff truncated for display]';
2
2
 
3
+ // Review replies always list every changed file with its counts. Patch text
4
+ // is carried per file within these caps (UTF-8 bytes); a file past either one
5
+ // is listed `patchOmitted` with reason PATCH_TOO_LARGE and is read on its own,
6
+ // up to the larger "show anyway" cap, when it is opened.
7
+ /** Largest single-file patch a review reply carries inline. */
8
+ export const REVIEW_FILE_PATCH_MAX_BYTES = 1024 * 1024;
9
+ /** Largest total patch text a review reply carries. */
10
+ export const REVIEW_PATCH_MAX_BYTES = 2 * 1024 * 1024;
11
+ /** Largest single-file patch a file-patch read returns. */
12
+ export const REVIEW_FILE_PATCH_SHOW_MAX_BYTES = 8 * 1024 * 1024;
13
+ export const PATCH_TOO_LARGE = 'too_large';
14
+
15
+ /** A reply file listed with its counts but without its patch, for size. */
16
+ export function patchOmittedFile(file) {
17
+ return { ...file, patchOmitted: true, reason: PATCH_TOO_LARGE };
18
+ }
19
+
20
+ /** A `diff --git` section (string or Buffer) whose hunks boundReviewPatch cut. */
21
+ export function reviewSectionTruncated(section) {
22
+ return section.includes(TRUNCATED);
23
+ }
24
+
25
+ /** Nothing of the reply's patch fit: no patch text, a file omitted for size. */
26
+ export function reviewDiffTooLarge(files, patch) {
27
+ return !patch && (files || []).some((file) => file?.patchOmitted === true && file.reason === PATCH_TOO_LARGE);
28
+ }
29
+
30
+ /** The per-file and total caps of one reply. `admit(bytes)` takes a patch of
31
+ * that size from the remaining total, or refuses it. */
32
+ export function createReviewPatchBudget(total = REVIEW_PATCH_MAX_BYTES) {
33
+ let remaining = total;
34
+ return {
35
+ get remaining() {
36
+ return remaining;
37
+ },
38
+ admit(bytes) {
39
+ if (bytes > REVIEW_FILE_PATCH_MAX_BYTES || bytes > remaining) return false;
40
+ remaining -= bytes;
41
+ return true;
42
+ },
43
+ };
44
+ }
45
+
46
+ /** One file-patch read's reply: its patch, or none when past `maxBytes`. */
47
+ export function filePatchReply(path, patch, maxBytes = REVIEW_FILE_PATCH_SHOW_MAX_BYTES) {
48
+ const text = typeof patch === 'string' ? patch : '';
49
+ if (Buffer.byteLength(text, 'utf8') > maxBytes) {
50
+ return { supported: true, path, patch: '', patchOmitted: true, reason: PATCH_TOO_LARGE };
51
+ }
52
+ return { supported: true, path, patch: text };
53
+ }
54
+
3
55
  /** Bound hunk bodies, never the inventory of changed files. Headers are kept
4
56
  * even when the inventory itself exceeds the display budget. */
5
57
  export function boundReviewPatch(patch, maxChars) {
@@ -0,0 +1,4 @@
1
+ export type SessionSidebarChange = { favorite: boolean } | { archived: boolean };
2
+ export type SessionSidebarHost = (sessionId: unknown, change: unknown) => unknown;
3
+ export function registerSessionSidebarHost(host: SessionSidebarHost): () => void;
4
+ export function applySessionSidebarChange(sessionId: string, change: SessionSidebarChange): Promise<void>;
@@ -0,0 +1,38 @@
1
+ // Runtime → desktop request channel for a session's sidebar metadata
2
+ // (favorite, archive). That metadata belongs to the desktop
3
+ // service hosted in this daemon: it registers a host here, and the Lead's
4
+ // `session` tool applies a change through it, so the sidebar republishes live.
5
+ //
6
+ // Deliberately dependency-free: the desktop service bundle imports this file
7
+ // too, and both copies share one registry through a global symbol.
8
+
9
+ const HOSTS_KEY = Symbol.for('mixdog.sessionSidebarHosts.v1');
10
+
11
+ function hosts() {
12
+ globalThis[HOSTS_KEY] ??= [];
13
+ return globalThis[HOSTS_KEY];
14
+ }
15
+
16
+ /**
17
+ * Register a desktop host. `host(sessionId, change)` applies one change:
18
+ * `{ favorite: boolean }` or `{ archived: boolean }`.
19
+ * @returns {() => void} Unregister.
20
+ */
21
+ export function registerSessionSidebarHost(host) {
22
+ const entry = { host };
23
+ hosts().push(entry);
24
+ return () => {
25
+ const list = hosts();
26
+ const index = list.indexOf(entry);
27
+ if (index >= 0) list.splice(index, 1);
28
+ };
29
+ }
30
+
31
+ /** Apply one change through exactly one host: the most recently registered
32
+ * (active) desktop service. Never broadcast — each service writes the shared
33
+ * metadata file, so a second write would be redundant at best. */
34
+ export async function applySessionSidebarChange(sessionId, change) {
35
+ const active = hosts().at(-1);
36
+ if (!active) throw new Error('no desktop app is attached to this runtime');
37
+ await active.host(sessionId, change);
38
+ }
@@ -0,0 +1,121 @@
1
+ // slow-span.mjs
2
+ // Passive per-request timing spans. Every traced call is timed on the same
3
+ // monotonic clock the owner heartbeat uses (performance.now), completed spans
4
+ // over `minMs` land in a bounded ring, and spans over `slowMs` are logged as
5
+ // `[slow-op] <label> <ms>`. When the event loop stalls, `describe(from, to)`
6
+ // names the spans that overlapped the stall window. Spans carry labels, phase
7
+ // durations and sizes only — never payloads.
8
+
9
+ import { AsyncLocalStorage } from 'node:async_hooks';
10
+ import { performance } from 'node:perf_hooks';
11
+
12
+ export const SPAN_RING_MIN_MS = 25;
13
+ export const SPAN_SLOW_MS = 1000;
14
+ export const SPAN_RING_CAPACITY = 64;
15
+
16
+ const current = new AsyncLocalStorage();
17
+
18
+ /** Short, log-safe id of a session id. */
19
+ export function shortId(id) {
20
+ const text = String(id ?? '');
21
+ return text ? text.slice(0, 8) : '';
22
+ }
23
+
24
+ /** Appends detail (e.g. the action name) to the label of the span the caller runs in. */
25
+ export function annotateSpan(detail) {
26
+ const span = current.getStore();
27
+ if (span && detail) span.label += `:${detail}`;
28
+ }
29
+
30
+ /** Closes the running phase of the caller's span at `now`, under `name`. */
31
+ export function markPhase(name) {
32
+ const span = current.getStore();
33
+ if (!span) return;
34
+ const t = span.now();
35
+ span.phases.push([name, t - span.mark]);
36
+ span.mark = t;
37
+ }
38
+
39
+ /** Records a size (count/bytes) on the caller's span. */
40
+ export function noteSpanSize(size) {
41
+ const span = current.getStore();
42
+ if (span && Number.isFinite(size)) span.size = size;
43
+ }
44
+
45
+ const round = (ms) => Math.round(ms);
46
+
47
+ function formatSpan(span) {
48
+ const phases = span.phases.map(([name, ms]) => `${name}=${round(ms)}`).join(' ');
49
+ const size = span.size === undefined ? '' : ` size=${span.size}`;
50
+ return `${span.label} ${round(span.ms)}ms${phases ? ` ${phases}` : ''}${size}`;
51
+ }
52
+
53
+ export function createSlowSpans({
54
+ now = () => performance.now(),
55
+ capacity = SPAN_RING_CAPACITY,
56
+ minMs = SPAN_RING_MIN_MS,
57
+ slowMs = SPAN_SLOW_MS,
58
+ log = () => {},
59
+ } = {}) {
60
+ const ring = [];
61
+ let sink = log;
62
+
63
+ function complete(span) {
64
+ span.end = now();
65
+ span.ms = span.end - span.start;
66
+ if (span.ms >= minMs) {
67
+ ring.push({
68
+ label: span.label,
69
+ start: span.start,
70
+ end: span.end,
71
+ ms: span.ms,
72
+ phases: span.phases,
73
+ size: span.size,
74
+ });
75
+ if (ring.length > capacity) ring.shift();
76
+ }
77
+ if (span.ms >= slowMs) {
78
+ try {
79
+ sink(`[slow-op] ${formatSpan(span)}`);
80
+ } catch {
81
+ /* logging must not fail the call */
82
+ }
83
+ }
84
+ }
85
+
86
+ return {
87
+ setLog(next) {
88
+ sink = typeof next === 'function' ? next : () => {};
89
+ },
90
+ /** Runs `fn` inside a span; markPhase/annotateSpan inside it attach to this span. */
91
+ async trace(label, fn) {
92
+ const start = now();
93
+ const span = { label: String(label), start, mark: start, now, phases: [], size: undefined };
94
+ try {
95
+ return await current.run(span, fn);
96
+ } finally {
97
+ complete(span);
98
+ }
99
+ },
100
+ /** Completed spans overlapping [from, to], longest overlap first. */
101
+ overlapping(from, to, limit = 3) {
102
+ return ring
103
+ .map((span) => ({ span, overlap: Math.min(span.end, to) - Math.max(span.start, from) }))
104
+ .filter((row) => row.overlap > 0)
105
+ .sort((a, b) => b.overlap - a.overlap || b.span.end - a.span.end)
106
+ .slice(0, limit)
107
+ .map((row) => row.span);
108
+ },
109
+ /** One-line description of the spans overlapping a stall window ('' when none). */
110
+ describe(from, to, limit = 3) {
111
+ const spans = this.overlapping(from, to, limit);
112
+ return spans.length ? `spans: ${spans.map((span) => formatSpan({ ...span })).join('; ')}` : '';
113
+ },
114
+ get recent() {
115
+ return ring.slice();
116
+ },
117
+ };
118
+ }
119
+
120
+ /** Process-wide recorder; the daemon points its log at daemon.log. */
121
+ export const slowSpans = createSlowSpans();
@@ -15,6 +15,11 @@ import { join } from 'node:path';
15
15
  import { formatElapsed } from './statusline-format.mjs';
16
16
  import { positiveInt } from '../numbers.mjs';
17
17
  import { isPidAlive } from '../pid-liveness.mjs';
18
+ import { workspaceSees } from '../worktrees/workspace-visibility.mjs';
19
+
20
+ /** Whether an orphaned held shell (`status.orphaned`) belongs in the list of a
21
+ * session working in `sessionCwd`. */
22
+ export const shellJobVisibleFrom = (job, sessionCwd) => workspaceSees(job?.cwd, sessionCwd);
18
23
 
19
24
  const DEFAULT_MIXDOG_HOME = process.env.MIXDOG_HOME || join(homedir(), '.mixdog');
20
25
  const DEFAULT_STANDALONE_DATA_DIR = join(DEFAULT_MIXDOG_HOME, 'data');
@@ -76,9 +81,38 @@ export function shellJobsStatus({ clientHostPid, sessionId } = {}) {
76
81
  _shellJobsRefreshInFlight.delete(ownerPid);
77
82
  });
78
83
  }
79
- const value = cached?.value || EMPTY_SHELL_JOBS;
80
- if (!scoped) return value;
81
- return (scope && value.sessions?.[scope]) || EMPTY_SHELL_JOBS_SESSION;
84
+ const own = cached?.value || EMPTY_SHELL_JOBS;
85
+ // Session buckets are not pid-scoped, so they come from the freshest scan of
86
+ // ANY owner. Reading them from this owner's own slot made the list follow
87
+ // that slot's age: an owner polled again after its entry was evicted (or
88
+ // went stale) answered with "no sessions", and the finished shells vanished
89
+ // until the next poll brought them back.
90
+ const sessions = freshestShellJobsSessions() ?? own.sessions;
91
+ if (!scoped) return sessions === own.sessions ? own : { ...own, sessions };
92
+ return (scope && sessions?.[scope]) || EMPTY_SHELL_JOBS_SESSION;
93
+ }
94
+
95
+ /** Listed jobs held only because their termination is unconfirmed. */
96
+ export function unconfirmedShellCount(status) {
97
+ const jobs = Array.isArray(status?.jobs) ? status.jobs : [];
98
+ return jobs.filter((job) => job?.terminationUnconfirmed === true).length;
99
+ }
100
+
101
+ // Awaited fresh scan for pollers that own their cadence (desktop): the result
102
+ // reflects the disk at call time instead of the previous poll. The CLI render
103
+ // path keeps using the cache-only shellJobsStatus.
104
+ export async function shellJobsStatusFresh({ clientHostPid } = {}) {
105
+ const ownerPid = positiveInt(clientHostPid);
106
+ if (!ownerPid) return EMPTY_SHELL_JOBS;
107
+ return refreshShellJobsStatus(ownerPid);
108
+ }
109
+
110
+ function freshestShellJobsSessions() {
111
+ let freshest = null;
112
+ for (const entry of _shellJobsSegmentCache.values()) {
113
+ if (!freshest || entry.at >= freshest.at) freshest = entry;
114
+ }
115
+ return freshest?.value.sessions;
82
116
  }
83
117
 
84
118
  // Memory cycle L2 segment source. The daemon-hosted memory runtime writes
@@ -142,12 +176,13 @@ async function refreshShellJobsStatus(ownerPid) {
142
176
  names = await readdir(dir);
143
177
  } catch {
144
178
  rememberShellJobs(ownerPid, value);
145
- return;
179
+ return value;
146
180
  }
147
181
  const { ids, ownerByJob, doneIds } = listOpenShellJobs(names);
148
182
  let count = 0;
149
183
  let oldestMs = Infinity;
150
184
  const jobs = [];
185
+ const orphaned = [];
151
186
  // sessionId -> { count, oldestMs, jobs }. Jobs with no session stamp (legacy
152
187
  // records, plain CLI runs) still count toward the owner total but belong to
153
188
  // no pane, so they never light up a session's indicator.
@@ -160,11 +195,16 @@ async function refreshShellJobsStatus(ownerPid) {
160
195
  } catch {
161
196
  continue;
162
197
  }
163
- if (!(await isShellJobAlive(detail, p, dir, id))) continue;
198
+ // A killed command whose processes are not confirmed gone has already
199
+ // reported its result, so its tool card is closed: it is listed until
200
+ // its owner retires the record. Its root pid may be gone while a
201
+ // descendant lives, so the owner's liveness decides, not the root's.
202
+ const unconfirmed = detail?.terminationUnconfirmed === true;
203
+ if (unconfirmed ? !isPidAlive(ownerByJob.get(id) || 0) : !(await isShellJobAlive(detail, p, dir, id))) continue;
164
204
  // A foreground command is awaited in its own tool card; listing it here
165
205
  // made every short command flash in and out of the shell list. Only
166
206
  // backgrounded jobs (including promoted ones) are background work.
167
- if (detail?.foreground === true) continue;
207
+ if (detail?.foreground === true && !unconfirmed) continue;
168
208
  // Owner-wide totals stay this process's own; session buckets take every
169
209
  // live job regardless of which host published it.
170
210
  const ownedByThisHost = ownerByJob.get(id) === ownerPid;
@@ -181,8 +221,12 @@ async function refreshShellJobsStatus(ownerPid) {
181
221
  command: String(detail?.command || '').trim(),
182
222
  cwd: String(detail?.cwd || '').trim(),
183
223
  startedAt: detail?.startedAt || (Number.isFinite(jobMs) ? jobMs : null),
224
+ ...(unconfirmed ? { terminationUnconfirmed: true } : {}),
184
225
  };
185
226
  if (ownedByThisHost) jobs.push(job);
227
+ // Held by a session that has closed: every session that sees its
228
+ // folder lists it (shellJobVisibleFrom), not only the closed owner.
229
+ if (unconfirmed && detail?.ownerSessionClosed === true) orphaned.push(job);
186
230
  if (!owner) continue;
187
231
  const bucket = bySession.get(owner) || { count: 0, oldestMs: Infinity, jobs: [], finished: [] };
188
232
  bucket.count += 1;
@@ -221,10 +265,12 @@ async function refreshShellJobsStatus(ownerPid) {
221
265
  // count stays 0 (its publisher is a shard, not this host), so an empty
222
266
  // aggregate must NOT discard the session buckets.
223
267
  if (count || bySession.size) value = summarizeShellJobs({ count, oldestMs, jobs, bySession });
268
+ if (orphaned.length) value = { ...value, orphaned };
224
269
  } catch {
225
270
  value = EMPTY_SHELL_JOBS;
226
271
  }
227
272
  rememberShellJobs(ownerPid, value);
273
+ return value;
228
274
  }
229
275
 
230
276
  // Newest-first, capped ids of job records with no `.done` marker, plus the
@@ -5,7 +5,8 @@
5
5
  import { formatToolActionHeader, toolLoadingTargets } from '../tool-surface.mjs';
6
6
  import { agentActionSummary, agentActionTitle, agentResponseTitle, isAgentTool } from './agent-surface.mjs';
7
7
  import { backgroundTaskActionTitle, backgroundTaskResultTitle, taskControlTitle } from './background-task.mjs';
8
- import { toolSearchLoadedSummary } from './generic-detail.mjs';
8
+ import { bridgeDescribedToolNames, toolSearchLoadedSummary } from './generic-detail.mjs';
9
+ import { displayToolSearchTarget } from '../tool-primitives.mjs';
9
10
  import { safeInlineText } from './inline-text.mjs';
10
11
  import { shellHeader } from './shell-surface.mjs';
11
12
 
@@ -20,6 +21,11 @@ function headerLabel(base, surface, display, status, detail) {
20
21
  }
21
22
  if (display.isBackgroundMetadataResult) return backgroundTaskActionTitle(normalizedName, display.backgroundMeta);
22
23
  if (isShellSurface) return shellHeader(status.shellStatus, groupCount, parsedArgs?.verifyShell === true);
24
+ // Bridge load_tool describes definitions; it never loads a tool.
25
+ const described =
26
+ normalizedName === 'load_tool' && !headerPending ? bridgeDescribedToolNames(display.displayedResultText) : null;
27
+ if (described)
28
+ return described.length ? `Described ${described.map(displayToolSearchTarget).join(', ')}` : 'Described';
23
29
  return (
24
30
  (isAgentTool(normalizedName) ? agentActionTitle(parsedArgs, display.displayedResultText) : '') ||
25
31
  formatToolActionHeader(name, args, {