mixdog 1.2.3 → 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 (465) 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/probe-provider-catalog.mjs +31 -0
  5. package/scripts/provider-pingpong-live.mjs +128 -38
  6. package/scripts/session-sweep.mjs +5 -25
  7. package/src/agents/maintainer/AGENT.md +1 -1
  8. package/src/agents/maintainer/agent.json +1 -1
  9. package/src/agents/reviewer/AGENT.md +2 -4
  10. package/src/agents/security/AGENT.md +1 -2
  11. package/src/agents/writer/AGENT.md +2 -3
  12. package/src/defaults/shipped-history.json +6 -1
  13. package/src/defaults/skills/image/SKILL.md +21 -23
  14. package/src/lib/keychain-cjs.cjs +13 -11
  15. package/src/rules/agent/AGENT.md +7 -5
  16. package/src/rules/lead/LEAD.md +7 -9
  17. package/src/rules/shared/45-destructive.md +4 -0
  18. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  19. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  20. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  21. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  22. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  23. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  24. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +1 -1
  25. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
  26. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  28. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2 -5
  29. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -0
  30. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  31. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  32. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +81 -10
  33. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
  34. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
  35. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
  36. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
  37. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
  38. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  40. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  41. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  42. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  43. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +41 -11
  44. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
  46. package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
  47. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
  48. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
  49. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
  50. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
  51. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
  52. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
  53. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  54. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  55. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +6 -1
  56. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
  57. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
  58. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
  59. package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
  60. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  61. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
  62. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
  63. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  64. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
  65. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
  66. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  67. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
  68. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
  69. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
  70. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  72. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
  74. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
  75. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
  76. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  78. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
  79. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  80. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +3 -1
  81. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
  82. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
  83. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
  84. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
  85. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
  86. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
  87. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
  88. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
  89. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
  90. package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
  91. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
  92. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
  93. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
  94. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
  95. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
  96. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  97. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
  98. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  99. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  100. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  101. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +3 -1
  102. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  103. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
  104. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
  105. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
  106. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  107. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  108. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  109. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  110. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  111. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -11
  112. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  113. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
  114. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  115. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
  116. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  118. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  119. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +1 -1
  120. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  121. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  122. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -4
  123. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
  124. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -27
  125. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  126. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  127. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  128. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +4 -1
  129. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
  130. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
  131. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  132. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
  133. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
  134. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  135. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
  136. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
  137. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
  138. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  139. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  140. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +21 -1
  141. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
  142. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  143. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
  144. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
  145. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  146. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  147. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  148. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  149. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +29 -8
  150. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  151. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  152. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +32 -14
  153. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
  155. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  156. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
  157. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  158. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
  159. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  160. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
  161. package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
  162. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
  163. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  164. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  165. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  167. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  169. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +5 -11
  170. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  171. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  172. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -32
  174. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  175. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  176. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  177. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +1 -1
  178. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  179. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
  180. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
  181. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  182. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  183. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +7 -8
  184. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  185. package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
  186. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
  187. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
  188. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  189. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
  190. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  191. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  192. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  193. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  194. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  195. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +204 -10
  196. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  197. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  198. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  199. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  200. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  201. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  202. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  203. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +200 -17
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  205. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  206. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  207. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  208. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  209. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  210. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  211. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  212. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  213. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  214. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  215. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  216. package/src/runtime/attachments/store.d.mts +9 -0
  217. package/src/runtime/attachments/store.mjs +80 -9
  218. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  219. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  220. package/src/runtime/computer-bridge/action-schema.mjs +178 -178
  221. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  222. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  223. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  224. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  225. package/src/runtime/github/tool.mjs +118 -17
  226. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  227. package/src/runtime/media/catalog.mjs +4 -4
  228. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  229. package/src/runtime/media/defaults.mjs +37 -0
  230. package/src/runtime/media/jobs.mjs +12 -2
  231. package/src/runtime/media/lanes.mjs +12 -0
  232. package/src/runtime/media/tool-defs.mjs +15 -4
  233. package/src/runtime/media/tool.mjs +41 -12
  234. package/src/runtime/media/upstream-error.mjs +72 -6
  235. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  236. package/src/runtime/memory/lib/pg/process.mjs +5 -7
  237. package/src/runtime/memory/lib/pg/supervisor.mjs +4 -1
  238. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  239. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  240. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  241. package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
  242. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  243. package/src/runtime/office/core/office-write-ledger.mjs +1 -5
  244. package/src/runtime/office/index.mjs +2 -3
  245. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  246. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  247. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  248. package/src/runtime/shared/atomic-file.d.mts +1 -1
  249. package/src/runtime/shared/background-tasks.mjs +6 -1
  250. package/src/runtime/shared/bounded-line-diff.mjs +11 -2
  251. package/src/runtime/shared/browser-launch.mjs +15 -0
  252. package/src/runtime/shared/err-text.mjs +42 -4
  253. package/src/runtime/shared/file-lock.mjs +6 -5
  254. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  255. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  256. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  257. package/src/runtime/shared/model-route-chain.mjs +48 -0
  258. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  259. package/src/runtime/shared/pid-liveness.mjs +12 -0
  260. package/src/runtime/shared/provider-api-key.mjs +6 -0
  261. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  262. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  263. package/src/runtime/shared/quiet-progress.mjs +101 -0
  264. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  265. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  266. package/src/runtime/shared/remote-intent.mjs +2 -42
  267. package/src/runtime/shared/slow-span.mjs +8 -1
  268. package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
  269. package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
  270. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  271. package/src/runtime/shared/tool-result-summary.mjs +16 -2
  272. package/src/runtime/shared/tool-status.mjs +3 -2
  273. package/src/runtime/shared/tool-surface.mjs +2 -3
  274. package/src/runtime/shared/tool-work-units.mjs +22 -15
  275. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  276. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  277. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  278. package/src/runtime/shared/transcript-writer.mjs +14 -4
  279. package/src/runtime/shared/turn-changes.mjs +2 -1
  280. package/src/runtime/shared/turn-snapshot.mjs +11 -3
  281. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  282. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  283. package/src/runtime/shared/worktrees/carry.mjs +6 -4
  284. package/src/runtime/shared/worktrees/contract.mjs +27 -1
  285. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  286. package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
  287. package/src/runtime/shared/worktrees/git-head.mjs +22 -13
  288. package/src/runtime/shared/worktrees/include.mjs +125 -7
  289. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  290. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  291. package/src/runtime/shared/worktrees/manager.mjs +378 -32
  292. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  293. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  294. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  295. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  296. package/src/runtime/terminal-bridge/client.mjs +14 -10
  297. package/src/session-runtime/boot/apis.mjs +7 -1
  298. package/src/session-runtime/boot/config.mjs +2 -0
  299. package/src/session-runtime/boot/facade.mjs +3 -0
  300. package/src/session-runtime/boot/session.mjs +3 -2
  301. package/src/session-runtime/boot/tools.mjs +3 -0
  302. package/src/session-runtime/conversation-import/service.mjs +1 -1
  303. package/src/session-runtime/goal-facade-api.mjs +2 -2
  304. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
  305. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
  306. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
  307. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  308. package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
  309. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
  310. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
  311. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  312. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  313. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  314. package/src/session-runtime/lifecycle/teardown.mjs +7 -16
  315. package/src/session-runtime/media-api.mjs +8 -0
  316. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  317. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  318. package/src/session-runtime/model-route/set-route.mjs +114 -34
  319. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  320. package/src/session-runtime/model-route-api.mjs +4 -2
  321. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  322. package/src/session-runtime/native-web-search.mjs +9 -8
  323. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  324. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  325. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  326. package/src/session-runtime/provider-models.mjs +1 -0
  327. package/src/session-runtime/provider-usage.mjs +4 -0
  328. package/src/session-runtime/route-resolution.mjs +3 -1
  329. package/src/session-runtime/runtime-core.mjs +4 -0
  330. package/src/session-runtime/runtime-facade.mjs +6 -0
  331. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  332. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  333. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  334. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  335. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  336. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  337. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  338. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  339. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  340. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  341. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  342. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  343. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +9 -6
  344. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  345. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  346. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  347. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  348. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  349. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  350. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  351. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  352. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  353. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -9
  354. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  355. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  356. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  357. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  358. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  359. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  360. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  361. package/src/session-runtime/services/agent-tool/worker-index.mjs +28 -8
  362. package/src/session-runtime/services/agent-tool.mjs +4 -0
  363. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  364. package/src/session-runtime/services/provider-admin.mjs +77 -0
  365. package/src/session-runtime/session-create/session-options.mjs +7 -5
  366. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  367. package/src/session-runtime/session-transcript.mjs +4 -5
  368. package/src/session-runtime/session-turn-api.mjs +3 -9
  369. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
  370. package/src/session-runtime/setup-tool/executor.mjs +23 -5
  371. package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
  372. package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
  373. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
  374. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  375. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  376. package/src/session-runtime/turn/side-question-ops.mjs +1 -4
  377. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
  378. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
  379. package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
  380. package/src/session-runtime/turn/turn-run.mjs +1 -36
  381. package/src/session-runtime/usage-stats-api.mjs +4 -1
  382. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  383. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  384. package/src/session-runtime/workspace/project-branches.mjs +28 -36
  385. package/src/session-runtime/workspace/transition-steps.mjs +96 -95
  386. package/src/session-runtime/workspace/transitions.mjs +248 -68
  387. package/src/standalone/channel-transport.mjs +3 -4
  388. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  389. package/src/standalone/daemon-pg-stop.mjs +1 -3
  390. package/src/standalone/daemon-session-control.mjs +88 -0
  391. package/src/standalone/daemon-stored-session-views.mjs +23 -3
  392. package/src/standalone/daemon.mjs +2 -0
  393. package/src/standalone/local-session-runtime.mjs +11 -12
  394. package/src/standalone/session-protocol.mjs +7 -0
  395. package/src/standalone/session-runtime-inline-host.mjs +2 -0
  396. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  397. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  398. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  399. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  400. package/src/standalone/session-service/agent-tree.mjs +28 -2
  401. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  402. package/src/standalone/session-service/entries.mjs +1 -0
  403. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  404. package/src/standalone/session-service/quota-resume.mjs +28 -13
  405. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  406. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  407. package/src/standalone/session-tool-output.mjs +82 -0
  408. package/src/tui/app/app-view.jsx +2 -1
  409. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  410. package/src/tui/app/provider-setup-picker.mjs +15 -3
  411. package/src/tui/app/slash-commands.mjs +6 -0
  412. package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
  413. package/src/tui/components/Spinner.jsx +4 -0
  414. package/src/tui/components/SpinnerByline.jsx +21 -2
  415. package/src/tui/components/status-line/local-line.mjs +10 -2
  416. package/src/tui/dist/index.mjs +478 -251
  417. package/src/tui/session/active-tool-summary.mjs +1 -1
  418. package/src/tui/session/context-state.mjs +0 -3
  419. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  420. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  421. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  422. package/src/tui/session/quota-resume.mjs +140 -61
  423. package/src/tui/session/session-api/commands.mjs +4 -10
  424. package/src/tui/session/session-api/controls.mjs +12 -0
  425. package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
  426. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  427. package/src/tui/session/session-api/lifecycle.mjs +13 -11
  428. package/src/tui/session/session-api/media.mjs +2 -0
  429. package/src/tui/session/session-api/routes.mjs +81 -57
  430. package/src/tui/session/session-api/settings.mjs +3 -3
  431. package/src/tui/session/session-api/worktree.mjs +3 -2
  432. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  433. package/src/tui/session/session-flow/drain.mjs +6 -4
  434. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  435. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  436. package/src/tui/session/session-flow/queue.mjs +1 -1
  437. package/src/tui/session/tool-approval.mjs +17 -8
  438. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  439. package/src/tui/session/tui-steering-persist.mjs +3 -5
  440. package/src/tui/session/turn-quiet.mjs +53 -0
  441. package/src/tui/session/turn-stream.mjs +5 -1
  442. package/src/tui/session/turn.mjs +38 -31
  443. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  444. package/src/tui/spinner-meta.mjs +10 -0
  445. package/src/tui/spinner-verbs.mjs +3 -0
  446. package/src/ui/statusline.mjs +13 -3
  447. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  448. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  449. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  450. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -302
  451. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  452. package/src/session-runtime/turn/share-ops.mjs +0 -77
  453. package/src/tui/session/cross-surface-share.mjs +0 -406
  454. package/src/tui/session/live-share/delta.mjs +0 -153
  455. package/src/tui/session/live-share/mirror.mjs +0 -106
  456. package/src/tui/session/live-share/owner.mjs +0 -254
  457. package/src/tui/session/live-share/retry.mjs +0 -54
  458. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  459. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  460. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  461. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  462. package/src/tui/session/live-share/viewer.mjs +0 -99
  463. package/src/tui/session/live-share/wire.mjs +0 -44
  464. package/src/tui/session/live-share.mjs +0 -154
  465. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -3,12 +3,14 @@
3
3
  * to the shared stream state and relayed to the SSE sink. Returns the
4
4
  * message's forward-progress kind for the watchdog.
5
5
  */
6
+ import { randomUUID } from 'node:crypto';
7
+ import { registerCursorNativeCall } from './cursor-native-context.mjs';
6
8
  import { appendAgentTrace } from '../agent-trace.mjs';
7
9
  import { decodeMessage } from './cursor-wire-protobuf.mjs';
8
10
  import { MAX_CHECKPOINT_BYTES, cursorInteractionProgress } from './cursor-wire-guards.mjs';
9
11
  import { buildCursorInteractionResponse } from './cursor-wire-interactions.mjs';
10
12
  import { cursorError } from './cursor-wire-transport.mjs';
11
- import { handleExecMessage, handleKvMessage, sendClientMessage } from './cursor-wire-exec.mjs';
13
+ import { handleExecMessage, handleKvMessage, sendClientMessage, sendToolResult } from './cursor-wire-exec.mjs';
12
14
 
13
15
  // Unknown fields seen on every live frame: AgentServerMessage field 8 (timing
14
16
  // doubles) and InteractionUpdate field 25 (epoch-ms timestamp). Never traced.
@@ -43,6 +45,31 @@ function traceUnknownFields(trace, sessionId, scope, unknown, noise) {
43
45
  }
44
46
  }
45
47
 
48
+ // Parent edit outcomes are diagnostics, not executable calls or read results.
49
+ function traceNativeEditFailure(trace, sessionId, update) {
50
+ const completed = update.toolCallCompleted;
51
+ const result = completed?.toolCall?.editToolCall?.result;
52
+ if (!result) return;
53
+ const outcome = ['fileNotFound', 'readPermissionDenied', 'writePermissionDenied', 'rejected', 'error'].find(
54
+ (key) => result[key] !== undefined
55
+ );
56
+ if (!outcome) return;
57
+ try {
58
+ trace({
59
+ sessionId,
60
+ kind: 'cursor_native_edit_failure',
61
+ provider: 'cursor',
62
+ payload: {
63
+ callId: (completed.callId || '').slice(0, 256),
64
+ modelCallId: (completed.modelCallId || '').slice(0, 256),
65
+ outcome,
66
+ },
67
+ });
68
+ } catch {
69
+ /* best-effort */
70
+ }
71
+ }
72
+
46
73
  // Relays one interaction update to the SSE stream and returns its progress.
47
74
  function applyInteractionUpdate(update, state, filter, emit) {
48
75
  if (update.textDelta?.text) {
@@ -79,9 +106,32 @@ function applyCheckpointUpdate(update, conversation, state) {
79
106
  }
80
107
 
81
108
  // Announces a newly pending native/MCP tool call as a completion chunk once.
82
- function announcePendingToolCall(state, pending, emit) {
83
- if (state.pending.some((entry) => entry.toolCallId === pending.toolCallId)) return;
109
+ function announcePendingToolCall(state, pending, emit, bridge, ownerSessionId) {
110
+ state.executions ??= new Map();
111
+ const executions = state.executions;
112
+ const execId = pending.exec.execId ?? pending.exec.id;
113
+ const previous = execId !== undefined ? executions.get(execId) : undefined;
114
+ if (previous) {
115
+ if (previous.completedResult) {
116
+ sendToolResult(
117
+ bridge,
118
+ { ...previous, exec: pending.exec },
119
+ previous.completedResult.result,
120
+ previous.completedResult.ok
121
+ );
122
+ }
123
+ return;
124
+ }
125
+ // A parent call can issue distinct executions; each needs its own local result.
126
+ if ([...executions.values(), ...state.pending].some((entry) => entry.toolCallId === pending.toolCallId)) {
127
+ pending.toolCallId = randomUUID();
128
+ }
129
+ if (execId !== undefined) executions.set(execId, pending);
130
+ registerCursorNativeCall(ownerSessionId, pending, executions);
84
131
  state.pending.push(pending);
132
+ // Native execs may await their result before the server completes a step.
133
+ // The bridge hands off only after all currently received frames are whole.
134
+ if (pending.native) state.batchBoundaryReady = true;
85
135
  emit({
86
136
  tool_calls: [
87
137
  {
@@ -101,12 +151,24 @@ function announcePendingToolCall(state, pending, emit) {
101
151
  */
102
152
  export function processServerMessage(
103
153
  bytes,
104
- { state, filter, emit, conversation, tools, cloudRule, bridge, sessionId = '', trace = appendAgentTrace }
154
+ {
155
+ state,
156
+ filter,
157
+ emit,
158
+ conversation,
159
+ tools,
160
+ cloudRule,
161
+ bridge,
162
+ sessionId = '',
163
+ ownerSessionId = '',
164
+ trace = appendAgentTrace,
165
+ }
105
166
  ) {
106
167
  const message = decodeMessage('AgentServerMessage', bytes);
107
168
  traceUnknownFields(trace, sessionId, 'agent_server_message', message.$unknown, NOISE_SERVER_FIELDS);
108
169
  if (message.interactionUpdate) {
109
170
  traceUnknownFields(trace, sessionId, 'interaction_update', message.interactionUpdate.$unknown, NOISE_UPDATE_FIELDS);
171
+ traceNativeEditFailure(trace, sessionId, message.interactionUpdate);
110
172
  }
111
173
  if (message.interactionUpdate) return applyInteractionUpdate(message.interactionUpdate, state, filter, emit);
112
174
  if (message.kvServerMessage) {
@@ -119,7 +181,7 @@ export function processServerMessage(
119
181
  }
120
182
  if (message.execServerMessage) {
121
183
  const handled = handleExecMessage(bridge, message.execServerMessage, tools, cloudRule, (pending) =>
122
- announcePendingToolCall(state, pending, emit)
184
+ announcePendingToolCall(state, pending, emit, bridge, ownerSessionId)
123
185
  );
124
186
  return handled === false ? 'park' : 'work';
125
187
  }
@@ -328,11 +328,12 @@ function createPendingToolBatchResponse(active, model, key) {
328
328
  }
329
329
 
330
330
  // Stream state shared by the sink, the message router and the bridge controller.
331
- function freshStreamState(sawTurnEnded) {
331
+ function freshStreamState(sawTurnEnded, executions) {
332
332
  return {
333
333
  outputTokens: 0,
334
334
  contextTokens: null,
335
335
  pending: [],
336
+ executions,
336
337
  closed: false,
337
338
  sawEnd: false,
338
339
  sawTurnEnded: sawTurnEnded === true,
@@ -360,7 +361,9 @@ function createStreamResponse({
360
361
  // Owning session, carried into the stored run so a session close can find
361
362
  // and tear down the pending batch's bridge/heartbeat.
362
363
  sessionId = '',
364
+ ownerSessionId = sessionId,
363
365
  sawTurnEnded = false,
366
+ executions = new Map(),
364
367
  restart = null,
365
368
  sleep = undefined,
366
369
  onStageChange = null,
@@ -376,7 +379,7 @@ function createStreamResponse({
376
379
  const stream = new ReadableStream({
377
380
  start(controller) {
378
381
  const filter = thinkingFilter();
379
- const state = freshStreamState(sawTurnEnded);
382
+ const state = freshStreamState(sawTurnEnded, executions);
380
383
  const tuning = resolveCursorStreamTuning();
381
384
  watchdog = createCursorStreamWatchdog({
382
385
  idleTimeoutMs: tuning.idleTimeoutMs,
@@ -400,7 +403,7 @@ function createStreamResponse({
400
403
  watchdog,
401
404
  sink,
402
405
  tuning,
403
- run: { key, conversation, tools, cloudRule, modelParameters, maxMode, sessionId },
406
+ run: { key, conversation, tools, cloudRule, modelParameters, maxMode, sessionId, ownerSessionId },
404
407
  runs,
405
408
  restart,
406
409
  sleep,
@@ -449,6 +452,7 @@ function resumeRun(active, toolResults, userText, model, key) {
449
452
  }
450
453
  const payload = { ...result, content: String(result.content ?? '') };
451
454
  if (pendingUserText && pending.exec.execId === lastExecId) {
455
+ if (pending.native?.resultType === 'readResult') pending.nativeUserMessage = pendingUserText;
452
456
  payload.content += `\n\n<user_message>\n${pendingUserText}\n</user_message>`;
453
457
  userTextDelivered = true;
454
458
  }
@@ -471,7 +475,11 @@ function noUserMessageResponse() {
471
475
  });
472
476
  }
473
477
 
474
- export async function handleChatCompletion(body, accessToken, { onStageChange = null, getAccessToken = null } = {}) {
478
+ export async function handleChatCompletion(
479
+ body,
480
+ accessToken,
481
+ { onStageChange = null, getAccessToken = null, resetActiveRun = false, ownerSessionId = '' } = {}
482
+ ) {
475
483
  await warmCursorClientVersion();
476
484
  const parsed = parseMessages(body.messages);
477
485
  if (
@@ -492,6 +500,7 @@ export async function handleChatCompletion(body, accessToken, { onStageChange =
492
500
  const cloudRule = parsed.systems.join('\n\n') || undefined;
493
501
  const active = activeRuns.get(key);
494
502
  if (
503
+ !resetActiveRun &&
495
504
  active &&
496
505
  parsed.toolResults.length &&
497
506
  active.bridge.alive &&
@@ -531,6 +540,7 @@ export async function handleChatCompletion(body, accessToken, { onStageChange =
531
540
  maxMode,
532
541
  key,
533
542
  sessionId,
543
+ ownerSessionId,
534
544
  onStageChange,
535
545
  restart: async ({ fromCheckpoint, reason, error }) => {
536
546
  if (reason === 'throttle') {
@@ -49,6 +49,7 @@ function toCursorMessages(messages, providerName, { nativePdf } = {}) {
49
49
  ...toolMessage,
50
50
  mixdog_tool_error: message.toolKind === 'error' || message.isError === true,
51
51
  ...(media.length ? { mixdog_tool_media: media } : {}),
52
+ ...(message.readWindow?.lineClipped === true ? { mixdog_read_window: { lineClipped: true } } : {}),
52
53
  });
53
54
  }
54
55
  return output;
@@ -545,6 +546,9 @@ function selectCursorVariant(group, { effort = null, fast = false } = {}) {
545
546
  class CursorProviderBase {
546
547
  // Cursor's chat wire has no document block: PDFs lower to text.
547
548
  nativePdf = false;
549
+ // Native read results are judged as exact source windows, so the tool
550
+ // finalizer reports their clipped lines next to the text.
551
+ consumesReadWindows = true;
548
552
 
549
553
  static inputExcludesCache = false;
550
554
  // The in-place stream retry budget is the whole recovery: a spent budget
@@ -640,6 +644,13 @@ class CursorProviderBase {
640
644
  const response = await runtime.handleChatCompletion(body, accessToken, {
641
645
  onStageChange: sendOpts.onStageChange,
642
646
  getAccessToken: (options) => this._accessToken({ signal, ...options }),
647
+ // A deliberate history reset must reach Cursor's private parked run,
648
+ // not just the orchestrator's providerState.
649
+ resetActiveRun: Boolean(sendOpts.cacheBreakIntent),
650
+ // Native read/edit capabilities are process-local. An explicit empty
651
+ // executor (the model-proxy host: tools run in the server daemon)
652
+ // keeps every call an ordinary Mixdog tool call.
653
+ ownerSessionId: String(sendOpts.toolExecutionSessionId ?? (sendOpts.sessionId || '')),
643
654
  });
644
655
  try {
645
656
  sendOpts.onStageChange?.('streaming');
@@ -699,7 +710,9 @@ class CursorProviderBase {
699
710
  const sessionScope = String(
700
711
  sendOpts.transportScope ||
701
712
  sendOpts.sessionId ||
702
- sendOpts.providerCacheKey || sendOpts.promptCacheKey || `cursor-call:${randomUUID()}`
713
+ sendOpts.providerCacheKey ||
714
+ sendOpts.promptCacheKey ||
715
+ `cursor-call:${randomUUID()}`
703
716
  );
704
717
  const openAiTools = tools?.length
705
718
  ? toOpenAITools(acceptedWireTools(tools, 'openai', sendOpts.onToolExcluded, '[cursor] tool'))
@@ -386,6 +386,14 @@ function catalogLevels(row) {
386
386
  return levels.size ? [...levels].sort(byRank) : null;
387
387
  }
388
388
 
389
+ function reasoningLevelFields(levels) {
390
+ if (!levels) return {};
391
+ return {
392
+ reasoningOptions: levels.length ? [{ type: 'effort', values: [...levels] }] : [],
393
+ reasoningLevels: [...levels],
394
+ };
395
+ }
396
+
389
397
  function effectiveRow(base, override, { providerId, discovered, newModelsHidden }) {
390
398
  const ov = override || {};
391
399
  const reasoning = ov.reasoning || {};
@@ -413,12 +421,7 @@ function effectiveRow(base, override, { providerId, discovered, newModelsHidden
413
421
  hidden,
414
422
  manual: ov.manual === true,
415
423
  supportsReasoning: levels ? levels.some((level) => level !== 'none') : base.supportsReasoning === true,
416
- ...(levels
417
- ? {
418
- reasoningOptions: levels.length ? [{ type: 'effort', values: [...levels] }] : [],
419
- reasoningLevels: [...levels],
420
- }
421
- : {}),
424
+ ...reasoningLevelFields(levels),
422
425
  customReasoning: { wireFormat: reasoning.wireFormat ?? 'standard', wireValues, replay },
423
426
  ...(replay ? { reasoningContentField: 'reasoning_content' } : {}),
424
427
  };
@@ -173,7 +173,11 @@ export async function createCustomProvider(id, config) {
173
173
  if (providerOffersWire(providerId, 'messages')) {
174
174
  const { AnthropicProvider } = await import('./anthropic.mjs');
175
175
  // The Anthropic SDK appends /v1/messages itself; the endpoint's /v1 base maps to it.
176
- messagesEngine = new AnthropicProvider({ ...engine, name: providerId, baseURL: cfg.baseURL.replace(/\/v1$/i, '') });
176
+ messagesEngine = new AnthropicProvider({
177
+ ...engine,
178
+ name: providerId,
179
+ baseURL: cfg.baseURL.replace(/\/v1$/i, ''),
180
+ });
177
181
  messagesEngine.nativePdf = false;
178
182
  }
179
183
  class CompatBase extends OpenAICompatProvider {
@@ -207,7 +211,8 @@ export async function createCustomProvider(id, config) {
207
211
  // The bound Messages engine reads the parent's model rows, so a routed
208
212
  // Messages request carries the same row-driven thinking/effort as the
209
213
  // Anthropic protocol.
210
- if (provider.messagesEngine) provider.messagesEngine.getCachedModelInfo = (model) => provider.getCachedModelInfo(model);
214
+ if (provider.messagesEngine)
215
+ provider.messagesEngine.getCachedModelInfo = (model) => provider.getCachedModelInfo(model);
211
216
  provider.customConfig = cfg;
212
217
  provider._customKeyless = keyless;
213
218
  provider._applyCustomRows(provider._customRows());
@@ -1,3 +1,4 @@
1
+ import { isVisibleStreamProgress } from '../../../shared/stream-progress.mjs';
1
2
  import { anthropicEffortLevelsFor, normalizeAnthropicEffortInput } from './anthropic-effort.mjs';
2
3
  import { CUSTOM_EFFORT_LEVELS, customEffortLevels, isCustomProviderName } from './custom-reasoning.mjs';
3
4
  import { codexModelSupportsEffortUpdates } from './openai-oauth-catalog.mjs';
@@ -72,19 +73,40 @@ export function isEffortConfigurationRejection(status, text) {
72
73
  /**
73
74
  * Runs `send(opts)`; when the model rejects the mid-conversation effort
74
75
  * update, switches the updates off for it and replays the request once
75
- * without them. The rejection happens before any output streams.
76
+ * without them. Never replay after output reached the caller, cancellation,
77
+ * or an explicit opt-out; a late error is not evidence of missing support.
76
78
  */
77
79
  export async function withEffortConfigurationFallback(provider, model, opts, send) {
80
+ let streamed = false;
81
+ const track =
82
+ (callback, isProgress = false) =>
83
+ (...args) => {
84
+ if (!isProgress || isVisibleStreamProgress(args[0])) streamed = true;
85
+ return callback(...args);
86
+ };
87
+ const tracked = { ...opts };
88
+ if (typeof opts?.onStreamDelta === 'function') tracked.onStreamDelta = track(opts.onStreamDelta, true);
89
+ if (typeof opts?.onTextDelta === 'function') tracked.onTextDelta = track(opts.onTextDelta);
90
+ if (typeof opts?.onToolCall === 'function') tracked.onToolCall = track(opts.onToolCall);
78
91
  try {
79
- return await send(opts);
92
+ return await send(tracked);
80
93
  } catch (error) {
81
94
  const status = error?.status ?? error?.httpStatus;
82
- if (opts?._effortConfigurationRetry || !isEffortConfigurationRejection(status, error?.message)) throw error;
95
+ const emitted =
96
+ streamed || error?.liveTextEmitted === true || error?.emittedToolCall === true || error?.unsafeToRetry === true;
97
+ if (
98
+ opts?._effortConfigurationRetry ||
99
+ opts?.effortConfigurationEnabled === false ||
100
+ opts?.signal?.aborted ||
101
+ emitted ||
102
+ !isEffortConfigurationRejection(status, error?.message)
103
+ )
104
+ throw error;
83
105
  markEffortConfigurationUnsupported(provider, model);
84
106
  process.stderr.write(
85
107
  `[${provider}] ${model} rejected the mid-conversation effort update; retrying once without it\n`
86
108
  );
87
- return send({ ...opts, effortConfigurationEnabled: false, _effortConfigurationRetry: true });
109
+ return send({ ...tracked, effortConfigurationEnabled: false, _effortConfigurationRetry: true });
88
110
  }
89
111
  }
90
112
  const OPENAI_PROVIDERS = new Set(['openai', 'openai-oauth']);
@@ -77,7 +77,9 @@ const GEMINI_CACHE_MIN_TOKENS = 4096;
77
77
  // Minimum prefix tokens for an explicit cache, or null when the docs exclude
78
78
  // the model from explicit caching.
79
79
  export function geminiExplicitCacheMinTokens(model) {
80
- const bare = String(model || '').replace(/^models\//i, '').toLowerCase();
80
+ const bare = String(model || '')
81
+ .replace(/^models\//i, '')
82
+ .toLowerCase();
81
83
  const major = /^gemini-(\d+)/.exec(bare);
82
84
  if (major && Number(major[1]) >= 4) return null;
83
85
  if (/^gemini-2\.5-(?:pro|flash)(?!-lite)(?:-|$)/.test(bare)) return 2048;
@@ -263,19 +265,23 @@ export function _resolveGeminiCacheUsage({ usageMetadata, cachedContent, provide
263
265
  // the prompt portion.
264
266
  const toolUseTokens = firstFinite(usageMetadata?.toolUsePromptTokenCount, usageMetadata?.tool_use_prompt_token_count);
265
267
  const inputTokens = hasExplicitPromptTokens ? promptTokens + toolUseTokens : Math.max(0, totalTokens - outputTokens);
266
- const reportedCachedTokens = firstFinite(
268
+ const reportedCachedCount = [
267
269
  // generateContent UsageMetadata field.
268
270
  usageMetadata?.cachedContentTokenCount,
269
271
  usageMetadata?.cached_content_token_count,
270
272
  // Newer SDK convenience alias documented for implicit cache hits.
271
273
  usageMetadata?.totalCachedTokens,
272
- usageMetadata?.total_cached_tokens
273
- );
274
+ usageMetadata?.total_cached_tokens,
275
+ ]
276
+ .map((value) => (value == null ? NaN : Number(value)))
277
+ .find((value) => Number.isFinite(value) && value >= 0);
278
+ const reportedCachedTokens = reportedCachedCount ?? 0;
274
279
  const cachedFallbackTokens = cachedContent ? Number(providerState?.gemini?.cacheTokenSize || 0) || 0 : 0;
275
- const rawCachedTokens = reportedCachedTokens > 0 ? reportedCachedTokens : cachedFallbackTokens;
280
+ // An explicit zero is a measured miss, not missing usage metadata.
281
+ const rawCachedTokens = reportedCachedCount ?? cachedFallbackTokens;
276
282
  const cachedTokens = inputTokens > 0 ? Math.min(rawCachedTokens, inputTokens) : rawCachedTokens;
277
283
  let cacheTokenSource = 'none';
278
- if (reportedCachedTokens > 0) cacheTokenSource = 'usage_metadata';
284
+ if (reportedCachedCount !== undefined) cacheTokenSource = 'usage_metadata';
279
285
  else if (cachedFallbackTokens > 0) cacheTokenSource = 'cache_create_fallback';
280
286
  return {
281
287
  inputTokens,
@@ -97,7 +97,10 @@ export function geminiErrorContract({ details, errorDetails, googleStatus, messa
97
97
  const scope = scopeOf(String(violation?.quotaId || ''));
98
98
  if (scope) scopes.add(scope);
99
99
  // A spent allowance is named by the typed violation, not by prose.
100
- if (String(violation?.quotaValue ?? '').trim() === '0' || LIMIT_ZERO_RE.test(String(violation?.description || ''))) {
100
+ if (
101
+ String(violation?.quotaValue ?? '').trim() === '0' ||
102
+ LIMIT_ZERO_RE.test(String(violation?.description || ''))
103
+ ) {
101
104
  zeroLimit = true;
102
105
  }
103
106
  }
@@ -121,7 +124,9 @@ export function geminiErrorContract({ details, errorDetails, googleStatus, messa
121
124
  CAPACITY_REASONS.has(reason) ||
122
125
  (!reason && scopes.size === 0 && retryAfterMs === undefined && CAPACITY_MESSAGE_RE.test(text));
123
126
  // A per-day violation outlasts any per-minute one reported with it.
124
- let quotaScope = scopes.has('day') ? 'day' : scopes.has('minute') ? 'minute' : undefined;
127
+ let quotaScope;
128
+ if (scopes.has('day')) quotaScope = 'day';
129
+ else if (scopes.has('minute')) quotaScope = 'minute';
125
130
  if (retryAfterMs === undefined) {
126
131
  const named = MESSAGE_DELAY_RE.exec(text);
127
132
  if (named) retryAfterMs = adviceMs(named[1]);
@@ -158,10 +163,13 @@ export function geminiInBandError(chunk, label) {
158
163
  if (!detail || (typeof detail !== 'object' && typeof detail !== 'string')) return null;
159
164
  const body = typeof detail === 'object' ? detail : { message: detail };
160
165
  const googleStatus = typeof body.status === 'string' ? body.status : '';
161
- const status = Number.isFinite(Number(body.code)) && Number(body.code) > 0
162
- ? Number(body.code)
163
- : GOOGLE_STATUS_HTTP[googleStatus.toUpperCase()];
164
- const err = new Error(`${label} in-band error${status ? ` ${status}` : ''}: ${String(body.message || googleStatus || 'unknown').slice(0, 300)}`);
166
+ const status =
167
+ Number.isFinite(Number(body.code)) && Number(body.code) > 0
168
+ ? Number(body.code)
169
+ : GOOGLE_STATUS_HTTP[googleStatus.toUpperCase()];
170
+ const err = new Error(
171
+ `${label} in-band error${status ? ` ${status}` : ''}: ${String(body.message || googleStatus || 'unknown').slice(0, 300)}`
172
+ );
165
173
  err.name = 'GeminiInBandError';
166
174
  if (status) {
167
175
  err.status = status;
@@ -44,10 +44,10 @@ export function buildGeminiRequest(messages, useModel, tools, opts) {
44
44
  // explicit opts.includeThoughts still wins.
45
45
  const thinkingConfig = geminiThinkingConfig(useModel, opts, { includeThoughts: true });
46
46
  const controls = geminiGenerationControls(opts);
47
- const generationConfig =
48
- thinkingConfig || Object.keys(controls).length
49
- ? { ...(thinkingConfig ? { thinkingConfig } : {}), ...controls }
50
- : undefined;
47
+ let generationConfig;
48
+ if (thinkingConfig || Object.keys(controls).length) {
49
+ generationConfig = { ...(thinkingConfig ? { thinkingConfig } : {}), ...controls };
50
+ }
51
51
  const systemInstruction =
52
52
  messages
53
53
  .filter((m) => m.role === 'system')
@@ -149,6 +149,7 @@ export function resolveGeminiUsage(response, opts, cachedContent, useModel) {
149
149
  }
150
150
 
151
151
  export function geminiSendResult(parsed, useModel, opts, resolvedUsage) {
152
+ if (parsed.providerReplay) parsed.providerReplay.requestContext = { model: useModel };
152
153
  return {
153
154
  content: parsed.content,
154
155
  model: useModel,
@@ -1,7 +1,11 @@
1
1
  // First-byte and idle watchdogs of one Gemini REST SSE body. Either timeout
2
2
  // cancels the reader and fails the pending read, so the caller surfaces a typed
3
- // timeout instead of waiting on a stalled socket.
4
- import { PROVIDER_SSE_IDLE_TIMEOUT_MS, PROVIDER_SSE_IDLE_WATCHDOG_ENABLED } from '../../stall-policy.mjs';
3
+ // timeout instead of waiting on a stalled socket. The idle timer re-arms only
4
+ // on decoded payloads (semantic progress), so it uses the semantic window.
5
+ // Each timeout names its phase (`timeoutPhase`): 'first-chunk' before any
6
+ // payload, 'idle' after one.
7
+ import { PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS, PROVIDER_SSE_IDLE_WATCHDOG_ENABLED } from '../../stall-policy.mjs';
8
+ import { TIMEOUT_PHASE } from '../../../../shared/provider-timeout-phase.mjs';
5
9
 
6
10
  export function createRestStreamWatchdogs({ reader, label, firstByteTimeoutMs, timeoutError }) {
7
11
  let idleTimedOut = false;
@@ -19,11 +23,18 @@ export function createRestStreamWatchdogs({ reader, label, firstByteTimeoutMs, t
19
23
  pendingReject = null;
20
24
  reject(err);
21
25
  };
22
- const idleError = () => timeoutError(`${label} SSE idle`, PROVIDER_SSE_IDLE_TIMEOUT_MS);
26
+ const idleError = () =>
27
+ Object.assign(timeoutError(`${label} SSE idle`, PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS), {
28
+ timeoutPhase: TIMEOUT_PHASE.IDLE,
29
+ });
23
30
 
24
31
  let firstByteTimer = setTimeout(() => {
25
32
  cancelReader('first byte timeout');
26
- failPending(timeoutError(`${label} first byte`, firstByteTimeoutMs));
33
+ failPending(
34
+ Object.assign(timeoutError(`${label} first byte`, firstByteTimeoutMs), {
35
+ timeoutPhase: TIMEOUT_PHASE.FIRST_CHUNK,
36
+ })
37
+ );
27
38
  }, firstByteTimeoutMs);
28
39
  firstByteTimer.unref?.();
29
40
  const clearFirstByte = () => {
@@ -46,7 +57,7 @@ export function createRestStreamWatchdogs({ reader, label, firstByteTimeoutMs, t
46
57
  idleTimedOut = true;
47
58
  cancelReader('SSE idle timeout');
48
59
  failPending(idleError());
49
- }, PROVIDER_SSE_IDLE_TIMEOUT_MS);
60
+ }, PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS);
50
61
  idleTimer.unref?.();
51
62
  },
52
63
  // One reader.read() with its reject handle registered for the watchdogs;
@@ -148,7 +148,12 @@ export async function runGeminiStreamAttempts({ run, signal, onRetry, sleepFn, a
148
148
  } catch (err) {
149
149
  const waitMs = connected ? geminiMidstreamDelayMs(err, streamAttempt, signal) : null;
150
150
  if (waitMs == null) throw err;
151
- onRetry?.({ attempt: streamAttempt + 1, maxAttempts: GEMINI_MIDSTREAM_MAX_ATTEMPTS, lastErr: err, delayMs: waitMs });
151
+ onRetry?.({
152
+ attempt: streamAttempt + 1,
153
+ maxAttempts: GEMINI_MIDSTREAM_MAX_ATTEMPTS,
154
+ lastErr: err,
155
+ delayMs: waitMs,
156
+ });
152
157
  await sleepWithAbort(waitMs, signal, sleepFn, 'Gemini stream retry wait aborted');
153
158
  continue;
154
159
  }
@@ -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.