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
@@ -175,6 +175,24 @@ export function appendBuffered(path, text) {
175
175
  }
176
176
  }
177
177
 
178
+ /**
179
+ * Drop every not-yet-written chunk for `path` (its file is being deleted, so a
180
+ * later flush must not recreate it). A write already handed to the OS cannot
181
+ * be recalled; callers unlink after this and it lands before or is removed.
182
+ */
183
+ export function discardBuffered(path) {
184
+ const q = queues.get(path);
185
+ if (!q) return;
186
+ if (q.timer) {
187
+ clearTimeout(q.timer);
188
+ q.timer = null;
189
+ }
190
+ q.chunks = [];
191
+ q.bytes = 0;
192
+ q.failCount = 0;
193
+ deleteIfIdle(path, q);
194
+ }
195
+
178
196
  /** Observable overflow counters for buffered append queues. */
179
197
  export function getBufferedAppenderStats(path) {
180
198
  const q = queues.get(path);
@@ -18,8 +18,10 @@ import {
18
18
  backupUserData,
19
19
  backupUserDataAsync,
20
20
  markUserDataInitialized,
21
+ ensureUserDataInitialized,
21
22
  loadLatestMixdogConfigFromBackup,
22
- hasUserDataInitMarker,
23
+ isUserDataRecoveryExpected,
24
+ findLegacyUserDataEvidence,
23
25
  } from './user-data-guard.mjs';
24
26
  import { AGENT_PROVIDER_ENV, AGENT_PROVIDER_ENV_ALIASES, getAgentApiKey } from './provider-api-key.mjs';
25
27
 
@@ -236,7 +238,7 @@ function readConfigFile() {
236
238
  }
237
239
  }
238
240
 
239
- function writeConfigFile(data) {
241
+ function writeConfigFile(data, postBackupReason = 'post-config-write') {
240
242
  // R4 data-at-rest: mixdog-config.json holds provider apiKeys; clamp to
241
243
  // owner-only on POSIX via 0o600/0o700 mode bits, AND fail-closed on
242
244
  // Windows where those bits are advisory — `secret: true` makes the
@@ -261,29 +263,76 @@ function writeConfigFile(data) {
261
263
  markUserDataInitialized(resolvePluginData());
262
264
  } catch {}
263
265
  try {
264
- backupUserData(resolvePluginData(), 'post-config-write');
266
+ backupUserData(resolvePluginData(), postBackupReason);
265
267
  } catch {}
266
268
  }
267
269
 
270
+ // Config paths whose restore could not be persisted: the in-memory restore is
271
+ // still served, but the failure is logged (and the write retried) only once
272
+ // per process instead of on every read.
273
+ const _restorePersistFailed = new Set();
274
+
275
+ /**
276
+ * Write a config restored on a plain read back to disk through the normal save
277
+ * path (atomic write + backups), so later reads hit the file instead of
278
+ * restoring again. Try-once lock: a contended lock means a writer (possibly
279
+ * this process's own outer RMW) is about to persist, so the next read retries.
280
+ */
281
+ function persistRestoredConfig(restored) {
282
+ const path = configPath();
283
+ if (_restorePersistFailed.has(path)) return;
284
+ try {
285
+ const wrote = withFileLockSync(
286
+ `${path}.lock`,
287
+ () => {
288
+ if (existsSync(path)) return false;
289
+ writeAll(restored, 'post-restore');
290
+ return true;
291
+ },
292
+ { timeoutMs: 0 }
293
+ );
294
+ if (wrote) {
295
+ process.stderr.write(
296
+ '[config] read: restored mixdog-config.json from latest user-data backup (missing after init) and saved it\n'
297
+ );
298
+ }
299
+ } catch (err) {
300
+ if (err?.code === 'ELOCKCONTENDED') return;
301
+ _restorePersistFailed.add(path);
302
+ process.stderr.write(
303
+ `[config] read: restored mixdog-config.json from latest user-data backup (missing after init); saving it failed, serving it from memory: ${err?.message || err}\n`
304
+ );
305
+ }
306
+ }
307
+
268
308
  function readAll() {
269
309
  const parsed = readConfigFile();
270
- if (parsed != null) return canonicalizeUnifiedConfig(parsed);
310
+ if (parsed != null) {
311
+ // A data dir from before the in-dir init marker gets one (plus a first
312
+ // scoped snapshot) once per process, so its config stays recoverable.
313
+ try {
314
+ ensureUserDataInitialized(resolvePluginData());
315
+ } catch {}
316
+ return canonicalizeUnifiedConfig(parsed);
317
+ }
271
318
  // Symmetric with readAllForRmW(): a missing/unreadable config on a data
272
319
  // dir that was previously initialized means the file was LOST (deleted,
273
- // failed write), not a fresh install. Self-heal from the newest
320
+ // failed write), not a fresh install. A recreated data dir has no marker
321
+ // and starts fresh. Self-heal from this data dir's newest
274
322
  // structurally-complete backup instead of silently collapsing to {} —
275
323
  // which callers (readSection/getCapabilities) merge with in-memory
276
- // defaults, dropping the user's presets/agent routes/sections. In-memory only:
277
- // readAll() runs OUTSIDE the config lock (unlike the RMW path), so we do
278
- // not write here to avoid an unlocked-write race; the next updateSection
279
- // re-persists the file under the lock.
280
- if (hasUserDataInitMarker(resolvePluginData())) {
324
+ // defaults, dropping the user's presets/agent routes/sections. The restore
325
+ // is persisted under the config lock (only if the file is still missing) so
326
+ // later reads hit the file instead of restoring and logging again.
327
+ // An upgraded data dir (legacy marker / matching legacy backup, no in-dir
328
+ // marker yet) is a recovery case too; without a verifiable backup reads stay
329
+ // empty and RMW writes refuse (see readAllForRmW).
330
+ if (isUserDataRecoveryExpected(resolvePluginData())) {
281
331
  const restored = loadLatestMixdogConfigFromBackup(resolvePluginData());
282
332
  if (restored && isPlainObject(restored)) {
283
- process.stderr.write(
284
- '[config] read: restored mixdog-config.json from latest user-data backup (missing after init)\n'
285
- );
286
- return canonicalizeUnifiedConfig(restored);
333
+ const config = canonicalizeUnifiedConfig(restored);
334
+ persistRestoredConfig(config);
335
+ return config;
287
336
  }
288
337
  }
289
338
  return {};
@@ -300,11 +349,22 @@ function quarantineMalformedConfig(parseErr) {
300
349
  }
301
350
 
302
351
  function restoreAllForRmWOrThrow(reason) {
303
- const restored = loadLatestMixdogConfigFromBackup(resolvePluginData());
352
+ const restored = loadLatestMixdogConfigFromBackup(resolvePluginData(), { fresh: true });
304
353
  if (restored && isPlainObject(restored)) {
305
354
  process.stderr.write(`[config] RMW read: restored mixdog-config.json from latest user-data backup (${reason})\n`);
306
355
  return restored;
307
356
  }
357
+ const legacy = findLegacyUserDataEvidence(resolvePluginData(), { fresh: true });
358
+ if (legacy) {
359
+ const err = new Error(
360
+ `[config] mixdog-config.json is missing but this data dir (${resolvePluginData()}) was initialized by an older ` +
361
+ `Mixdog build and no backup verified to belong to it was found; refusing to write a fresh config over a ` +
362
+ `recoverable state. Restore mixdog-config.json from a backup under ${legacy.roots.join(' or ')}, or delete ` +
363
+ `the legacy marker(s) to start fresh: ${legacy.markers.join(', ') || '(none; matching legacy backups are incomplete)'}`
364
+ );
365
+ err.code = 'EUSERDATARECOVERY';
366
+ throw err;
367
+ }
308
368
  throw new Error(
309
369
  `[config] mixdog-config.json is unreadable and no valid backup was found (${reason}); refusing section write that would wipe other sections`
310
370
  );
@@ -321,7 +381,7 @@ function readAllForRmW() {
321
381
  raw = readFileSync(configPath(), 'utf8');
322
382
  } catch (err) {
323
383
  if (err.code === 'ENOENT') {
324
- if (hasUserDataInitMarker(resolvePluginData())) {
384
+ if (isUserDataRecoveryExpected(resolvePluginData(), { fresh: true })) {
325
385
  return restoreAllForRmWOrThrow('config file missing after user-data was initialized');
326
386
  }
327
387
  return {};
@@ -402,8 +462,8 @@ export function subscribeConfigChange(listener) {
402
462
  };
403
463
  }
404
464
 
405
- function writeAll(data) {
406
- writeConfigFile(canonicalizeUnifiedConfig(data));
465
+ function writeAll(data, postBackupReason) {
466
+ writeConfigFile(canonicalizeUnifiedConfig(data), postBackupReason);
407
467
  notifyConfigChanged();
408
468
  }
409
469
 
@@ -1,6 +1,7 @@
1
1
  import { transportErrorText } from './transport-error-text.mjs';
2
2
  import { describeError, safeErrorDetails } from './error-presentation.mjs';
3
3
  import { oneLine } from './clean.mjs';
4
+ import { TIMEOUT_PHASE, isFirstByteTimeout } from './provider-timeout-phase.mjs';
4
5
 
5
6
  // HTTP status carried by a provider/transport error, or 0 when absent.
6
7
  export function errorHttpStatus(err) {
@@ -185,7 +186,9 @@ export function isCancelLikeError(error) {
185
186
  const KIND_LINES = {
186
187
  overloaded: 'Provider is busy at capacity.',
187
188
  rate_limited: ({ retryAfterMs }) =>
188
- retryAfterMs ? `Provider is rate-limited (retry in ${formatDurationMs(retryAfterMs)}).` : 'Provider is rate-limited.',
189
+ retryAfterMs
190
+ ? `Provider is rate-limited (retry in ${formatDurationMs(retryAfterMs)}).`
191
+ : 'Provider is rate-limited.',
189
192
  quota_exhausted: 'Provider usage limit reached.',
190
193
  entitlement: 'Not included in your plan.',
191
194
  billing: 'Out of credits or at spend limit.',
@@ -198,7 +201,38 @@ const KIND_LINES = {
198
201
  // A bare message carries none, so its wording keeps the legacy text path.
199
202
  function hasTypedEvidence(error) {
200
203
  if (!error || typeof error !== 'object') return false;
201
- return Boolean(error.errorKind?.kind) || errorHttpStatus(error) > 0 || Boolean(error.code) || Boolean(error.retryAfterMs);
204
+ return (
205
+ Boolean(error.errorKind?.kind) || errorHttpStatus(error) > 0 || Boolean(error.code) || Boolean(error.retryAfterMs)
206
+ );
207
+ }
208
+
209
+ // The window a provider timeout names (providerTimeoutError's message), or 0.
210
+ const timedOutMs = (text) => Number(/timed out after (\d+)ms/i.exec(text)?.[1]) || 0;
211
+
212
+ // A provider timeout before the model produced anything (isFirstByteTimeout):
213
+ // the model is slow, not the connection.
214
+ function stillThinkingText(error, text) {
215
+ const ms = Number(error.waitedMs) || timedOutMs(text);
216
+ const provider =
217
+ typeof error.providerLabel === 'string' && error.providerLabel ? error.providerLabel : 'the provider';
218
+ const attempts = Number(error.attempts) > 0 ? `; attempts: ${Math.floor(Number(error.attempts))}` : '';
219
+ return `Model still thinking: no output in ${formatDurationMs(ms)}; ${provider} sent nothing yet${attempts}.`;
220
+ }
221
+
222
+ // Stamped provider timeout phases and stream cuts. Null when the error names
223
+ // neither, so the text rules below decide.
224
+ function typedStreamFailureText(error, text) {
225
+ if (!error || typeof error !== 'object') return null;
226
+ if (isFirstByteTimeout(error)) return stillThinkingText(error, text);
227
+ if (error.timeoutPhase === TIMEOUT_PHASE.IDLE) {
228
+ const ms = timedOutMs(text);
229
+ return ms > 0 ? `No progress ${formatDurationMs(ms)}.` : 'No progress.';
230
+ }
231
+ // A stream that ended before its finish marker lost its connection.
232
+ if (error.code === 'TRUNCATED_STREAM' && error.streamCorruption !== true) {
233
+ return 'Connection to the provider was lost (TRUNCATED_STREAM).';
234
+ }
235
+ return null;
202
236
  }
203
237
 
204
238
  export function presentErrorText(error, options = {}) {
@@ -215,12 +249,20 @@ export function presentErrorText(error, options = {}) {
215
249
  const name = error && typeof error === 'object' ? String(error.name || '') : '';
216
250
  const code = error && typeof error === 'object' ? String(error.code || '') : '';
217
251
  const status = errorHttpStatus(error);
252
+ // The fixed request overhead error is actionable as written (sizes,
253
+ // contributors, remedy): keep its lines instead of a generic "Context too
254
+ // large." that would suggest compacting.
255
+ if (code === 'TOOL_SURFACE_EXCEEDS_CONTEXT' || /\(TOOL_SURFACE_EXCEEDS_CONTEXT\)/.test(text)) {
256
+ return stripErrorPrefix(text);
257
+ }
218
258
  const jsonError = extractJsonError(text);
219
259
  if (jsonError) text = jsonError;
220
260
  const embeddedError = extractEmbeddedError(text);
221
261
  if (embeddedError) text = embeddedError;
222
262
  text = oneLine(stripErrorPrefix(text));
223
263
  if (!text) return 'Unknown error';
264
+ const streamFailure = typedStreamFailureText(error, text);
265
+ if (streamFailure) return streamFailure;
224
266
 
225
267
  if (code === 'PROVIDER_PREFIX_MUTATION' || name === 'ProviderPrefixMutationError') {
226
268
  return 'Session state changed unexpectedly.';
@@ -276,9 +318,10 @@ export function presentErrorText(error, options = {}) {
276
318
  return Number.isFinite(ms) && ms > 0 ? `No first response ${formatDurationMs(ms)}.` : 'No first response.';
277
319
  }
278
320
 
321
+ // The agent's own watchdog, worded apart from any provider timeout.
279
322
  const firstTransport = /first (?:transport|semantic response) stale\s*\((\d+)ms\)/i.exec(text);
280
323
  if (firstTransport) {
281
- return `No first response ${formatDurationMs(firstTransport[1])}.`;
324
+ return `Agent watchdog stopped the run: no model response in ${formatDurationMs(firstTransport[1])}.`;
282
325
  }
283
326
 
284
327
  const firstResponse = /(?:agent\s+)?first response stale\s*\((\d+)ms\)/i.exec(text);
@@ -357,7 +400,8 @@ export function backgroundTaskFailureStatusLabel(status, error, options = {}) {
357
400
  /^timeout$/i.test(statusNorm) ||
358
401
  watchdog?.kind === 'timeout' ||
359
402
  /first response stale/i.test(raw) ||
360
- /no first response from/i.test(presented)
403
+ /no first response from/i.test(presented) ||
404
+ /^(?:Model still thinking|Agent watchdog stopped the run):/.test(presented)
361
405
  )
362
406
  head = 'Timeout';
363
407
  else if (
@@ -278,12 +278,13 @@ function* releaseReclaimGuard(reclaim) {
278
278
 
279
279
  // A lock is reclaimable when its recorded owner is dead, or when it names no
280
280
  // owner at all and has outlived the stale window.
281
- function lockReclaimable(owner, stat, staleMs) {
281
+ function lockReclaimable(owner, stat, staleMs, strictOwner = false) {
282
282
  if (owner.pid !== null) return !ownerIsLive(owner);
283
+ if (strictOwner) return false;
283
284
  return Date.now() - (Number(stat.mtimeMs) || 0) >= Math.max(0, staleMs);
284
285
  }
285
286
 
286
- function* tryReclaimStaleLock(lockPath, staleMs) {
287
+ function* tryReclaimStaleLock(lockPath, staleMs, strictOwner = false) {
287
288
  let initial;
288
289
  try {
289
290
  initial = yield ['stat', lockPath];
@@ -291,7 +292,7 @@ function* tryReclaimStaleLock(lockPath, staleMs) {
291
292
  return false;
292
293
  }
293
294
  const owner = yield* readLockOwner(lockPath);
294
- if (!lockReclaimable(owner, initial, staleMs)) return false;
295
+ if (!lockReclaimable(owner, initial, staleMs, strictOwner)) return false;
295
296
  const reclaim = yield* tryAcquireReclaimGuard(lockPath);
296
297
  if (reclaim === null) return false;
297
298
  try {
@@ -303,7 +304,7 @@ function* tryReclaimStaleLock(lockPath, staleMs) {
303
304
  }
304
305
  const currentOwner = yield* readLockOwner(lockPath);
305
306
  if (currentOwner.pid !== owner.pid || currentOwner.token !== owner.token) return false;
306
- if (lockReclaimable(currentOwner, current, staleMs)) {
307
+ if (lockReclaimable(currentOwner, current, staleMs, strictOwner)) {
307
308
  try {
308
309
  yield ['unlink', lockPath];
309
310
  return true;
@@ -429,7 +430,7 @@ function* acquireLock(lockPath, opts, mode, markHeld, timing = null) {
429
430
  // The reclaim runs synchronously in both modes: it is a few metadata
430
431
  // calls, and an await inside it would let a process exit strand its guard.
431
432
  try {
432
- if (runSync(tryReclaimStaleLock(lockPath, staleMs))) continue;
433
+ if (runSync(tryReclaimStaleLock(lockPath, staleMs, opts.strictOwner === true))) continue;
433
434
  } catch {}
434
435
  if (timeoutMs <= 0) throw contentionError(lockPath, error, yield* describeLockHolder(lockPath));
435
436
  if (Date.now() >= deadline) break;
@@ -1,3 +1,8 @@
1
1
  export function enforceOwnerOnlyAclWin32(targetPath: string, options?: { fresh?: boolean }): void;
2
2
 
3
- export function enforceOwnerOnlyAclWin32Async(targetPath: string, options?: { fresh?: boolean }): Promise<void>;
3
+ export function enforceOwnerOnlyAclWin32Async(
4
+ targetPath: string,
5
+ options?: { fresh?: boolean }
6
+ ): Promise<void>;
7
+
8
+ export function enforceOwnerOnlyDirectoryWin32Async(targetPath: string): Promise<void>;
@@ -73,6 +73,16 @@ function icaclsPath() {
73
73
  return path;
74
74
  }
75
75
 
76
+ const quoteForPowerShell = (value) => `'${String(value).replaceAll("'", "''")}'`;
77
+
78
+ function powerShellCommand(icacls, script) {
79
+ return {
80
+ executable: join(dirname(icacls), 'WindowsPowerShell', 'v1.0', 'powershell.exe'),
81
+ label: 'Windows ACL update',
82
+ args: ['-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(script, 'utf16le').toString('base64')],
83
+ };
84
+ }
85
+
76
86
  function ownerOnlyAclCommand(targetPath, sid, fresh, icacls) {
77
87
  if (fresh) {
78
88
  return {
@@ -84,7 +94,7 @@ function ownerOnlyAclCommand(targetPath, sid, fresh, icacls) {
84
94
  // Never /reset a published secret: that temporarily restores broad parent
85
95
  // grants, and a later failure leaves them in place. Build the protected DACL
86
96
  // in memory and publish it in one native ACL update instead.
87
- const quote = (value) => `'${String(value).replaceAll("'", "''")}'`;
97
+ const quote = quoteForPowerShell;
88
98
  const script = [
89
99
  "$ErrorActionPreference = 'Stop';",
90
100
  `$path = ${quote(targetPath)};`,
@@ -100,11 +110,37 @@ function ownerOnlyAclCommand(targetPath, sid, fresh, icacls) {
100
110
  'if ($directory) { [System.IO.Directory]::SetAccessControl($path, $acl) }',
101
111
  'else { [System.IO.File]::SetAccessControl($path, $acl) };',
102
112
  ].join(' ');
103
- return {
104
- executable: join(dirname(icacls), 'WindowsPowerShell', 'v1.0', 'powershell.exe'),
105
- label: 'Windows ACL update',
106
- args: ['-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(script, 'utf16le').toString('base64')],
107
- };
113
+ return powerShellCommand(icacls, script);
114
+ }
115
+
116
+ // Replaces a directory's whole DACL (explicit grants to anyone else included)
117
+ // with one protected, inheritable owner-only grant, in one native update, so
118
+ // files created inside need no ACL call of their own. Files already inside
119
+ // that carry an explicit grant or any other principal's grant are reset to
120
+ // inherit only that owner grant.
121
+ function ownerOnlyDirectoryCommand(targetPath, sid, icacls) {
122
+ const script = [
123
+ "$ErrorActionPreference = 'Stop';",
124
+ `$path = ${quoteForPowerShell(targetPath)};`,
125
+ `$sid = [System.Security.Principal.SecurityIdentifier]::new(${quoteForPowerShell(sid)});`,
126
+ '$acl = [System.Security.AccessControl.DirectorySecurity]::new();',
127
+ '$acl.SetAccessRuleProtection($true, $false);',
128
+ '$acl.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new(',
129
+ '$sid, [System.Security.AccessControl.FileSystemRights]::FullControl,',
130
+ "[System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit',",
131
+ '[System.Security.AccessControl.PropagationFlags]::None,',
132
+ '[System.Security.AccessControl.AccessControlType]::Allow));',
133
+ '[System.IO.Directory]::SetAccessControl($path, $acl);',
134
+ 'foreach ($file in [System.IO.Directory]::GetFiles($path)) {',
135
+ '$current = [System.IO.File]::GetAccessControl($file);',
136
+ '$rules = @($current.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]));',
137
+ '$foreign = @($rules | Where-Object { -not $_.IsInherited -or $_.IdentityReference -ne $sid });',
138
+ 'if ($current.AreAccessRulesProtected -or $foreign.Count -gt 0) {',
139
+ '$reset = [System.Security.AccessControl.FileSecurity]::new();',
140
+ '$reset.SetAccessRuleProtection($false, $false);',
141
+ '[System.IO.File]::SetAccessControl($file, $reset) } };',
142
+ ].join(' ');
143
+ return powerShellCommand(icacls, script);
108
144
  }
109
145
 
110
146
  function aclFailure(targetPath, cause, label = 'icacls') {
@@ -143,3 +179,15 @@ export async function enforceOwnerOnlyAclWin32Async(targetPath, { fresh = false
143
179
  throw aclFailure(targetPath, error, command.label);
144
180
  }
145
181
  }
182
+
183
+ export async function enforceOwnerOnlyDirectoryWin32Async(targetPath) {
184
+ if (process.platform !== 'win32') return;
185
+ const icacls = icaclsPath();
186
+ if (cachedUserSid === null) cachedUserSid = await resolveCurrentUserPrincipalAsync();
187
+ const command = ownerOnlyDirectoryCommand(targetPath, cachedUserSid, icacls);
188
+ try {
189
+ await execFileAsync(command.executable, command.args, { windowsHide: true, timeout: 15_000 });
190
+ } catch (error) {
191
+ throw aclFailure(targetPath, error, command.label);
192
+ }
193
+ }
@@ -2,7 +2,6 @@ import { EFFORT_BETA_HEADER } from './anthropic-effort.mjs';
2
2
  import { normalizeClaudeModelId } from './anthropic-thinking-contract.mjs';
3
3
  import { getModelMetadataSync } from './model-catalog.mjs';
4
4
 
5
- const EXTENDED_CACHE_TTL_BETA_HEADER = 'extended-cache-ttl-2025-04-11';
6
5
  const INTERLEAVED_THINKING_BETA_HEADER = 'interleaved-thinking-2025-05-14';
7
6
  const FAST_MODE_BETA_HEADER = 'fast-mode-2026-02-01';
8
7
  const TOOL_SEARCH_BETA_HEADER = 'advanced-tool-use-2025-11-20';
@@ -23,7 +22,7 @@ export function supportsAnthropicFastMode(model) {
23
22
  }
24
23
 
25
24
  export function buildAnthropicBetaHeaders({
26
- base = `${INTERLEAVED_THINKING_BETA_HEADER},${EXTENDED_CACHE_TTL_BETA_HEADER}`,
25
+ base = INTERLEAVED_THINKING_BETA_HEADER,
27
26
  fastMode = false,
28
27
  toolSearch = false,
29
28
  effort = false,
@@ -291,6 +291,12 @@ export function applyAnthropicEffortToBody(
291
291
  ) {
292
292
  if (!body || typeof body !== 'object') return;
293
293
 
294
+ // A gateway that declares its own effort contract (DeepSeek ignores
295
+ // budget_tokens) projects effort itself; returning true skips the Claude rules.
296
+ if (typeof opts.messagesEffortProjection === 'function') {
297
+ if (opts.messagesEffortProjection(body, { model, effort: opts.effort }) === true) return;
298
+ }
299
+
294
300
  const thinkingBudgetTokens = Number(opts.thinkingBudgetTokens);
295
301
  if (Number.isFinite(thinkingBudgetTokens) && thinkingBudgetTokens > 0) {
296
302
  assertAnthropicManualBudgetSupported(model);
@@ -28,6 +28,7 @@ export const ANTIGRAVITY_MODELS = Object.freeze([
28
28
  low: 'gemini-3.1-pro-low',
29
29
  high: 'gemini-3.1-pro-high',
30
30
  }),
31
+ fallbackModel('gemini-4-argon', 'Gemini 4 Argon', 'gemini-pro', 1048576, 'gemini-4-argon', ['low', 'medium', 'high']),
31
32
  fallbackModel('claude-opus-4-6-thinking', 'Claude Opus 4.6 (Thinking)', null, 250000, 'claude-opus-4-6-thinking', [
32
33
  'low',
33
34
  'medium',
@@ -8,6 +8,7 @@ import { currentProviderAccountId } from '../provider-auth-binding.mjs';
8
8
  // fallback, catalog retry) runs its own accounting and its result or error
9
9
  // then returns through the enclosing send, which must not write it again.
10
10
  const recorded = new WeakSet();
11
+ const UNMEASURED_USAGE = Object.freeze({ inputTokens: null, inputTokensKnown: false });
11
12
  const hasTokens = (usage) =>
12
13
  ['inputTokens', 'outputTokens', 'cachedTokens', 'cacheWriteTokens'].some((key) => Number(usage?.[key]) > 0);
13
14
  // One rule for every reported usage object: tokens, or a provider-reported
@@ -51,7 +52,9 @@ export async function accountProviderSend(provider, instance, send, model, opts
51
52
  // abandoned attempt or a failure shares that clock with the final attempt,
52
53
  // so timing it too would count the same seconds twice and understate speed.
53
54
  const record = async (result, id, owner, timed) => {
54
- if (!result?.usage) return;
55
+ // A completed call that reported no usage is still a call: it is recorded
56
+ // as unmeasured (unknown input, unpriced) instead of vanishing from totals.
57
+ if (!result?.usage && !(timed && result && typeof result === 'object')) return;
55
58
  // A nested send (e.g. a fallback model re-send) already stamped its own
56
59
  // final attempt's tier; the outer context only saw the abandoned attempt.
57
60
  result.requestServiceTier ??= identity.requestServiceTier || '';
@@ -59,7 +62,7 @@ export async function accountProviderSend(provider, instance, send, model, opts
59
62
  if (openingError) throw openingError;
60
63
  if (!ledger) return;
61
64
  recorded.add(owner);
62
- const usage = result.usage;
65
+ const usage = result.usage || UNMEASURED_USAGE;
63
66
  const row = makeUsageRecord({
64
67
  id: result.responseId ? undefined : id,
65
68
  ts: Date.now(),
@@ -61,6 +61,8 @@ const add = (target, row) => {
61
61
  costBilled: row.cost_source === 'provider' ? row.cost_usd : 0,
62
62
  costEstimated: row.cost_source === 'provider' ? 0 : row.cost_usd,
63
63
  });
64
+ // A call recorded without provider usage is unmeasured whatever its provider.
65
+ if (row.unmeasured && !usage.unmeasuredTurns) usage.unmeasuredTurns = usage.turns || 0;
64
66
  for (const field of [
65
67
  'turns',
66
68
  'input',
@@ -311,6 +313,7 @@ export function readSessionUsage(db, sessionIds) {
311
313
  json_extract(r.signature,'$[1]') AS model,
312
314
  json_extract(r.signature,'$[4]') AS cost_source,
313
315
  json_extract(r.signature,'$[7]') AS rank,
316
+ COALESCE(json_extract(json_extract(r.signature,'$[5]'),'$.inputTokensKnown'),1)=0 AS unmeasured,
314
317
  m.turns,m.input,m.output,m.cache_read,m.cache_write,m.cost_usd,m.duration_ms,
315
318
  m.speed_output,m.speed_ms
316
319
  FROM mine m JOIN usage_routes r ON r.id=m.route
@@ -9,6 +9,15 @@ export function createLoopbackListener({
9
9
  let current = null;
10
10
  let closing = null;
11
11
 
12
+ // close() drops only the keep-alive sockets idle at that moment; one whose
13
+ // in-flight response ends later would hold the close for the server's whole
14
+ // keepAliveTimeout (~5 s). Drop each as its response settles while stopping.
15
+ server.on('request', (_req, res) => {
16
+ res.once('close', () => {
17
+ if (closing) server.closeIdleConnections();
18
+ });
19
+ });
20
+
12
21
  function start() {
13
22
  if (closing) return Promise.reject(new Error('HTTP listener is stopping'));
14
23
  if (current) return current.promise;
@@ -0,0 +1,8 @@
1
+ export function canonicalRouteProvider(value: unknown): string;
2
+ export function routeChain(route: Record<string, unknown>): Record<string, unknown>[];
3
+ export function validateRouteChainProviders(routes: Record<string, unknown>[]): void;
4
+ export function normalizeRouteChain(
5
+ route: Record<string, unknown>,
6
+ normalizeLeaf: (route: Record<string, unknown>, fallback: Record<string, unknown>) => Record<string, unknown> | null,
7
+ fallback?: Record<string, unknown>
8
+ ): Record<string, unknown> | null;
@@ -0,0 +1,48 @@
1
+ const PROVIDER_ALIASES = Object.freeze({
2
+ 'openai-api': 'openai',
3
+ 'xai-api': 'xai',
4
+ 'gemini-api': 'gemini',
5
+ 'anthropic-api': 'anthropic',
6
+ });
7
+
8
+ export function canonicalRouteProvider(value) {
9
+ const id = String(value || '').trim();
10
+ return PROVIDER_ALIASES[id] || id;
11
+ }
12
+
13
+ export function routeChain(route) {
14
+ if (!route || typeof route !== 'object' || Array.isArray(route)) return [];
15
+ const { fallbacks = [], ...primary } = route;
16
+ if (!Array.isArray(fallbacks)) throw new Error('route.fallbacks must be an array');
17
+ for (const entry of fallbacks) {
18
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry) || Object.hasOwn(entry, 'fallbacks')) {
19
+ throw new Error('fallback routes must be leaf route objects');
20
+ }
21
+ }
22
+ return [primary, ...fallbacks];
23
+ }
24
+
25
+ export function validateRouteChainProviders(routes) {
26
+ const providers = new Set();
27
+ for (const route of routes) {
28
+ const provider = canonicalRouteProvider(route.provider);
29
+ if (!provider || !String(route.model || '').trim()) throw new Error('route requires provider and model');
30
+ if (providers.has(provider)) throw new Error(`duplicate route provider "${provider}"`);
31
+ if (providers.size && provider === 'default') throw new Error('follow Main is only allowed as the primary route');
32
+ providers.add(provider);
33
+ }
34
+ }
35
+
36
+ export function normalizeRouteChain(route, normalizeLeaf, fallback = {}) {
37
+ const raw = routeChain({ ...fallback, ...route });
38
+ const primary = normalizeLeaf(route, fallback);
39
+ if (!primary) return null;
40
+ const routes = raw.map((entry, index) => {
41
+ const normalized = index === 0 ? primary : normalizeLeaf(entry, {});
42
+ if (!normalized) throw new Error('fallback route requires provider and model');
43
+ return { ...normalized, provider: canonicalRouteProvider(normalized.provider) };
44
+ });
45
+ validateRouteChainProviders(routes);
46
+ const [first, ...rest] = routes;
47
+ return rest.length ? { ...first, fallbacks: rest } : first;
48
+ }
@@ -0,0 +1,22 @@
1
+ import { providerErrorKind } from '../agent/orchestrator/providers/provider-error-kind.mjs';
2
+ import { readStreamOutcome } from '../agent/orchestrator/providers/lib/stream-outcome.mjs';
3
+
4
+ const ELIGIBLE = new Set(['rate_limited', 'quota_exhausted', 'overloaded', 'transient']);
5
+
6
+ export function canFallbackRoute(error, { signal, outcome = readStreamOutcome(error), committed = false } = {}) {
7
+ if (signal?.aborted || committed || outcome.userAbort || outcome.stallObserved) return false;
8
+ if (
9
+ !outcome.replaySafe ||
10
+ outcome.observedOutput ||
11
+ outcome.toolCallsStarted ||
12
+ outcome.pendingToolInput ||
13
+ outcome.continuation ||
14
+ outcome.terminalObserved
15
+ )
16
+ return false;
17
+ const { kind, status } = providerErrorKind(error);
18
+ if (!ELIGIBLE.has(kind)) return false;
19
+ // A rejected HTTP request or a provider account-pool refusal proves no
20
+ // generation started. A transport disconnect alone does not.
21
+ return status === 429 || status === 503 || (kind === 'quota_exhausted' && error?.quotaExhausted != null);
22
+ }
@@ -25,3 +25,15 @@ export function isPidAlive(value) {
25
25
  return error?.code === 'EPERM';
26
26
  }
27
27
  }
28
+
29
+ /** Destructive operations require proof of death, not merely a failed probe. */
30
+ export function isPidAliveOrUnknown(value) {
31
+ const pid = parsePid(value);
32
+ if (!pid) return true;
33
+ try {
34
+ process.kill(pid, 0);
35
+ return true;
36
+ } catch (error) {
37
+ return error?.code !== 'ESRCH';
38
+ }
39
+ }
@@ -72,12 +72,20 @@ export function getAgentApiKey(provider) {
72
72
  /** The one API-key resolver for key-based providers: an explicit config key
73
73
  * wins, otherwise the environment/keychain (getAgentApiKey). */
74
74
  export function resolveProviderApiKey(provider, config) {
75
+ if (config?.apiKeyEnv) return process.env[config.apiKeyEnv] || '';
75
76
  return config?.apiKey || getAgentApiKey(provider) || '';
76
77
  }
77
78
 
79
+ /** Presence twin of resolveProviderApiKey, same precedence, no key value read. */
80
+ export function hasProviderApiKey(provider, config) {
81
+ if (config?.apiKeyEnv) return Boolean(process.env[config.apiKeyEnv]);
82
+ return Boolean(config?.apiKey) || hasAgentApiKey(provider);
83
+ }
84
+
78
85
  /** Auth-error reload: the stored/environment key is re-read first so a
79
86
  * rotated key beats the stale one captured in config. */
80
87
  export function reloadProviderApiKey(provider, config) {
88
+ if (config?.apiKeyEnv) return process.env[config.apiKeyEnv] || '';
81
89
  return getAgentApiKey(provider) || config?.apiKey || '';
82
90
  }
83
91