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
@@ -4,7 +4,7 @@ import { createRemoteVersionSource } from './npm-cli-version.mjs';
4
4
  // documented version endpoint; the official installer script embeds the
5
5
  // current build (…/lab/<build>/…), parsed best-effort. Any format change or
6
6
  // failure falls back to the floor.
7
- export const CURSOR_CLIENT_VERSION_FLOOR = 'cli-2026.10.14-941492e';
7
+ export const CURSOR_CLIENT_VERSION_FLOOR = 'cli-2026.10.16-e3cb207';
8
8
  const BUILD_PATTERN = /downloads\.cursor\.com\/lab\/(\d{4}\.\d{2}\.\d{2}-[0-9a-f]{6,40})\//;
9
9
  export const CURSOR_INSTALL_URL = 'https://cursor.com/install';
10
10
 
@@ -0,0 +1,48 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { isDeepStrictEqual } from 'node:util';
3
+
4
+ const PREFIX = 'cursor_native_';
5
+ const pendingCalls = new Map();
6
+ const AUTHORIZATION_MS = 10 * 60 * 1000;
7
+
8
+ export function isCursorNativeCallId(id) {
9
+ return typeof id === 'string' && id.startsWith(PREFIX);
10
+ }
11
+
12
+ // Registered before streaming the call, including when a later frame is partial.
13
+ // Model arguments never grant this capability.
14
+ export function registerCursorNativeCall(ownerSessionId, pending, executions) {
15
+ if (!ownerSessionId || !pending.native) return;
16
+ if (pending.toolName !== 'read' && pending.toolName !== 'edit') return;
17
+ if (!['readResult', 'writeResult'].includes(pending.native.resultType)) return;
18
+ const now = Date.now();
19
+ for (const [id, entry] of pendingCalls) {
20
+ if (entry.expiresAt <= now) pendingCalls.delete(id);
21
+ }
22
+ if (pendingCalls.size >= 4096) throw new Error('Cursor native execution authorization capacity exceeded');
23
+ pending.toolCallId = `${PREFIX}${randomUUID()}`;
24
+ const entry = {
25
+ ownerSessionId,
26
+ pending,
27
+ executions,
28
+ expiresAt: now + AUTHORIZATION_MS,
29
+ arguments: JSON.parse(pending.decodedArgs),
30
+ };
31
+ pendingCalls.set(pending.toolCallId, entry);
32
+ }
33
+
34
+ export function cursorNativeCall(ownerSessionId, id, name, args) {
35
+ if (!isCursorNativeCallId(id)) return null;
36
+ const entry = pendingCalls.get(id);
37
+ if (!entry) throw new Error('Cursor native execution authorization is missing');
38
+ if (entry.expiresAt <= Date.now()) throw new Error('Cursor native execution authorization expired');
39
+ if (entry.ownerSessionId !== ownerSessionId) throw new Error('Cursor native execution authorization owner mismatch');
40
+ if (entry.pending.toolName !== name) throw new Error('Cursor native execution authorization tool mismatch');
41
+ if (!isDeepStrictEqual(entry.arguments, args))
42
+ throw new Error('Cursor native execution authorization argument mismatch');
43
+ return entry;
44
+ }
45
+
46
+ export function releaseCursorNativeCall(pending) {
47
+ pendingCalls.delete(pending.toolCallId);
48
+ }
@@ -1,11 +1,28 @@
1
1
  // Cursor exec/kv message handling: routing native exec requests to local
2
2
  // tools and sending results back on the bridge.
3
3
  import crypto from 'node:crypto';
4
+ import { BRIDGE_NAME_MAX_CHARS, isBridgeMetaTool } from '../runtime-core/tool-bridge-contract.mjs';
5
+ import { releaseCursorNativeCall } from './cursor-native-context.mjs';
4
6
  import { decodeJsonValue, encodeMessage } from './cursor-wire-protobuf.mjs';
5
7
  import { capCursorToolResult, storeCursorBlob } from './cursor-wire-guards.mjs';
6
8
  import { buildCursorExecThrow } from './cursor-wire-interactions.mjs';
7
9
  import { connectFrame, textDecoder, textEncoder } from './cursor-wire-transport.mjs';
8
10
  import { buildRequestContext } from './cursor-wire-request.mjs';
11
+ import { readSourceWindow } from '../../../shared/read-row-numbers.mjs';
12
+ import { splitGrepLineNumberOnlyPrefix, splitGrepCountPrefix } from '../tools/builtin/grep-formatting.mjs';
13
+
14
+ const nativeWriteDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
15
+
16
+ function nativeWriteText(args) {
17
+ if (!args.fileBytes?.length) return args.fileText || '';
18
+ try {
19
+ return nativeWriteDecoder.decode(args.fileBytes);
20
+ } catch {
21
+ throw Object.assign(new Error('Native Write fileBytes must be valid UTF-8; no file was written'), {
22
+ code: 'CURSOR_WRITE_ENCODING',
23
+ });
24
+ }
25
+ }
9
26
 
10
27
  export function heartbeatFrame() {
11
28
  return connectFrame(encodeMessage('AgentClientMessage', { clientHeartbeat: {} }));
@@ -70,12 +87,15 @@ const NATIVE_EXEC_CASES = [
70
87
  ],
71
88
  [
72
89
  'writeArgs',
73
- ['write'],
90
+ // Only the guarded edit tool: it creates missing files and fills empty
91
+ // ones, while its executor rejects overwrites of non-empty files. An
92
+ // explicit write tool would overwrite without any native capability
93
+ // (remote/proxied calls), so it never serves a native Write.
94
+ ['edit'],
74
95
  (tool, args) => ({
75
96
  [argumentName(tool, ['file_path', 'filePath', 'path'], 'file_path')]: args.path || '',
76
- [argumentName(tool, ['content', 'file_text', 'text'], 'content')]: args.fileBytes?.length
77
- ? textDecoder.decode(args.fileBytes)
78
- : args.fileText || '',
97
+ old_string: '',
98
+ new_string: nativeWriteText(args),
79
99
  }),
80
100
  'writeResult',
81
101
  ],
@@ -90,7 +110,9 @@ const NATIVE_EXEC_CASES = [
90
110
  pattern: args.pattern || '.',
91
111
  ...(args.path ? { path: args.path } : {}),
92
112
  ...(args.glob ? { glob: args.glob } : {}),
93
- mode: args.outputMode || 'content',
113
+ mode: args.outputMode === 'files_with_matches' ? 'files' : args.outputMode || 'content',
114
+ context: 0,
115
+ ...(args.headLimit > 0 ? { limit: args.headLimit } : {}),
94
116
  }),
95
117
  'grepResult',
96
118
  ],
@@ -130,6 +152,16 @@ const rejectedPath = (args) => ({ rejected: { path: args.path || '', reason: UNA
130
152
  const rejectedShell = (args) => ({
131
153
  rejected: { command: args.command || '', workingDirectory: args.workingDirectory || '', reason: UNAVAILABLE },
132
154
  });
155
+ const rejectedBackgroundShell = (args) => ({
156
+ rejected: {
157
+ command: args.command || '',
158
+ workingDirectory: args.workingDirectory || '',
159
+ reason:
160
+ 'Cursor background shell is not supported. Use the mixdog MCP shell tool with {"command":"..."}; ' +
161
+ 'if it returns task_id, use the mixdog task tool with {"action":"wait","task_id":"<returned id>"}. ' +
162
+ 'Use load_tool {"names":"task"} if task is not loaded.',
163
+ },
164
+ });
133
165
  const unavailableError = () => ({ error: { error: UNAVAILABLE } });
134
166
 
135
167
  // Native exec cases with no Mixdog tool behind them: [exec key, exec result
@@ -143,7 +175,7 @@ const UNAVAILABLE_EXEC_RESULTS = [
143
175
  ['fetchArgs', 'fetchResult', (args) => ({ error: { url: args.url || '', error: UNAVAILABLE } })],
144
176
  ['shellArgs', 'shellResult', rejectedShell],
145
177
  ['shellStreamArgs', 'shellResult', rejectedShell],
146
- ['backgroundShellSpawnArgs', 'backgroundShellSpawnResult', rejectedShell],
178
+ ['backgroundShellSpawnArgs', 'backgroundShellSpawnResult', rejectedBackgroundShell],
147
179
  ['writeShellStdinArgs', 'writeShellStdinResult', unavailableError],
148
180
  ['diagnosticsArgs', 'diagnosticsResult', () => ({})],
149
181
  ];
@@ -163,18 +195,44 @@ function rejectUnavailableExec(bridge, exec) {
163
195
  function handleMcpExec(bridge, exec, tools, onToolCall) {
164
196
  const args = exec.mcpArgs;
165
197
  const requestedName = args.toolName || args.name;
166
- const tool = toolByNames(tools, [requestedName]);
198
+ const directTool = toolByNames(tools, [requestedName]);
199
+ // Only the bridge granted in this request can resolve a deferred name.
200
+ // The ordinary runtime still projects the target and enforces its policy.
201
+ let tool =
202
+ directTool ||
203
+ (typeof requestedName === 'string' && requestedName.length > 0 ? toolByNames(tools, ['call_tool']) : null);
167
204
  if (!tool) {
168
205
  sendExecResult(bridge, exec, 'mcpResult', {
169
206
  error: { error: `Tool not available: ${requestedName || 'unknown'}` },
170
207
  });
171
208
  return;
172
209
  }
210
+ let decodedArgs = decodeMcpArgs(args.args);
211
+ if (
212
+ requestedName === 'call_tool' &&
213
+ directTool &&
214
+ Object.keys(decodedArgs).length === 2 &&
215
+ Object.hasOwn(decodedArgs, 'name') &&
216
+ Object.hasOwn(decodedArgs, 'arguments') &&
217
+ typeof decodedArgs.name === 'string' &&
218
+ decodedArgs.name.length > 0 &&
219
+ decodedArgs.name.length <= BRIDGE_NAME_MAX_CHARS &&
220
+ !isBridgeMetaTool(decodedArgs.name) &&
221
+ decodedArgs.arguments !== null &&
222
+ typeof decodedArgs.arguments === 'object' &&
223
+ !Array.isArray(decodedArgs.arguments)
224
+ ) {
225
+ const target = toolByNames(tools, [decodedArgs.name]);
226
+ if (target) {
227
+ tool = target;
228
+ decodedArgs = decodedArgs.arguments;
229
+ }
230
+ }
173
231
  onToolCall({
174
232
  exec,
175
233
  toolCallId: args.toolCallId || crypto.randomUUID(),
176
234
  toolName: tool.name,
177
- decodedArgs: JSON.stringify(decodeMcpArgs(args.args)),
235
+ decodedArgs: JSON.stringify(directTool ? decodedArgs : { name: requestedName, arguments: decodedArgs }),
178
236
  });
179
237
  }
180
238
 
@@ -191,7 +249,14 @@ export function handleExecMessage(bridge, exec, tools, cloudRule, onToolCall) {
191
249
  handleMcpExec(bridge, exec, tools, onToolCall);
192
250
  return;
193
251
  }
194
- const redirect = redirectNativeExec(exec, tools);
252
+ let redirect;
253
+ try {
254
+ redirect = redirectNativeExec(exec, tools);
255
+ } catch (error) {
256
+ if (error.code !== 'CURSOR_WRITE_ENCODING') throw error;
257
+ sendExecResult(bridge, exec, 'writeResult', { error: { path: exec.writeArgs.path || '', error: error.message } });
258
+ return;
259
+ }
195
260
  if (redirect) {
196
261
  onToolCall(redirect);
197
262
  return;
@@ -227,31 +292,41 @@ function parseListedPaths(text, rootPath) {
227
292
 
228
293
  function parseGrepResult(text, args) {
229
294
  const mode = args.outputMode || 'content';
295
+ const lines = text.split(/\r?\n/).filter((line) => line && !line.startsWith('[total ') && !line.startsWith('... ['));
230
296
  if (mode === 'files_with_matches') {
231
- const files = text
232
- .split(/\r?\n/)
233
- .map((line) => line.trim())
234
- .filter(Boolean);
297
+ const files = lines.map((line) => line.trim()).filter((line) => !line.startsWith('(no matches)'));
235
298
  return { files: { files, totalFiles: files.length } };
236
299
  }
237
300
  if (mode === 'count') {
238
301
  const counts = [];
239
302
  let totalMatches = 0;
240
- for (const line of text.split(/\r?\n/)) {
241
- const match = line.match(/^(.*):(\d+)$/);
242
- if (!match) continue;
243
- const count = Number(match[2]);
244
- counts.push({ file: match[1], count });
303
+ for (const line of lines) {
304
+ const parsed = splitGrepCountPrefix(line);
305
+ if (!parsed && !/^\d+$/.test(line)) continue;
306
+ const count = parsed ? parsed.count : Number(line);
307
+ counts.push({ file: parsed?.path || args.path, count });
245
308
  totalMatches += count;
246
309
  }
247
310
  return { count: { counts, totalFiles: counts.length, totalMatches } };
248
311
  }
249
312
  const byFile = new Map();
250
- for (const line of text.split(/\r?\n/)) {
251
- const match = line.match(/^(.+?):(\d+):(.*)$/);
252
- if (!match) continue;
253
- if (!byFile.has(match[1])) byFile.set(match[1], []);
254
- byFile.get(match[1]).push({ lineNumber: Number(match[2]), content: match[3] });
313
+ let currentFile = args.path;
314
+ for (const line of lines) {
315
+ const grouped = /^ {2}(\d+): (.*)$/.exec(line);
316
+ // Native searches request no context: only :N: is a line delimiter.
317
+ // A -N- segment may be part of the filename, not a context-line prefix.
318
+ const match = grouped ? null : /^(.+?):(\d+):/.exec(line);
319
+ const prefix = match ? { path: match[1], lineNo: Number(match[2]), markerEnd: match[0].length } : null;
320
+ const single = grouped || prefix ? null : splitGrepLineNumberOnlyPrefix(line);
321
+ if (!grouped && !prefix && !single) {
322
+ currentFile = line.replace(/ \(\d+ hits\)$/, '');
323
+ continue;
324
+ }
325
+ const file = prefix?.path || currentFile;
326
+ const lineNumber = grouped ? Number(grouped[1]) : (prefix || single).lineNo;
327
+ const content = grouped ? grouped[2] : line.slice((prefix || single).markerEnd);
328
+ if (!byFile.has(file)) byFile.set(file, []);
329
+ byFile.get(file).push({ lineNumber, content });
255
330
  }
256
331
  const matches = [...byFile].map(([file, fileMatches]) => ({ file, matches: fileMatches }));
257
332
  const matchedLines = matches.reduce((sum, entry) => sum + entry.matches.length, 0);
@@ -290,7 +365,7 @@ function sendShellStream(bridge, exec, text, code) {
290
365
  // rejected shell command.
291
366
  const NATIVE_FAILURE_PAYLOADS = {
292
367
  readResult: (args, text) => ({ rejected: { path: args.path || '', reason: text || 'Read failed' } }),
293
- writeResult: (args, text) => ({ rejected: { path: args.path || '', reason: text || 'Write failed' } }),
368
+ writeResult: (args, text) => ({ error: { path: args.path || '', error: text || 'Write failed' } }),
294
369
  fetchResult: (args, text) => ({ error: { url: args.url || '', error: text || 'Fetch failed' } }),
295
370
  lsResult: (args, text) => ({ rejected: { path: args.path || '', reason: text || 'List failed' } }),
296
371
  grepResult: (_args, text) => ({ error: { error: text || 'Grep failed' } }),
@@ -304,16 +379,30 @@ const NATIVE_FAILURE_PAYLOADS = {
304
379
  };
305
380
 
306
381
  const NATIVE_SUCCESS_PAYLOADS = {
307
- readResult: (args, text) => ({
308
- success: {
309
- path: args.path || '',
310
- content: text,
311
- totalLines: text ? text.split(/\r?\n/).length : 0,
312
- fileSize: textEncoder.encode(text).length,
313
- },
314
- }),
382
+ readResult: (args, text, pending, result) => {
383
+ const source = readSourceWindow(text);
384
+ // The read executor reports per-line clipping out of band: on the
385
+ // pending call (local) or on the result (remote/proxied).
386
+ if (!source || pending.nativeReadWindow?.lineClipped || result?.readWindow?.lineClipped)
387
+ return {
388
+ rejected: {
389
+ path: args.path || '',
390
+ reason:
391
+ 'This read result is not a complete contiguous source window. Use the mixdog MCP read tool with file_path, offset and limit; do not treat display markers as file content.',
392
+ },
393
+ };
394
+ return {
395
+ success: {
396
+ path: args.path || '',
397
+ content: source.content,
398
+ ...(source.totalLines === undefined ? {} : { totalLines: source.totalLines }),
399
+ truncated: source.truncated,
400
+ rangeApplied: Boolean(args.offset || args.limit || (source.startLine != null && source.startLine > 1)),
401
+ },
402
+ };
403
+ },
315
404
  writeResult: (args) => {
316
- const content = args.fileBytes?.length ? textDecoder.decode(args.fileBytes) : args.fileText || '';
405
+ const content = nativeWriteText(args);
317
406
  return {
318
407
  success: {
319
408
  path: args.path || '',
@@ -345,7 +434,9 @@ const NATIVE_SUCCESS_PAYLOADS = {
345
434
  };
346
435
 
347
436
  export function sendToolResult(bridge, pending, result, ok) {
437
+ releaseCursorNativeCall(pending);
348
438
  result = capCursorToolResult(result);
439
+ pending.completedResult = { result, ok };
349
440
  const { exec, native } = pending;
350
441
  const text = String(result?.content ?? '');
351
442
  const media = Array.isArray(result?.media) ? result.media : [];
@@ -354,6 +445,21 @@ export function sendToolResult(bridge, pending, result, ok) {
354
445
  return;
355
446
  }
356
447
  const { args, resultType } = native;
448
+ if (ok && resultType === 'readResult' && pending.nativeReadReply) {
449
+ let reply = pending.nativeReadReply;
450
+ if (pending.nativeUserMessage) {
451
+ reply = {
452
+ rejected: {
453
+ path: args.path || '',
454
+ reason: `Read interrupted by a new user instruction: ${pending.nativeUserMessage}`,
455
+ },
456
+ };
457
+ } else if (pending.nativeSnapshot) {
458
+ pending.nativeSnapshot.delivered = true;
459
+ }
460
+ sendExecResult(bridge, exec, resultType, reply);
461
+ return;
462
+ }
357
463
  if (resultType === 'shellStreamResult') {
358
464
  sendShellStream(bridge, exec, text, ok ? 0 : 1);
359
465
  return;
@@ -364,6 +470,10 @@ export function sendToolResult(bridge, pending, result, ok) {
364
470
  return;
365
471
  }
366
472
  if (Object.hasOwn(NATIVE_SUCCESS_PAYLOADS, resultType)) {
367
- sendExecResult(bridge, exec, resultType, NATIVE_SUCCESS_PAYLOADS[resultType](args, text));
473
+ const value = NATIVE_SUCCESS_PAYLOADS[resultType](args, text, pending, result);
474
+ if (resultType === 'writeResult' && Number.isInteger(pending.nativeWrittenBytes)) {
475
+ value.success.fileSize = pending.nativeWrittenBytes;
476
+ }
477
+ sendExecResult(bridge, exec, resultType, value);
368
478
  }
369
479
  }
@@ -87,7 +87,19 @@ const SCHEMAS = {
87
87
  ['clientHeartbeat', 7, 'ClientHeartbeat'],
88
88
  ]),
89
89
  TextDeltaUpdate: fields([['text', 1, 'string']]),
90
- ToolCall: fields([['mcpToolCall', 15, 'McpToolCall']]),
90
+ ToolCall: fields([
91
+ ['editToolCall', 12, 'NativeEditToolCall'],
92
+ ['mcpToolCall', 15, 'McpToolCall'],
93
+ ]),
94
+ NativeEditToolCall: fields([['result', 2, 'NativeEditResult']]),
95
+ NativeEditResult: fields([
96
+ ['success', 1, 'raw'],
97
+ ['fileNotFound', 2, 'raw'],
98
+ ['readPermissionDenied', 3, 'raw'],
99
+ ['writePermissionDenied', 4, 'raw'],
100
+ ['rejected', 6, 'raw'],
101
+ ['error', 7, 'raw'],
102
+ ]),
91
103
  McpToolCall: fields([
92
104
  ['args', 1, 'McpArgs'],
93
105
  ['result', 2, 'McpResult'],
@@ -422,6 +434,7 @@ const SCHEMAS = {
422
434
  ['totalLines', 3, 'int'],
423
435
  ['fileSize', 4, 'int'],
424
436
  ['truncated', 6, 'bool'],
437
+ ['rangeApplied', 8, 'bool'],
425
438
  ]),
426
439
  ReadRejected: fields([
427
440
  ['path', 1, 'string'],
@@ -430,7 +443,9 @@ const SCHEMAS = {
430
443
  ReadResult: fields([
431
444
  ['success', 1, 'ReadSuccess'],
432
445
  ['rejected', 3, 'ReadRejected'],
446
+ ['fileNotFound', 4, 'ReadFileNotFound'],
433
447
  ]),
448
+ ReadFileNotFound: fields([['path', 1, 'string']]),
434
449
  WriteSuccess: fields([
435
450
  ['path', 1, 'string'],
436
451
  ['linesCreated', 2, 'int'],
@@ -440,8 +455,13 @@ const SCHEMAS = {
440
455
  ['path', 1, 'string'],
441
456
  ['reason', 2, 'string'],
442
457
  ]),
458
+ WriteError: fields([
459
+ ['path', 1, 'string'],
460
+ ['error', 2, 'string'],
461
+ ]),
443
462
  WriteResult: fields([
444
463
  ['success', 1, 'WriteSuccess'],
464
+ ['error', 5, 'WriteError'],
445
465
  ['rejected', 6, 'WriteRejected'],
446
466
  ]),
447
467
  DeleteRejected: fields([
@@ -610,7 +630,7 @@ const SCHEMAS = {
610
630
  JsonValue: fields([
611
631
  ['nullValue', 1, 'int'],
612
632
  ['numberValue', 2, 'double'],
613
- ['stringValue', 3, 'string'],
633
+ ['stringValue', 3, 'string', { presence: true }],
614
634
  ['boolValue', 4, 'bool'],
615
635
  ['structValue', 5, 'JsonStruct'],
616
636
  ['listValue', 6, 'JsonList'],
@@ -620,7 +640,8 @@ const SCHEMAS = {
620
640
  };
621
641
 
622
642
  const textEncoder = new TextEncoder();
623
- const textDecoder = new TextDecoder();
643
+ // A protobuf string is data, not a text document with a disposable BOM.
644
+ const textDecoder = new TextDecoder('utf-8', { ignoreBOM: true });
624
645
 
625
646
  function concatBytes(parts) {
626
647
  const length = parts.reduce((sum, part) => sum + part.length, 0);
@@ -709,7 +730,10 @@ export function encodeMessage(type, value = {}) {
709
730
  let values = [fieldValue];
710
731
  if (descriptor.repeated) values = Array.isArray(fieldValue) ? fieldValue : [];
711
732
  for (const item of values) {
712
- if (shouldWrite(descriptor.type, item)) parts.push(encodeField(descriptor.no, descriptor.type, item));
733
+ // A oneof's explicit empty string is a value, not an absent field.
734
+ if ((descriptor.presence && item != null) || shouldWrite(descriptor.type, item)) {
735
+ parts.push(encodeField(descriptor.no, descriptor.type, item));
736
+ }
713
737
  }
714
738
  }
715
739
  return concatBytes(parts);
@@ -61,7 +61,13 @@ function toolResultEntry(message, text, toolNames) {
61
61
  const isError = message.mixdog_tool_error === true;
62
62
  const toolName = toolNames.get(toolCallId) || '';
63
63
  return {
64
- toolResult: { toolCallId, content: text, media, isError },
64
+ toolResult: {
65
+ toolCallId,
66
+ content: text,
67
+ media,
68
+ isError,
69
+ ...(message.mixdog_read_window?.lineClipped === true ? { readWindow: { lineClipped: true } } : {}),
70
+ },
65
71
  entry: {
66
72
  role: 'tool',
67
73
  id: toolCallId,
@@ -170,9 +176,7 @@ export function buildRequestContext(tools, cloudRule) {
170
176
  {
171
177
  serverName: 'mixdog',
172
178
  instructions:
173
- 'Use the tools provided by the mixdog MCP server for this task. ' +
174
- 'Follow their descriptions and input schemas. Prefer them over Cursor native tools; ' +
175
- 'native tools do not directly access the Mixdog environment. ' +
179
+ 'Do not use Cursor native tools; use only the tools provided by the mixdog MCP server, following their descriptions and declared input schemas. ' +
176
180
  'If a needed tool is not available, use the provided tool discovery mechanism rather than inventing a tool.',
177
181
  },
178
182
  ]
@@ -4,6 +4,7 @@
4
4
  * close verdict and the bounded in-place restart.
5
5
  */
6
6
  import {
7
+ MAX_CONNECT_FRAME_BYTES,
7
8
  isCursorAuthError,
8
9
  isCursorThrottleError,
9
10
  isRetryableCursorStreamError,
@@ -13,6 +14,10 @@ import { emitProviderRetryStage, markProviderRecoveryExhausted, retryAfterMsFrom
13
14
  import { createFrameParser, cursorError, parseEndStream } from './cursor-wire-transport.mjs';
14
15
  import { processServerMessage } from './cursor-wire-stream-messages.mjs';
15
16
 
17
+ // A parked HTTP/2 run can still receive parallel execs. Keep their raw chunks
18
+ // with the transport until the next SSE consumer attaches.
19
+ const parkedInputs = new WeakMap();
20
+
16
21
  // Resolves after `ms`, or early when the stream is cancelled.
17
22
  function abortableSleep(ms, signal) {
18
23
  return new Promise((resolve) => {
@@ -51,7 +56,9 @@ export function createBridgeController(ctx) {
51
56
  modelParameters: run.modelParameters,
52
57
  maxMode: run.maxMode,
53
58
  sessionId: run.sessionId,
59
+ ownerSessionId: run.ownerSessionId,
54
60
  pending: state.pending,
61
+ executions: state.executions,
55
62
  sawTurnEnded: state.sawTurnEnded,
56
63
  });
57
64
  sink.finish('tool_calls');
@@ -80,13 +87,11 @@ export function createBridgeController(ctx) {
80
87
  const serverDelay = retryAfterMsFromError(error);
81
88
  // Server advice is honored in full for every retryable kind; local
82
89
  // backoff applies only when the server gave none.
83
- const delayMs = Number.isFinite(serverDelay)
84
- ? serverDelay
85
- : backoffMs(throttled ? throttleCount + 1 : retryCount + 1);
90
+ const backoffAttempt = (throttled ? throttleCount : retryCount) + 1;
91
+ const delayMs = Number.isFinite(serverDelay) ? serverDelay : backoffMs(backoffAttempt);
86
92
  const throttleOk = throttled && throttleCount < tuning.maxThrottleRetries;
87
93
  const authOk = authFailure && authCount < tuning.maxAuthRetries;
88
- const canRetry =
89
- retryCount < tuning.maxRetries && recoveryEligible && (retryable || throttleOk || authOk);
94
+ const canRetry = retryCount < tuning.maxRetries && recoveryEligible && (retryable || throttleOk || authOk);
90
95
  if (!canRetry) {
91
96
  // A fresh Cursor run owns its bounded in-place retries. Mark
92
97
  // exhaustion so the outer loop does not multiply that budget.
@@ -96,8 +101,7 @@ export function createBridgeController(ctx) {
96
101
  // A throttle that spent its bounded retries is final for the turn too.
97
102
  if (
98
103
  recoveryEligible &&
99
- ((retryable && retryCount >= tuning.maxRetries) ||
100
- (throttled && throttleCount >= tuning.maxThrottleRetries))
104
+ ((retryable && retryCount >= tuning.maxRetries) || (throttled && throttleCount >= tuning.maxThrottleRetries))
101
105
  ) {
102
106
  markProviderRecoveryExhausted(error, { owner: 'cursor-wire', attempts: retryCount + 1 });
103
107
  }
@@ -118,6 +122,9 @@ export function createBridgeController(ctx) {
118
122
  lastErr: error,
119
123
  delayMs,
120
124
  });
125
+ let restartReason = 'transient';
126
+ if (throttled) restartReason = 'throttle';
127
+ else if (authFailure) restartReason = 'auth';
121
128
  void sleep(delayMs, cancelSignal).then(async () => {
122
129
  if (isCancelled() || state.closed) return;
123
130
  try {
@@ -126,7 +133,7 @@ export function createBridgeController(ctx) {
126
133
  attempt: retryCount,
127
134
  fromCheckpoint: !throttled && Boolean(run.conversation.checkpoint),
128
135
  visibleOutput: state.visibleOutput,
129
- reason: throttled ? 'throttle' : authFailure ? 'auth' : 'transient',
136
+ reason: restartReason,
130
137
  error,
131
138
  });
132
139
  if (isCancelled() || state.closed) {
@@ -200,6 +207,11 @@ export function createBridgeController(ctx) {
200
207
  const attach = (ownedBridge, nextHeartbeat) => {
201
208
  live.bridge = ownedBridge;
202
209
  live.heartbeat = nextHeartbeat;
210
+ let inbox = parkedInputs.get(ownedBridge);
211
+ if (!inbox) {
212
+ inbox = { chunks: [], bytes: 0 };
213
+ parkedInputs.set(ownedBridge, inbox);
214
+ }
203
215
  const messageCtx = {
204
216
  state,
205
217
  filter,
@@ -208,14 +220,26 @@ export function createBridgeController(ctx) {
208
220
  tools: run.tools,
209
221
  cloudRule: run.cloudRule,
210
222
  sessionId: run.sessionId,
223
+ ownerSessionId: run.ownerSessionId,
211
224
  };
212
225
  const frameParser = createFrameParser(
213
226
  // Server requests answer on whichever bridge is live when they arrive.
214
227
  (bytes) => watchdog.progress(processServerMessage(bytes, { ...messageCtx, bridge: live.bridge })),
215
228
  (bytes) => onEndStream(ownedBridge, bytes)
216
229
  );
217
- ownedBridge.onData((chunk) => {
218
- if (live.bridge !== ownedBridge || state.closed) return;
230
+ const receive = (chunk) => {
231
+ if (live.bridge !== ownedBridge || isCancelled()) return;
232
+ if (state.closed) {
233
+ if (inbox.bytes + chunk.byteLength > MAX_CONNECT_FRAME_BYTES) {
234
+ ownedBridge.close(
235
+ cursorError('Cursor parked input exceeds the buffer limit', { code: 'stream_buffer_limit' })
236
+ );
237
+ return;
238
+ }
239
+ inbox.chunks.push(chunk);
240
+ inbox.bytes += chunk.byteLength;
241
+ return;
242
+ }
219
243
  state.chunkSeq += 1;
220
244
  try {
221
245
  frameParser(chunk);
@@ -227,9 +251,15 @@ export function createBridgeController(ctx) {
227
251
  } catch (error) {
228
252
  ownedBridge.close(error);
229
253
  }
230
- });
254
+ };
255
+ ownedBridge.onData(receive);
231
256
  ownedBridge.onClose((error) => onBridgeClose(ownedBridge, nextHeartbeat, frameParser, error));
232
257
  watchdog.start();
258
+ while (!state.closed && !isCancelled() && inbox.chunks.length) {
259
+ const chunk = inbox.chunks.shift();
260
+ inbox.bytes -= chunk.byteLength;
261
+ receive(chunk);
262
+ }
233
263
  };
234
264
 
235
265
  return { attach };