mixdog 1.2.3 → 1.2.5

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 (469) hide show
  1. package/package.json +1 -1
  2. package/scripts/gate-local.mjs +6 -4
  3. package/scripts/lib/gate-scheduler.mjs +29 -11
  4. package/scripts/mobile-release.mjs +5 -4
  5. package/scripts/probe-provider-catalog.mjs +31 -0
  6. package/scripts/provider-pingpong-live.mjs +128 -38
  7. package/scripts/session-sweep.mjs +5 -25
  8. package/src/agents/maintainer/AGENT.md +1 -1
  9. package/src/agents/maintainer/agent.json +1 -1
  10. package/src/agents/reviewer/AGENT.md +2 -4
  11. package/src/agents/security/AGENT.md +1 -2
  12. package/src/agents/writer/AGENT.md +2 -3
  13. package/src/defaults/shipped-history.json +7 -1
  14. package/src/defaults/skills/image/SKILL.md +21 -23
  15. package/src/lib/keychain-cjs.cjs +13 -11
  16. package/src/output-styles/common.md +2 -1
  17. package/src/rules/agent/AGENT.md +7 -5
  18. package/src/rules/lead/LEAD.md +13 -13
  19. package/src/rules/shared/45-destructive.md +4 -0
  20. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  21. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  22. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  23. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  24. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  25. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  26. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
  28. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  29. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  30. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2 -5
  31. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -0
  32. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  33. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  34. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +81 -10
  35. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
  36. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
  37. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
  38. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
  39. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
  40. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  41. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  42. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  43. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  44. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +41 -11
  46. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
  47. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
  48. package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
  49. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
  50. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
  51. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
  52. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
  53. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
  54. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
  55. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  56. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  57. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +6 -1
  58. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
  59. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
  60. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
  61. package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
  62. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  63. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
  64. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
  65. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  66. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
  67. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
  68. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  69. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
  70. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
  72. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  74. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
  75. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
  76. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
  78. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
  79. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  80. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
  81. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  82. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +3 -1
  83. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
  84. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
  85. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
  86. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
  87. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
  88. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
  89. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
  90. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
  91. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
  92. package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
  93. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
  94. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
  95. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
  96. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
  97. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
  98. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  99. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
  100. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  101. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  102. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  103. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +3 -1
  104. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  105. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
  106. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
  107. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
  108. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  109. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  110. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  111. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  112. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  113. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -11
  114. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  115. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
  116. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  117. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
  118. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  119. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  120. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  121. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +1 -1
  122. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  123. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  124. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -4
  125. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
  126. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -27
  127. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  128. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  129. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  130. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +4 -1
  131. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
  132. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
  133. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  134. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
  135. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
  136. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  137. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
  138. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
  139. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
  140. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  141. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  142. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +21 -1
  143. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
  144. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  145. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
  146. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
  147. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  148. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  149. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  150. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  151. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +29 -8
  152. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  153. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  154. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +32 -14
  155. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
  156. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
  157. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  158. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
  159. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  160. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
  161. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  162. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
  163. package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
  164. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
  165. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  167. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  169. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +5 -11
  172. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  173. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  174. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  175. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -32
  176. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  177. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  178. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  179. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  181. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +160 -212
  182. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
  183. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  184. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  185. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +7 -8
  186. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  187. package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
  188. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
  189. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
  190. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  191. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
  192. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  193. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  194. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  195. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  196. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  197. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +204 -10
  198. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  199. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  200. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  201. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  202. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  203. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  205. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +200 -17
  206. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  207. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  208. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  209. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  210. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  211. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  212. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  213. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  214. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  215. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  216. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  217. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  218. package/src/runtime/attachments/store.d.mts +9 -0
  219. package/src/runtime/attachments/store.mjs +80 -9
  220. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  221. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  222. package/src/runtime/computer-bridge/action-schema.mjs +178 -178
  223. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  224. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  225. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  226. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  227. package/src/runtime/github/tool.mjs +118 -17
  228. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  229. package/src/runtime/media/catalog.mjs +4 -4
  230. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  231. package/src/runtime/media/defaults.mjs +37 -0
  232. package/src/runtime/media/jobs.mjs +12 -2
  233. package/src/runtime/media/lanes.mjs +12 -0
  234. package/src/runtime/media/tool-defs.mjs +15 -4
  235. package/src/runtime/media/tool.mjs +41 -12
  236. package/src/runtime/media/upstream-error.mjs +72 -6
  237. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  238. package/src/runtime/memory/lib/pg/process.mjs +5 -7
  239. package/src/runtime/memory/lib/pg/supervisor.mjs +4 -1
  240. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  241. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  242. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  243. package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
  244. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  245. package/src/runtime/office/core/office-write-ledger.mjs +1 -5
  246. package/src/runtime/office/index.mjs +2 -3
  247. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  248. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  249. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  250. package/src/runtime/shared/atomic-file.d.mts +1 -1
  251. package/src/runtime/shared/background-tasks.mjs +6 -1
  252. package/src/runtime/shared/bounded-line-diff.mjs +11 -2
  253. package/src/runtime/shared/browser-launch.mjs +15 -0
  254. package/src/runtime/shared/err-text.mjs +42 -4
  255. package/src/runtime/shared/file-lock.mjs +6 -5
  256. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  257. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  258. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  259. package/src/runtime/shared/model-route-chain.mjs +48 -0
  260. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  261. package/src/runtime/shared/pid-liveness.mjs +12 -0
  262. package/src/runtime/shared/provider-api-key.mjs +6 -0
  263. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  264. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  265. package/src/runtime/shared/quiet-progress.mjs +101 -0
  266. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  267. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  268. package/src/runtime/shared/remote-intent.mjs +2 -42
  269. package/src/runtime/shared/slow-span.mjs +8 -1
  270. package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
  271. package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
  272. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  273. package/src/runtime/shared/tool-result-summary.mjs +16 -2
  274. package/src/runtime/shared/tool-status.mjs +3 -2
  275. package/src/runtime/shared/tool-surface.mjs +2 -3
  276. package/src/runtime/shared/tool-work-units.mjs +22 -15
  277. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  278. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  279. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  280. package/src/runtime/shared/transcript-writer.mjs +14 -4
  281. package/src/runtime/shared/turn-changes.mjs +2 -1
  282. package/src/runtime/shared/turn-snapshot.mjs +11 -3
  283. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  284. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  285. package/src/runtime/shared/worktrees/carry.mjs +6 -4
  286. package/src/runtime/shared/worktrees/contract.mjs +27 -1
  287. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  288. package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
  289. package/src/runtime/shared/worktrees/git-head.mjs +22 -13
  290. package/src/runtime/shared/worktrees/include.mjs +125 -7
  291. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  292. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  293. package/src/runtime/shared/worktrees/manager.mjs +378 -32
  294. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  295. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  296. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  297. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  298. package/src/runtime/terminal-bridge/client.mjs +14 -10
  299. package/src/session-runtime/boot/apis.mjs +7 -1
  300. package/src/session-runtime/boot/config.mjs +2 -0
  301. package/src/session-runtime/boot/facade.mjs +3 -0
  302. package/src/session-runtime/boot/session.mjs +3 -2
  303. package/src/session-runtime/boot/tools.mjs +3 -0
  304. package/src/session-runtime/conversation-import/service.mjs +1 -1
  305. package/src/session-runtime/goal-facade-api.mjs +2 -2
  306. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
  307. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
  308. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
  309. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  310. package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
  311. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
  312. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
  313. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  314. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  315. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  316. package/src/session-runtime/lifecycle/teardown.mjs +7 -16
  317. package/src/session-runtime/media-api.mjs +8 -0
  318. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  319. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  320. package/src/session-runtime/model-route/set-route.mjs +114 -34
  321. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  322. package/src/session-runtime/model-route-api.mjs +4 -2
  323. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  324. package/src/session-runtime/native-web-search.mjs +9 -8
  325. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  326. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  327. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  328. package/src/session-runtime/provider-models.mjs +1 -0
  329. package/src/session-runtime/provider-usage.mjs +4 -0
  330. package/src/session-runtime/route-resolution.mjs +3 -1
  331. package/src/session-runtime/runtime-core.mjs +4 -0
  332. package/src/session-runtime/runtime-facade.mjs +6 -0
  333. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  334. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  335. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  336. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  337. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  338. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  339. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  340. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  341. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  342. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  343. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  344. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  345. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +9 -6
  346. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  347. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  348. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  349. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  350. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  351. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  352. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  353. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  354. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  355. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -9
  356. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  357. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  358. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  359. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  360. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  361. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  362. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  363. package/src/session-runtime/services/agent-tool/worker-index.mjs +28 -8
  364. package/src/session-runtime/services/agent-tool.mjs +4 -0
  365. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  366. package/src/session-runtime/services/provider-admin.mjs +77 -0
  367. package/src/session-runtime/session-create/session-options.mjs +7 -5
  368. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  369. package/src/session-runtime/session-transcript.mjs +4 -5
  370. package/src/session-runtime/session-turn-api.mjs +3 -9
  371. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
  372. package/src/session-runtime/setup-tool/executor.mjs +23 -5
  373. package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
  374. package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
  375. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
  376. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  377. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  378. package/src/session-runtime/turn/side-question-ops.mjs +1 -4
  379. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
  380. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
  381. package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
  382. package/src/session-runtime/turn/turn-run.mjs +1 -36
  383. package/src/session-runtime/usage-stats-api.mjs +4 -1
  384. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  385. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  386. package/src/session-runtime/workspace/project-branches.mjs +28 -36
  387. package/src/session-runtime/workspace/transition-steps.mjs +96 -95
  388. package/src/session-runtime/workspace/transitions.mjs +248 -68
  389. package/src/standalone/channel-transport.mjs +3 -4
  390. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  391. package/src/standalone/daemon-pg-stop.mjs +1 -3
  392. package/src/standalone/daemon-session-control.mjs +88 -0
  393. package/src/standalone/daemon-stored-session-views.mjs +23 -3
  394. package/src/standalone/daemon.mjs +2 -0
  395. package/src/standalone/desktop-service-registry.mjs +32 -5
  396. package/src/standalone/local-session-runtime.mjs +11 -12
  397. package/src/standalone/session-protocol.mjs +7 -0
  398. package/src/standalone/session-runtime-inline-host.mjs +2 -0
  399. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  400. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  401. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  402. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  403. package/src/standalone/session-service/agent-tree.mjs +28 -2
  404. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  405. package/src/standalone/session-service/entries.mjs +1 -0
  406. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  407. package/src/standalone/session-service/quota-resume.mjs +28 -13
  408. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  409. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  410. package/src/standalone/session-tool-output.mjs +82 -0
  411. package/src/tui/app/app-view.jsx +2 -1
  412. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  413. package/src/tui/app/provider-setup-picker.mjs +15 -3
  414. package/src/tui/app/slash-commands.mjs +6 -0
  415. package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
  416. package/src/tui/components/Spinner.jsx +4 -0
  417. package/src/tui/components/SpinnerByline.jsx +21 -2
  418. package/src/tui/components/status-line/local-line.mjs +10 -2
  419. package/src/tui/dist/index.mjs +529 -270
  420. package/src/tui/session/active-tool-summary.mjs +1 -1
  421. package/src/tui/session/context-state.mjs +0 -3
  422. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  423. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  424. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  425. package/src/tui/session/quota-resume.mjs +140 -61
  426. package/src/tui/session/session-api/commands.mjs +4 -10
  427. package/src/tui/session/session-api/controls.mjs +12 -0
  428. package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
  429. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  430. package/src/tui/session/session-api/lifecycle.mjs +13 -11
  431. package/src/tui/session/session-api/media.mjs +2 -0
  432. package/src/tui/session/session-api/routes.mjs +81 -57
  433. package/src/tui/session/session-api/settings.mjs +3 -3
  434. package/src/tui/session/session-api/worktree.mjs +3 -2
  435. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  436. package/src/tui/session/session-flow/drain.mjs +6 -4
  437. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  438. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  439. package/src/tui/session/session-flow/queue.mjs +1 -1
  440. package/src/tui/session/tool-approval.mjs +17 -8
  441. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  442. package/src/tui/session/tui-steering-persist.mjs +3 -5
  443. package/src/tui/session/turn-quiet.mjs +53 -0
  444. package/src/tui/session/turn-stream.mjs +5 -1
  445. package/src/tui/session/turn.mjs +38 -31
  446. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  447. package/src/tui/spinner-meta.mjs +10 -0
  448. package/src/tui/spinner-verbs.mjs +3 -0
  449. package/src/ui/statusline.mjs +13 -3
  450. package/src/ui/streaming-markdown-heal.mjs +70 -18
  451. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  452. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  453. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  454. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -302
  455. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  456. package/src/session-runtime/turn/share-ops.mjs +0 -77
  457. package/src/tui/session/cross-surface-share.mjs +0 -406
  458. package/src/tui/session/live-share/delta.mjs +0 -153
  459. package/src/tui/session/live-share/mirror.mjs +0 -106
  460. package/src/tui/session/live-share/owner.mjs +0 -254
  461. package/src/tui/session/live-share/retry.mjs +0 -54
  462. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  463. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  464. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  465. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  466. package/src/tui/session/live-share/viewer.mjs +0 -99
  467. package/src/tui/session/live-share/wire.mjs +0 -44
  468. package/src/tui/session/live-share.mjs +0 -154
  469. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -876,11 +876,11 @@ const isFailedToolResult = (message) => message.toolKind === 'error' || message.
876
876
  // recorded part, and a recorded Gemini part may carry no id at all, in which
877
877
  // case the response carries none either. An unmatched result keeps its own id.
878
878
  function toGeminiToolResult(message, toolNameByCallId, nestMedia, callsByFinalId) {
879
- const functionName = toolNameByCallId?.get(message.toolCallId) || message.toolCallId || '';
879
+ const replayedCall = callsByFinalId?.get(message.toolCallId);
880
+ const functionName = replayedCall?.name || toolNameByCallId?.get(message.toolCallId) || message.toolCallId || '';
880
881
  const { response: rawResponse, mediaParts } = splitGeminiToolContent(message.content);
881
882
  const response = isFailedToolResult(message) && 'result' in rawResponse ? { error: rawResponse.result } : rawResponse;
882
883
  const functionResponse = { name: functionName, response };
883
- const replayedCall = callsByFinalId?.get(message.toolCallId);
884
884
  const responseId = replayedCall ? replayedCall.id : message.toolCallId;
885
885
  if (typeof responseId === 'string' && responseId) functionResponse.id = responseId;
886
886
  if (!nestMedia) return { functionResponsePart: { functionResponse }, mediaParts };
@@ -895,16 +895,20 @@ function toGeminiToolResult(message, toolNameByCallId, nestMedia, callsByFinalId
895
895
  // A replay recorded by a non-Gemini model (Claude behind Antigravity) carries
896
896
  // signatures Gemini rejects: its replay envelope and the signed metadata
897
897
  // derived from the same response must not reach a Gemini request.
898
- function hasForeignReplay(message) {
898
+ function hasForeignReplay(message, model) {
899
899
  const replay = message?.providerReplay;
900
900
  if (replay?.provider !== 'gemini' && replay?.provider !== 'antigravity') return false;
901
901
  const recorded = replay.requestContext?.model;
902
- return typeof recorded === 'string' && recorded !== '' && !isGeminiFamilyModel(recorded);
902
+ return (
903
+ typeof recorded === 'string' &&
904
+ recorded !== '' &&
905
+ (!isGeminiFamilyModel(recorded) || (replay.provider === 'gemini' && model && recorded !== model))
906
+ );
903
907
  }
904
908
 
905
- function toGeminiContent(message) {
909
+ function toGeminiContent(message, model) {
906
910
  if (!message || message.role === 'system') return null;
907
- const foreign = message.role === 'assistant' && hasForeignReplay(message);
911
+ const foreign = message.role === 'assistant' && hasForeignReplay(message, model);
908
912
  if (foreign) message = { ...message, providerMetadata: undefined };
909
913
  const orderedReplay =
910
914
  message.role === 'assistant' && !foreign ? providerReplayItems(message, ['gemini', 'antigravity']) : undefined;
@@ -1019,7 +1023,7 @@ export function toGeminiContents(messages, model = '', { repairToolSignatures =
1019
1023
  for (const tc of m.toolCalls) {
1020
1024
  if (tc?.id && tc?.name) toolNameByCallId.set(tc.id, tc.name);
1021
1025
  }
1022
- const content = toGeminiContent(m);
1026
+ const content = toGeminiContent(m, model);
1023
1027
  assistantContent.set(m, content);
1024
1028
  const replayed = (content?.parts || []).filter((part) => part?.functionCall);
1025
1029
  m.toolCalls.forEach((tc, index) => {
@@ -1039,6 +1043,7 @@ export function toGeminiContents(messages, model = '', { repairToolSignatures =
1039
1043
  // first (one per call, in call order), then the media the results carried as
1040
1044
  // sibling inlineData/fileData parts.
1041
1045
  let toolTurn = null;
1046
+ let toolCallOrder = new Map();
1042
1047
  const nestMedia = supportsFunctionResponseParts(model);
1043
1048
  for (const message of messages) {
1044
1049
  if (message?.role === 'tool') {
@@ -1049,16 +1054,23 @@ export function toGeminiContents(messages, model = '', { repairToolSignatures =
1049
1054
  callsByFinalId
1050
1055
  );
1051
1056
  if (!toolTurn) {
1052
- toolTurn = { content: { role: 'user', parts: [] }, responseCount: 0 };
1057
+ toolTurn = { content: { role: 'user', parts: [] }, responseCount: 0, responseOrder: [] };
1053
1058
  contents.push(toolTurn.content);
1054
1059
  }
1055
- toolTurn.content.parts.splice(toolTurn.responseCount, 0, functionResponsePart);
1060
+ // Completion order is not call order. Anonymous parallel calls to the
1061
+ // same function can only be correlated by their original position.
1062
+ const order = toolCallOrder.get(message.toolCallId) ?? Infinity;
1063
+ const next = toolTurn.responseOrder.findIndex((value) => value > order);
1064
+ const index = next < 0 ? toolTurn.responseCount : next;
1065
+ toolTurn.responseOrder.splice(index, 0, order);
1066
+ toolTurn.content.parts.splice(index, 0, functionResponsePart);
1056
1067
  toolTurn.responseCount += 1;
1057
1068
  toolTurn.content.parts.push(...mediaParts);
1058
1069
  continue;
1059
1070
  }
1060
1071
  toolTurn = null;
1061
- const content = assistantContent.has(message) ? assistantContent.get(message) : toGeminiContent(message);
1072
+ toolCallOrder = new Map((message.toolCalls || []).map((call, index) => [call.id, index]));
1073
+ const content = assistantContent.has(message) ? assistantContent.get(message) : toGeminiContent(message, model);
1062
1074
  if (content) contents.push(content);
1063
1075
  }
1064
1076
  return repairToolSignatures ? ensureGeminiToolCallSignatures(contents, model) : contents;
@@ -513,7 +513,8 @@ function createLeakGuardFinalizer(textLeakGuard) {
513
513
  // `unwrapChunk` adapts a transport that nests the Gemini payload one level
514
514
  // deeper. Cloud Code Assist (Antigravity) streams `{ response: { candidates … } }`
515
515
  // while the public API streams the candidates directly; everything downstream —
516
- // aggregation, leak guard, watchdogs — stays shared.
516
+ // aggregation, leak guard, watchdogs — stays shared. `firstByteTimeoutMs` is
517
+ // the wait for the first chunk once the response headers arrived.
517
518
  export async function consumeGeminiRestStreamResponse(
518
519
  response,
519
520
  {
@@ -525,6 +526,7 @@ export async function consumeGeminiRestStreamResponse(
525
526
  unwrapChunk = null,
526
527
  onChunk = null,
527
528
  failureUsage = null,
529
+ firstByteTimeoutMs = GEMINI_FIRST_BYTE_TIMEOUT_MS,
528
530
  }
529
531
  ) {
530
532
  const unwrap =
@@ -548,7 +550,7 @@ export async function consumeGeminiRestStreamResponse(
548
550
  const watchdogs = createRestStreamWatchdogs({
549
551
  reader,
550
552
  label,
551
- firstByteTimeoutMs: GEMINI_FIRST_BYTE_TIMEOUT_MS,
553
+ firstByteTimeoutMs,
552
554
  timeoutError: geminiTimeoutError,
553
555
  });
554
556
  // One decoded chunk: collected for aggregation and relayed to every sink.
@@ -19,21 +19,43 @@ function catalogThinkingLevels(model, provider) {
19
19
  // Documented ranges: 2.5 Pro 128–32768 (cannot disable), 2.5 Flash 0–24576,
20
20
  // 2.5 Flash-Lite 0 or 512–24576; -1 is dynamic thinking for all of them.
21
21
  function budgetSpec(model) {
22
- const bare = String(model || '').replace(/^models\//i, '').toLowerCase();
22
+ const bare = String(model || '')
23
+ .replace(/^models\//i, '')
24
+ .toLowerCase();
23
25
  if (!/^gemini-2\.5(?:-|$)/.test(bare)) return null;
24
26
  if (/^gemini-2\.5-pro/.test(bare)) {
25
- return { name: 'Gemini 2.5 Pro', min: 128, max: 32768, canDisable: false, efforts: { minimal: 128, low: 1024, medium: 8192, high: 32768 } };
27
+ return {
28
+ name: 'Gemini 2.5 Pro',
29
+ min: 128,
30
+ max: 32768,
31
+ canDisable: false,
32
+ efforts: { minimal: 128, low: 1024, medium: 8192, high: 32768 },
33
+ };
26
34
  }
27
35
  if (/^gemini-2\.5-flash-lite/.test(bare)) {
28
- return { name: 'Gemini 2.5 Flash-Lite', min: 512, max: 24576, canDisable: true, efforts: { minimal: 512, low: 1024, medium: 8192, high: 24576 } };
36
+ return {
37
+ name: 'Gemini 2.5 Flash-Lite',
38
+ min: 512,
39
+ max: 24576,
40
+ canDisable: true,
41
+ efforts: { minimal: 512, low: 1024, medium: 8192, high: 24576 },
42
+ };
29
43
  }
30
- return { name: 'Gemini 2.5 Flash', min: 0, max: 24576, canDisable: true, efforts: { minimal: 0, low: 1024, medium: 8192, high: 24576 } };
44
+ return {
45
+ name: 'Gemini 2.5 Flash',
46
+ min: 0,
47
+ max: 24576,
48
+ canDisable: true,
49
+ efforts: { minimal: 0, low: 1024, medium: 8192, high: 24576 },
50
+ };
31
51
  }
32
52
 
33
53
  // Levels documented for models whose ladder differs from the generic wire
34
54
  // vocabulary (a catalog ladder, when declared, still takes precedence).
35
55
  function documentedThinkingLevels(model) {
36
- const bare = String(model || '').replace(/^models\//i, '').toLowerCase();
56
+ const bare = String(model || '')
57
+ .replace(/^models\//i, '')
58
+ .toLowerCase();
37
59
  if (bare === 'gemini-4-argon' || bare === 'gemini-3.8-flash') return ['low', 'medium', 'high'];
38
60
  return null;
39
61
  }
@@ -47,7 +69,9 @@ function checkBudget(model, spec, budget) {
47
69
  throw new TypeError(`${model} (${spec.name}) cannot disable thinking; thinkingBudget 0 is not allowed.`);
48
70
  }
49
71
  if (budget !== 0 && (budget < spec.min || budget > spec.max)) {
50
- throw new TypeError(`${model} (${spec.name}) thinkingBudget must be -1, ${spec.canDisable ? '0, or ' : ''}${spec.min}–${spec.max}; received ${budget}.`);
72
+ throw new TypeError(
73
+ `${model} (${spec.name}) thinkingBudget must be -1, ${spec.canDisable ? '0, or ' : ''}${spec.min}–${spec.max}; received ${budget}.`
74
+ );
51
75
  }
52
76
  }
53
77
 
@@ -75,7 +99,9 @@ export function geminiThinkingConfig(model, opts = {}, { includeThoughts, provid
75
99
  }
76
100
  if (spec && level) {
77
101
  if (!Object.hasOwn(spec.efforts, level)) {
78
- throw new TypeError(`${model} supports thinking levels ${Object.keys(spec.efforts).join(', ')}; received ${level}.`);
102
+ throw new TypeError(
103
+ `${model} supports thinking levels ${Object.keys(spec.efforts).join(', ')}; received ${level}.`
104
+ );
79
105
  }
80
106
  config.thinkingBudget = spec.efforts[level];
81
107
  } else if (level) {
@@ -731,8 +731,17 @@ export class GeminiProvider {
731
731
  }
732
732
 
733
733
  async _streamViaSdk(stream) {
734
- const { opts, signal, useModel, systemInstruction, geminiTools, toolConfig, generationConfig, safetySettings, contents } =
735
- stream;
734
+ const {
735
+ opts,
736
+ signal,
737
+ useModel,
738
+ systemInstruction,
739
+ geminiTools,
740
+ toolConfig,
741
+ generationConfig,
742
+ safetySettings,
743
+ contents,
744
+ } = stream;
736
745
  const genModel = this._currentGenAI().getGenerativeModel({
737
746
  model: useModel,
738
747
  systemInstruction,
@@ -3,7 +3,7 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
3
3
  // Grok CLI client version for the cli-chat-proxy version gate (HTTP 426).
4
4
  // Effective = env override, else max(floor, learned-from-426, live npm latest
5
5
  // of the official @xai-official/grok CLI).
6
- export const GROK_CLI_VERSION_FLOOR = '1.0.60';
6
+ export const GROK_CLI_VERSION_FLOOR = '1.0.62';
7
7
  export const GROK_CLI_NPM_PACKAGE = '@xai-official/grok';
8
8
 
9
9
  const live = createNpmVersionSource(GROK_CLI_NPM_PACKAGE, { persistKey: 'grok-cli' });
@@ -37,7 +37,9 @@ function lastEligibleBlockIndex(content) {
37
37
  export function countAnthropicCacheControls(value) {
38
38
  if (Array.isArray(value)) return value.reduce((sum, item) => sum + countAnthropicCacheControls(item), 0);
39
39
  if (!value || typeof value !== 'object') return 0;
40
- return (value.cache_control ? 1 : 0) + (Array.isArray(value.content) ? countAnthropicCacheControls(value.content) : 0);
40
+ return (
41
+ (value.cache_control ? 1 : 0) + (Array.isArray(value.content) ? countAnthropicCacheControls(value.content) : 0)
42
+ );
41
43
  }
42
44
 
43
45
  function stripCacheControl(block, budget) {
@@ -546,7 +548,12 @@ function toAnthropicTools(tools, logTag, onToolExcluded) {
546
548
  // `supportsDisableParallelToolUse: false` (gateway capability).
547
549
  export function toAnthropicToolChoice(
548
550
  toolChoice,
549
- { thinking = false, disableParallelToolUse = false, supportsDisableParallelToolUse = true, onThinkingConflict = 'fallback' } = {}
551
+ {
552
+ thinking = false,
553
+ disableParallelToolUse = false,
554
+ supportsDisableParallelToolUse = true,
555
+ onThinkingConflict = 'fallback',
556
+ } = {}
550
557
  ) {
551
558
  let choice;
552
559
  if (toolChoice === 'none') choice = { type: 'none' };
@@ -203,7 +203,8 @@ function assertObjectRoot(schema, rule) {
203
203
  function buildSchema(inputSchema) {
204
204
  if (!isPlainObject(inputSchema)) throw new SchemaProblem('', 'the input schema must be a JSON object schema');
205
205
  const { $schema, ...rest } = inputSchema;
206
- const schema = dialectOf(inputSchema) === 'draft-07' ? translateDraft07(rest, '', true, DRAFT07) : structuredClone(rest);
206
+ const schema =
207
+ dialectOf(inputSchema) === 'draft-07' ? translateDraft07(rest, '', true, DRAFT07) : structuredClone(rest);
207
208
  assertValidDraft202012(schema);
208
209
  assertObjectRoot(schema, 'anthropic');
209
210
  return schema;
@@ -222,8 +223,7 @@ function repairRoot(schema) {
222
223
  if (Array.isArray(type) && type.includes('object')) return { ...schema, type: 'object' };
223
224
  if (type !== undefined || Object.hasOwn(schema, '$ref')) return schema;
224
225
  const out = { type: 'object', ...schema };
225
- if (!Object.hasOwn(out, 'properties') && !ROOT_FORBIDDEN_KEYS.some((k) => Object.hasOwn(out, k)))
226
- out.properties = {};
226
+ if (!Object.hasOwn(out, 'properties') && !ROOT_FORBIDDEN_KEYS.some((k) => Object.hasOwn(out, k))) out.properties = {};
227
227
  return out;
228
228
  }
229
229
 
@@ -232,7 +232,8 @@ function refsIntoDefinitions(node) {
232
232
  if (Array.isArray(node)) return node.some(refsIntoDefinitions);
233
233
  if (!isPlainObject(node)) return false;
234
234
  return Object.entries(node).some(
235
- ([key, value]) => (key === '$ref' && typeof value === 'string' && /^#\/definitions(\/|$)/.test(value)) || refsIntoDefinitions(value)
235
+ ([key, value]) =>
236
+ (key === '$ref' && typeof value === 'string' && /^#\/definitions(\/|$)/.test(value)) || refsIntoDefinitions(value)
236
237
  );
237
238
  }
238
239
 
@@ -348,7 +349,10 @@ export function claudeBridgeInputSchema(inputSchema) {
348
349
  // Not valid as written: lower undeclared draft-07/04 constructs and
349
350
  // fill the root type; only a schema still broken is excluded.
350
351
  const repaired = repairedToolInputSchema(inputSchema, 'anthropic');
351
- result = repaired && !wireProblem(repaired, 'anthropic') ? { schema: repaired } : { pointer: error.pointer, reason: error.message };
352
+ result =
353
+ repaired && !wireProblem(repaired, 'anthropic')
354
+ ? { schema: repaired }
355
+ : { pointer: error.pointer, reason: error.message };
352
356
  }
353
357
  if (key !== null) {
354
358
  if (cache.size >= CACHE_LIMIT) cache.clear();
@@ -0,0 +1,86 @@
1
+ // Shared request-body compression for provider POSTs (Anthropic gzip, Codex
2
+ // zstd). Policy in one place:
3
+ // - bodies below REQ_COMPRESSION_MIN_BYTES are never compressed (CPU + header
4
+ // cost outweighs the upload saving);
5
+ // - a request that already carries Content-Encoding is never double-encoded;
6
+ // - a compression failure fails open to the plain body;
7
+ // - a 400/415 on a compressed request is drained and the SAME request is
8
+ // resent once uncompressed; compression latches off process-wide only when
9
+ // that plain resend succeeds (the encoding was the cause). If the resend
10
+ // fails too, nothing latches and the resend's response is returned.
11
+ import { promisify } from 'node:util';
12
+ import { gzip } from 'node:zlib';
13
+
14
+ export const REQ_COMPRESSION_MIN_BYTES = 8 * 1024;
15
+
16
+ export function createCompressionLatch(envVar) {
17
+ let latched = false;
18
+ return {
19
+ disabled: () => latched || process.env[envVar] === '0',
20
+ latchOff: () => {
21
+ latched = true;
22
+ },
23
+ reset: () => {
24
+ latched = false;
25
+ },
26
+ };
27
+ }
28
+
29
+ // One latch for every api.anthropic.com /v1/messages path (OAuth + API key).
30
+ export const anthropicGzipLatch = createCompressionLatch('MIXDOG_ANTHROPIC_REQ_GZIP');
31
+ // Compress on the libuv threadpool so large turn bodies never block the main thread.
32
+ export const gzipAsync = promisify(gzip);
33
+
34
+ export const hasContentEncoding = (headers) => new Headers(headers || {}).has('content-encoding');
35
+
36
+ export function withContentEncoding(headers, encoding) {
37
+ if (headers instanceof Headers || Array.isArray(headers)) {
38
+ const next = new Headers(headers);
39
+ next.delete('content-length');
40
+ next.set('Content-Encoding', encoding);
41
+ return next;
42
+ }
43
+ const rest = Object.fromEntries(
44
+ Object.entries(headers || {}).filter(([name]) => name.toLowerCase() !== 'content-length')
45
+ );
46
+ return { ...rest, 'Content-Encoding': encoding };
47
+ }
48
+
49
+ // Fail open: any compression error yields the plain body.
50
+ export async function compressBody(raw, compress, encoding) {
51
+ try {
52
+ return { bytes: await compress(raw), encoding };
53
+ } catch {
54
+ return { bytes: raw, encoding: null };
55
+ }
56
+ }
57
+
58
+ export const isEncodingRejection = (response) => response.status === 400 || response.status === 415;
59
+
60
+ export async function resendIfEncodingRejected({ response, encoded, resend, latch }) {
61
+ if (!encoded || !isEncodingRejection(response)) return response;
62
+ try {
63
+ await response.arrayBuffer();
64
+ } catch {
65
+ /* drain best-effort */
66
+ }
67
+ const retry = await resend();
68
+ if (retry.ok) latch.latchOff();
69
+ return retry;
70
+ }
71
+
72
+ /**
73
+ * Send `raw` compressed when eligible, with the rejection resend above.
74
+ * `send(bytes, headers)` performs one HTTP request.
75
+ */
76
+ export async function sendWithCompression({ raw, headers, encoding, compress, latch, send }) {
77
+ const plain = () => send(raw, headers);
78
+ if (latch.disabled() || raw.length < REQ_COMPRESSION_MIN_BYTES || hasContentEncoding(headers)) return plain();
79
+ const packed = await compressBody(raw, compress, encoding);
80
+ if (!packed.encoding) return plain();
81
+ const response = await send(packed.bytes, withContentEncoding(headers, encoding));
82
+ return resendIfEncodingRejected({ response, encoded: true, resend: plain, latch });
83
+ }
84
+
85
+ export const sendGzipCompressed = ({ compress = gzipAsync, ...rest }) =>
86
+ sendWithCompression({ ...rest, encoding: 'gzip', compress, latch: anthropicGzipLatch });
@@ -29,8 +29,10 @@ function isObject(value) {
29
29
  // answered by the server inside the same response. It is never a client call
30
30
  // awaiting a client output, so the guard neither pairs nor synthesizes it.
31
31
  function isServerToolSearch(item) {
32
- return (item.type === 'tool_search_call' || item.type === 'tool_search_output') &&
33
- (item.execution === 'server' || item.call_id === null);
32
+ return (
33
+ (item.type === 'tool_search_call' || item.type === 'tool_search_output') &&
34
+ (item.execution === 'server' || item.call_id === null)
35
+ );
34
36
  }
35
37
 
36
38
  function responsesCallId(item) {
@@ -167,7 +167,11 @@ function officeTextForFile(file) {
167
167
  });
168
168
  if (file.ref) return memoized(officeTextMemo, `ref:${file.ref}\0${file.filename || ''}`, compute);
169
169
  if (file.part && inlineOfficeText.has(file.part)) return inlineOfficeText.get(file.part);
170
- const key = createHash('sha256').update(file.filename || '').update('\0').update(file.data).digest('hex');
170
+ const key = createHash('sha256')
171
+ .update(file.filename || '')
172
+ .update('\0')
173
+ .update(file.data)
174
+ .digest('hex');
171
175
  const text = memoized(officeTextMemo, key, compute);
172
176
  if (file.part) inlineOfficeText.set(file.part, text);
173
177
  return text;
@@ -403,15 +407,19 @@ export async function preparePdfTextForProvider(messages, provider) {
403
407
  continue;
404
408
  }
405
409
  if (file && fileKind(file) === 'pdf') found.push({ part, file });
406
- else if (noDocuments && (file || part.type === 'document')) texts.set(part, file ? textFormOfFilePart(part) : documentSourceText(part));
410
+ else if (noDocuments && (file || part.type === 'document'))
411
+ texts.set(part, file ? textFormOfFilePart(part) : documentSourceText(part));
407
412
  }
408
413
  }
409
414
  if (!found.length && !texts.size) return messages;
410
415
  const extracted = await Promise.all(found.map(({ file }) => pdfTextFor(file)));
411
- found.forEach(({ part, file }, i) => texts.set(part, `--- ${fileLabel(file)} ---\n${extracted[i]}`));
416
+ found.forEach(({ part, file }, i) => {
417
+ texts.set(part, `--- ${fileLabel(file)} ---\n${extracted[i]}`);
418
+ });
412
419
  return messages.map((message) => {
413
420
  // A message whose content is one bare part becomes a one-part array.
414
- if (texts.has(message?.content)) return { ...message, content: [{ type: 'text', text: texts.get(message.content) }] };
421
+ if (texts.has(message?.content))
422
+ return { ...message, content: [{ type: 'text', text: texts.get(message.content) }] };
415
423
  const content = replacePdfParts(message?.content, texts);
416
424
  return content === message?.content ? message : { ...message, content };
417
425
  });
@@ -681,7 +689,10 @@ export function contentMediaBytes(content, { nativePdf = true } = {}) {
681
689
  if (!part || typeof part !== 'object') continue;
682
690
  if (isAttachmentReference(part)) {
683
691
  if (part.type === 'image') bytes += Math.ceil((Number(part.sizeBytes) || 0) / 3) * 4;
684
- else if (part.type === 'file' && countsAsMedia(String(part.mimeType || part.mediaType || 'application/pdf'), '')) {
692
+ else if (
693
+ part.type === 'file' &&
694
+ countsAsMedia(String(part.mimeType || part.mediaType || 'application/pdf'), '')
695
+ ) {
685
696
  bytes += Math.ceil((Number(part.sizeBytes) || 0) / 3) * 4;
686
697
  }
687
698
  continue;
@@ -9,7 +9,7 @@
9
9
  import { noteErrorUsage } from './lib/note-error-usage.mjs';
10
10
  import { fileMtimeMs, scrubOAuthSecrets } from './lib/oauth-token-utils.mjs';
11
11
  import { OpenAICompatProvider, preloadOpenAICompatRuntime } from './openai-compat.mjs';
12
- import { COMPAT_RETRY_POLICY } from './openai-compat-retry-profile.mjs';
12
+ import { COMPAT_RETRY_POLICY, compatFirstResponseBudget } from './openai-compat-retry-profile.mjs';
13
13
  import { fetchCompatModelItems, listCompatModels } from './openai-compat-models.mjs';
14
14
  import { makeModelCache } from './model-cache.mjs';
15
15
  import {
@@ -152,6 +152,12 @@ export class MimoOAuthProvider {
152
152
  return this.tokens;
153
153
  }
154
154
 
155
+ // The inner client's chat profile sets a longer first-byte window; the
156
+ // budget needs no credentials, so it is read from the profile directly.
157
+ firstResponseBudget() {
158
+ return compatFirstResponseBudget(this.name, MIMO_CHAT_PROFILE);
159
+ }
160
+
155
161
  _ensureInner() {
156
162
  const { apiKey, baseUrl } = this.ensureAuth();
157
163
  const key = `${baseUrl}:${apiKey}`;
@@ -90,6 +90,15 @@ export function inlineModelProxyAttachments(messages, { maxBytes = MODEL_PROXY_I
90
90
  return out ?? messages;
91
91
  }
92
92
 
93
+ /** A first-response budget the PC reported, or null for anything malformed. */
94
+ function reportedBudget(value) {
95
+ const transportMs = Number(value?.transportMs);
96
+ const semanticMs = Number(value?.semanticMs);
97
+ return transportMs > 0 && semanticMs > 0 && Number.isFinite(transportMs) && Number.isFinite(semanticMs)
98
+ ? { transportMs, semanticMs }
99
+ : null;
100
+ }
101
+
93
102
  export class ModelProxyProvider {
94
103
  #channel;
95
104
  #modelInfo = new Map();
@@ -101,6 +110,7 @@ export class ModelProxyProvider {
101
110
  this.#channel = channel;
102
111
  // Adapter traits are reported by the PC's real instance.
103
112
  if (typeof this.config.modelProxy?.nativePdf === 'boolean') this.nativePdf = this.config.modelProxy.nativePdf;
113
+ if (this.config.modelProxy?.consumesReadWindows === true) this.consumesReadWindows = true;
104
114
  }
105
115
 
106
116
  #call(method, fields = {}, options = {}) {
@@ -110,18 +120,16 @@ export class ModelProxyProvider {
110
120
  async send(messages, model, tools, sendOpts) {
111
121
  const { options, callbacks } = splitModelProxySendOptions(sendOpts);
112
122
  const finalized = isFinalizedProviderRequestTools(tools);
113
- const result = await this.#call(
114
- 'send',
115
- {
116
- model: model ?? null,
117
- messages: inlineModelProxyAttachments(messages),
118
- tools: Array.isArray(tools) ? tools : null,
119
- toolsFinalized: finalized,
120
- nativePrefixCount: finalized ? providerNativeToolPrefixCount(tools) : 0,
121
- options,
122
- },
123
- { signal: sendOpts?.signal || null, callbacks }
124
- );
123
+ const fields = {
124
+ model: model ?? null,
125
+ messages: inlineModelProxyAttachments(messages),
126
+ tools: Array.isArray(tools) ? tools : null,
127
+ toolsFinalized: finalized,
128
+ nativePrefixCount: finalized ? providerNativeToolPrefixCount(tools) : 0,
129
+ options,
130
+ };
131
+ const signal = sendOpts?.signal || null;
132
+ const result = await this.#call('send', fields, { signal, callbacks });
125
133
  // The PC rerouted the wire (a clear "unsupported" refusal) and reports the
126
134
  // route it used: the daemon's own session adopts it, so the next proxied
127
135
  // turn starts on the new wire instead of repeating the refusal.
@@ -163,6 +171,16 @@ export class ModelProxyProvider {
163
171
  return this.#modelInfo.get(String(model ?? '')) ?? null;
164
172
  }
165
173
 
174
+ /** The PC adapter's first-response budget for `model`: the catalog's
175
+ * model-specific figure, else the adapter's own from its provider config;
176
+ * null keeps the agent watchdog default. */
177
+ firstResponseBudget(model) {
178
+ return (
179
+ reportedBudget(this.getCachedModelInfo(model)?.firstResponseBudget) ??
180
+ reportedBudget(this.config.modelProxy?.firstResponseBudget)
181
+ );
182
+ }
183
+
166
184
  /** The PC adapter's wire route for `model` (its config and roster decide);
167
185
  * null for a single-wire adapter, which is remembered so every later turn
168
186
  * skips the round trip. */
@@ -222,10 +240,12 @@ export function loadModelProxyProviderConfig({
222
240
  channel = getModelProxyChannel(),
223
241
  now = Date.now,
224
242
  waitMs = MODEL_PROXY_CONFIG_WAIT_MS,
243
+ force = false,
225
244
  } = {}) {
226
245
  const generation = channel.generation;
227
246
  const cached = _providerConfigCache;
228
247
  if (
248
+ !force &&
229
249
  cached &&
230
250
  cached.channel === channel &&
231
251
  cached.generation === generation &&
@@ -234,7 +254,16 @@ export function loadModelProxyProviderConfig({
234
254
  return Promise.resolve(cached.value);
235
255
  }
236
256
  const inFlight = _providerConfigInFlight;
237
- if (inFlight && inFlight.channel === channel && inFlight.generation === generation) return inFlight.promise;
257
+ // A forced read starts after the caller's change, never reuses an older
258
+ // snapshot. Short setup reads also cannot inherit a registry init's budget.
259
+ if (
260
+ !force &&
261
+ inFlight &&
262
+ inFlight.channel === channel &&
263
+ inFlight.generation === generation &&
264
+ inFlight.waitMs === waitMs
265
+ )
266
+ return inFlight.promise;
238
267
  const promise = (async () => {
239
268
  const deadline = Date.now() + waitMs;
240
269
  let delay = CONFIG_RETRY_FIRST_MS;
@@ -247,12 +276,27 @@ export function loadModelProxyProviderConfig({
247
276
  }
248
277
  }
249
278
  try {
250
- const reply = await channel.request({ provider: '', method: 'providerConfig' });
279
+ const remaining = deadline - Date.now();
280
+ if (remaining <= 0) throw new ModelProxyUnavailableError('the desktop provider request timed out');
281
+ const controller = new AbortController();
282
+ const timer = setTimeout(
283
+ () => controller.abort(new ModelProxyUnavailableError('the desktop provider request timed out')),
284
+ remaining
285
+ );
286
+ timer.unref?.();
287
+ let reply;
288
+ try {
289
+ reply = await channel.request({ provider: '', method: 'providerConfig' }, { signal: controller.signal });
290
+ } finally {
291
+ clearTimeout(timer);
292
+ }
251
293
  const raw = reply?.providers && typeof reply.providers === 'object' ? reply.providers : {};
252
294
  // Defense in depth: the PC already strips secrets before sending.
253
295
  const value = stripModelProxySecrets(raw);
254
296
  if (providerConfigReady(reply, value)) {
255
- if (channel.generation === generation) {
297
+ // An older read may finish after a forced refresh; only the newest
298
+ // request may publish to the shared cache.
299
+ if (channel.generation === generation && _providerConfigInFlight === entry) {
256
300
  _providerConfigCache = { at: now(), value, channel, generation };
257
301
  }
258
302
  return value;
@@ -268,7 +312,7 @@ export function loadModelProxyProviderConfig({
268
312
  delay = Math.min(delay * 2, CONFIG_RETRY_MAX_MS);
269
313
  }
270
314
  })();
271
- const entry = { channel, generation, promise };
315
+ const entry = { channel, generation, waitMs, promise };
272
316
  _providerConfigInFlight = entry;
273
317
  const clear = () => {
274
318
  if (_providerConfigInFlight === entry) _providerConfigInFlight = null;
@@ -56,11 +56,6 @@ function resolveProbeState(paths, evaluate) {
56
56
  return sawUnreadable ? 'unreadable' : 'absent';
57
57
  }
58
58
 
59
- function pushUnique(list, value) {
60
- if (!value || typeof value !== 'string') return;
61
- if (!list.includes(value)) list.push(value);
62
- }
63
-
64
59
  // Short-TTL memo. Under simultaneous multi-agent launch, buildDefaultConfig
65
60
  // and registry lazy-init call these probes in bursts; each probe does
66
61
  // synchronous existsSync + readFileSync disk work. Cache the STATE per key
@@ -113,9 +108,11 @@ function memoProbe(key, paths, compute, extraSignature = '') {
113
108
  }
114
109
 
115
110
  function anthropicOAuthState() {
116
- const paths = [];
117
- pushUnique(paths, process.env.ANTHROPIC_OAUTH_CREDENTIALS_PATH);
118
- pushUnique(paths, ANTHROPIC_DEFAULT_CREDENTIALS_PATH);
111
+ const paths = [
112
+ boundProviderAuthPath('anthropic-oauth') ||
113
+ process.env.ANTHROPIC_OAUTH_CREDENTIALS_PATH ||
114
+ ANTHROPIC_DEFAULT_CREDENTIALS_PATH,
115
+ ];
119
116
  return memoProbe('anthropic-oauth', paths, () => {
120
117
  return resolveProbeState(paths, (docs) => {
121
118
  const candidates = [];
@@ -176,9 +173,7 @@ function mimoOAuthState() {
176
173
  process.env.MIMO_OAUTH_CREDENTIALS_PATH ||
177
174
  join(resolvePluginData(), 'mimo-oauth.json'),
178
175
  ];
179
- return memoProbe('mimo-oauth', paths, () =>
180
- resolveProbeState(paths, (docs) => docs.some((own) => !!own?.apiKey))
181
- );
176
+ return memoProbe('mimo-oauth', paths, () => resolveProbeState(paths, (docs) => docs.some((own) => !!own?.apiKey)));
182
177
  }
183
178
 
184
179
  function commandCodeOAuthState() {
@@ -230,7 +225,10 @@ function cursorEnvTokenFingerprint() {
230
225
  }
231
226
 
232
227
  function cursorOAuthState() {
233
- const paths = [process.env.CURSOR_OAUTH_CREDENTIALS_PATH, join(resolvePluginData(), 'cursor-oauth.json')];
228
+ // Match the adapter: selected account, then explicit path, then legacy file.
229
+ // An environment token must not authenticate a different selected account.
230
+ const bound = boundProviderAuthPath('cursor-oauth');
231
+ const paths = [bound || process.env.CURSOR_OAUTH_CREDENTIALS_PATH || join(resolvePluginData(), 'cursor-oauth.json')];
234
232
  // The env token is the whole answer on this branch and has no file metadata
235
233
  // behind it, so its VALUE is what the memo signature has to track: a length
236
234
  // (or a bare present/absent flag) let a swap to an equal-length expired token
@@ -245,7 +243,7 @@ function cursorOAuthState() {
245
243
  // Expiry is read by the one shared JWT reader (cursor-auth.cursorTokenExpiry),
246
244
  // which answers 0 for a non-JWT or unparseable token — exactly the "assume
247
245
  // usable" outcome this branch already took for those shapes.
248
- if (process.env.CURSOR_ACCESS_TOKEN) {
246
+ if (process.env.CURSOR_ACCESS_TOKEN && !bound) {
249
247
  const expiresAt = cursorTokenExpiry(process.env.CURSOR_ACCESS_TOKEN);
250
248
  return expiresAt === 0 || expiresAt > Date.now() ? 'present' : 'absent';
251
249
  }