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
@@ -0,0 +1,76 @@
1
+ import { canFallbackRoute } from '../../../../shared/model-route-fallback.mjs';
2
+ import { getProvider, initProviders } from '../../providers/registry.mjs';
3
+ import { loadConfig } from '../../config.mjs';
4
+ import { ensureProviderEnabled } from '../../runtime-core/config-helpers.mjs';
5
+ import { updateSessionRoute } from '../manager/session-lifecycle.mjs';
6
+ import { pinSessionWireRoute } from '../../providers/wire-route.mjs';
7
+ import { buildRequestSendOptions } from '../manager/ask-turn-loop-options.mjs';
8
+ import { prepareTurnEffortConfiguration } from '../../providers/effort-configuration.mjs';
9
+ import { resolveSessionContextMeta } from '../manager/context-meta.mjs';
10
+
11
+ export async function advanceAgentRoute(state, error) {
12
+ const session = state.sessionRef;
13
+ const index = session?.routeFallbackIndex || 0;
14
+ const next = session?.routeFallbacks?.[index];
15
+ const committed = state.toolCallsTotal > 0 || state.response != null;
16
+ if (!session?.agent || !next || !canFallbackRoute(error, { signal: state.signal, committed })) return false;
17
+ state.throwIfAborted();
18
+ const config = ensureProviderEnabled(loadConfig(), next.provider);
19
+ await initProviders(config.providers, { signal: state.signal });
20
+ state.throwIfAborted();
21
+ const provider = getProvider(next.provider);
22
+ if (!provider) throw new Error(`Provider "${next.provider}" not available`);
23
+ const oldOptions = buildRequestSendOptions({
24
+ sessionId: state.sessionId,
25
+ session,
26
+ signal: state.signal,
27
+ });
28
+ const updated = updateSessionRoute(
29
+ session.id,
30
+ {
31
+ ...next,
32
+ effort: next.effort || null,
33
+ fast: next.fast === true,
34
+ autoEffort: next.autoEffort !== false,
35
+ modelParameters: next.modelParameters || {},
36
+ contextPercent: next.contextPercent,
37
+ contextTokens: next.contextTokens,
38
+ selectedContextWindow: resolveSessionContextMeta(provider, next.model, next).rawContextWindow,
39
+ },
40
+ { crossProvider: true }
41
+ );
42
+ if (!updated) throw new Error('agent session closed during model fallback');
43
+ updated.routeFallbackIndex = index + 1;
44
+ await pinSessionWireRoute(updated, provider);
45
+ state.throwIfAborted();
46
+ state.messages.splice(0, state.messages.length, ...updated.messages);
47
+ updated.liveTurnMessages = state.messages;
48
+ state.sessionRef = updated;
49
+ state.provider = provider;
50
+ state.model = updated.model;
51
+ state.tools = updated.tools;
52
+ state.providerState = undefined;
53
+ state.providerStateUpdated = true;
54
+ state.prefixGuardState = null;
55
+ state.fixedProviderToolSurface = null;
56
+ state.cacheBreakTraceKeys.clear();
57
+ state.transportRetriesUsed = 0;
58
+ state.transportRetryMax = 0;
59
+ for (const key of Object.keys(oldOptions)) delete state.opts[key];
60
+ Object.assign(
61
+ state.opts,
62
+ buildRequestSendOptions({
63
+ sessionId: state.sessionId,
64
+ session: updated,
65
+ turnEffort: updated.effort,
66
+ effortConfiguration: prepareTurnEffortConfiguration(updated, provider),
67
+ signal: state.signal,
68
+ })
69
+ );
70
+ state.opts.onStageChange?.('connecting', {
71
+ provider: updated.provider,
72
+ model: updated.model,
73
+ reason: 'model-fallback',
74
+ });
75
+ return true;
76
+ }
@@ -18,6 +18,7 @@ import { runWithProviderRequestToolsScope } from '../../runtime-core/provider-re
18
18
  import { REPEAT_FAIL_LIMIT } from './loop-state.mjs';
19
19
  import { createToolCallIdResolver } from './tool-call-ids.mjs';
20
20
  import { captureSideQuestionRequest } from '../side-question-store.mjs';
21
+ import { advanceAgentRoute } from './route-fallback.mjs';
21
22
  import {
22
23
  beginProviderToolExclusions,
23
24
  dropSessionTool,
@@ -205,7 +206,8 @@ export async function sendProviderRequest(state, round) {
205
206
  );
206
207
  } catch (error) {
207
208
  sideQuestion?.discard();
208
- throw error;
209
+ if (!(await advanceAgentRoute(state, error))) throw error;
210
+ result = { action: 'retry_route' };
209
211
  }
210
212
  if (result.action === 'proceed') sideQuestion?.settle(result.response);
211
213
  else sideQuestion?.discard();
@@ -233,6 +235,8 @@ function appendRecoveryNotice(state, notice) {
233
235
  * instead of processing a response. */
234
236
  export function applyRetryAction(state, result) {
235
237
  switch (result.action) {
238
+ case 'retry_route':
239
+ return true;
236
240
  case 'retry':
237
241
  // Keep opts.cacheBreakIntent: the failed send never consumed the tag,
238
242
  // and the reactive-compact retry that follows IS the tagged transition.
@@ -21,15 +21,14 @@ import { judgeTurn, recordEffortDecision } from '../../../../effort-judge/judge-
21
21
  import { stepResultWindow } from '../../../../effort-judge/judge-input.mjs';
22
22
 
23
23
  const TEXT_BLOCKS = new Set(['text', 'input_text', 'output_text']);
24
- const textOf = (content) =>
25
- typeof content === 'string'
26
- ? content
27
- : Array.isArray(content)
28
- ? content
29
- .filter((block) => block && TEXT_BLOCKS.has(block.type))
30
- .map((block) => block.text)
31
- .join('\n')
32
- : '';
24
+ function textOf(content) {
25
+ if (typeof content === 'string') return content;
26
+ if (!Array.isArray(content)) return '';
27
+ return content
28
+ .filter((block) => block && TEXT_BLOCKS.has(block.type))
29
+ .map((block) => block.text)
30
+ .join('\n');
31
+ }
33
32
  // Same argument text the training data was built from (head 600 code points).
34
33
  const argText = (args) =>
35
34
  Array.from(typeof args === 'string' ? args : JSON.stringify(args ?? {}))
@@ -14,6 +14,12 @@ export function _stripMcpPrefix(name) {
14
14
  export function _isReadTool(name) {
15
15
  return _stripMcpPrefix(name) === 'read';
16
16
  }
17
+
18
+ // Cursor's native file protocol needs source content, not a receipt saying
19
+ // the model has already seen it. Keep actual read caching and permissions.
20
+ export function requiresReadBody(name, sessionRef) {
21
+ return name === 'read' && (sessionRef?.provider === 'cursor-oauth' || sessionRef?.provider === 'cursor-api');
22
+ }
17
23
  export function _isMutationTool(name, args = null) {
18
24
  const n = String(_stripMcpPrefix(name) || '').toLowerCase();
19
25
  return n === 'apply_patch' || n === 'edit' || _isGitMutationTool(name, args);
@@ -15,6 +15,8 @@ import { executeInternalTool, isInternalTool } from '../../../internal-tools.mjs
15
15
  import { buildSkillsListResponse, viewSkill } from '../tool-helpers.mjs';
16
16
  import { isOnDeferredToolSurface } from '../deferred-call-through.mjs';
17
17
  import { _executeCodeGraphToolLazy } from '../../manager/runtime-loaders.mjs';
18
+ import { requiresReadBody } from '../tool-classify.mjs';
19
+ import { executeCursorNativeBuiltin } from '../../../tools/builtin/external-tool-adapters.mjs';
18
20
 
19
21
  function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts }) {
20
22
  const mcpScopeId = sessionRef?.mcpScopeId || null;
@@ -100,11 +102,22 @@ export function dispatchToolCall({ name, args }, ctx) {
100
102
  if (name === 'shell' || isBuiltinTool(name) || isExternalAdapterTool(name)) {
101
103
  const builtinOpts = {
102
104
  ...completionToolOpts,
103
- ...(executeOpts.suppressReadUnchangedStub ? { suppressReadUnchangedStub: true } : {}),
105
+ ...(executeOpts.suppressReadUnchangedStub || requiresReadBody(name, sessionRef)
106
+ ? { suppressReadUnchangedStub: true }
107
+ : {}),
104
108
  // Runtime-granted only; any value inherited from executeOpts is overridden.
105
109
  elevationApproved: ctx.elevationApproved === true,
106
110
  };
107
- return executeBuiltinTool(name, args, cwd, builtinOpts);
111
+ return executeCursorNativeBuiltin(
112
+ name,
113
+ args,
114
+ cwd,
115
+ {
116
+ ...builtinOpts,
117
+ toolCallId: executeOpts.toolCallId || null,
118
+ },
119
+ executeBuiltinTool
120
+ );
108
121
  }
109
122
  return formatUnknownBuiltinToolMessage(name, args, 'tool');
110
123
  }
@@ -3,10 +3,7 @@
3
3
  // applyDeferredToolSurface; this module adds what a changed request prefix
4
4
  // invalidates: provider state, the prefix guard, the context baseline and the
5
5
  // cache-break tag. Historical tool calls are never rewritten.
6
- import {
7
- applyDeferredToolSurface,
8
- rebuildDeferredToolSurfaceForProvider,
9
- } from '../../runtime-core/tool-catalog.mjs';
6
+ import { applyDeferredToolSurface, rebuildDeferredToolSurfaceForProvider } from '../../runtime-core/tool-catalog.mjs';
10
7
  import {
11
8
  bridgeSurfaceOutdated,
12
9
  sessionToolExposure,
@@ -16,7 +16,7 @@ function isSleepLikeToolCall(call) {
16
16
  }
17
17
 
18
18
  export async function runToolPhase(state, round, sent, onToolCall) {
19
- const { opts, messages, tools, sessionId, sessionRef, signal, response, suppressMidTurnText } = state;
19
+ const { opts, messages, tools, sessionId, sessionRef, signal, response } = state;
20
20
  state.noToolTurn.noteToolCallTurn();
21
21
  const calls = response.toolCalls;
22
22
  round.resolveToolCallId.all(calls);
@@ -25,8 +25,7 @@ export async function runToolPhase(state, round, sent, onToolCall) {
25
25
  // UI. Providers that stream via onTextDelta already rendered it; providers
26
26
  // that return text only in response.content would otherwise show nothing
27
27
  // before the tool card. The engine de-dups against already-streamed text.
28
- // Sub-agent sessions suppress it entirely — Lead only consumes the answer.
29
- if (!suppressMidTurnText && typeof response.content === 'string' && response.content.trim()) {
28
+ if (typeof response.content === 'string' && response.content.trim()) {
30
29
  try {
31
30
  opts.onAssistantText?.(response.content);
32
31
  } catch {
@@ -39,7 +38,7 @@ export async function runToolPhase(state, round, sent, onToolCall) {
39
38
  // The wire calls stay the transcript identity (assistant turn below).
40
39
  const toolBatchId = recordToolBatch(sessionId, resolveExecutionToolCalls(calls, sessionRef), state.iterations);
41
40
  await Promise.resolve(onToolCall?.(state.iterations, calls));
42
- const assistantTurnMsg = buildToolCallAssistantMessage(response, { calls, suppressMidTurnText, opts });
41
+ const assistantTurnMsg = buildToolCallAssistantMessage(response, { calls, opts });
43
42
  commitAssistantMessage(messages, assistantTurnMsg, opts);
44
43
  try {
45
44
  opts.onToolPhaseStarted?.();
@@ -6,6 +6,7 @@
6
6
  // abort-aware call wrapper is ask-call-interrupt. This file owns the lock,
7
7
  // the loop and the runtime bookkeeping around each turn.
8
8
  import { createHash } from 'node:crypto';
9
+ import { admitWorkspaceActivity } from '../../../../shared/worktrees/activity-gate.mjs';
9
10
  import {
10
11
  persistedAssistantTranscriptMetadata,
11
12
  persistedUserTranscriptMetadata,
@@ -38,6 +39,16 @@ const traceAskStart = (sessionId, explicitPrefetch) => {
38
39
  );
39
40
  };
40
41
 
42
+ /** A background follow-up ask has no caller to reject to; its failure would
43
+ * otherwise strand the pending input silently. */
44
+ const logFollowUpFailure = (sessionId) => (error) => {
45
+ try {
46
+ process.stderr.write(`[agent-ask] follow-up ask failed session=${sessionId}: ${error?.message || error}\n`);
47
+ } catch {
48
+ /* best-effort */
49
+ }
50
+ };
51
+
41
52
  /** The transcript timestamps the caller supplied for this ask: the persisted
42
53
  * user metadata plus a one-shot reader for the assistant metadata. */
43
54
  export function createAskTranscriptMeta(rawTranscriptMeta) {
@@ -66,7 +77,13 @@ export function createAskTranscriptMeta(rawTranscriptMeta) {
66
77
  * the turn state and rethrows. Returns the terminal result preview and the
67
78
  * follow-ups drained right after the provider accepted the turn. */
68
79
  async function runAskTurn({ sessionId, opened, input, askOpts, onToolCall, cwdOverride, transcript, askStartedAt }) {
80
+ let releaseWorkspace;
69
81
  try {
82
+ releaseWorkspace = await admitWorkspaceActivity(
83
+ sessionId,
84
+ cwdOverride || opened.turn.session.cwd || process.cwd(),
85
+ opened.runtime.controller?.signal
86
+ );
70
87
  const prepared = await prepareAskTurn({ sessionId, opened, input, cwdOverride, transcriptMeta: transcript.user });
71
88
  const result = await runAskAgentLoop({
72
89
  sessionId,
@@ -105,8 +122,12 @@ async function runAskTurn({ sessionId, opened, input, askOpts, onToolCall, cwdOv
105
122
  generation: opened.askGeneration,
106
123
  turnCheckpointToken: opened.turnToken,
107
124
  runtime: opened.runtime,
125
+ transcriptMeta: transcript.raw,
126
+ askStartedAt,
108
127
  });
109
128
  throw err;
129
+ } finally {
130
+ releaseWorkspace?.();
110
131
  }
111
132
  }
112
133
 
@@ -122,9 +143,12 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
122
143
  process.stderr.write(`[agent-trace] lock-acquired waitedMs=${Date.now() - askStartedAt}\n`);
123
144
  }
124
145
  // A non-empty cross-process sweep starts an empty follow-up ask once the
125
- // current session lock is released; it never delays completion.
146
+ // current session lock is released; it never delays completion. The
147
+ // failed-turn retry identity is one-shot: a follow-up runs queued input,
148
+ // never the retried turn. Nobody awaits it, so a failure is logged.
149
+ const followUpOpts = { ...askOpts, retryFailedTurn: undefined, retryTurnId: undefined, retryAttemptId: undefined };
126
150
  const kickFollowUpAsk = () => {
127
- askSession(sessionId, '', null, onToolCall, cwdOverride, null, askOpts).catch(() => {});
151
+ askSession(sessionId, '', null, onToolCall, cwdOverride, null, followUpOpts).catch(logFollowUpFailure(sessionId));
128
152
  };
129
153
  // The mutex is held for the WHOLE askSession call, including any follow-up
130
154
  // turns drained from the pending-message queue below — the single outer
@@ -141,6 +165,7 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
141
165
  // A failed-turn retry rewinds only the turn it retries, never a drained
142
166
  // follow-up turn.
143
167
  let retryFailedTurn = askOpts.retryFailedTurn === true;
168
+ let retryTurnId = askOpts.retryTurnId;
144
169
  try {
145
170
  // Turn loop (pendingMessages pattern): run the current prompt, then drain
146
171
  // any `agent type=send` messages that were queued while this turn was in
@@ -163,6 +188,11 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
163
188
  input.retryFailedTurn = true;
164
189
  retryFailedTurn = false;
165
190
  }
191
+ if (retryTurnId) {
192
+ input.retryTurnId = retryTurnId;
193
+ input.retryAttemptId = askOpts.retryAttemptId;
194
+ retryTurnId = null;
195
+ }
166
196
  // Synchronous pre-await setup (must happen before any await so
167
197
  // closeSession() can't interleave between load and registration).
168
198
  const claimed = claimTurnRuntime({
@@ -217,7 +247,7 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
217
247
  if (count <= 0) return;
218
248
  kickFollowUpAsk();
219
249
  })
220
- .catch(() => {});
250
+ .catch(logFollowUpFailure(sessionId));
221
251
  });
222
252
  return result;
223
253
  }
@@ -13,10 +13,6 @@ export async function settleAskCleanup(promise, { timeoutMs } = {}) {
13
13
  }
14
14
 
15
15
  // Live Agent projection is a per-ask send opt, never a session field.
16
- // Callers that pass onTextDelta/onAssistantText still need `liveProjection`
17
- // to un-suppress provider streaming: askSession always wraps those
18
- // callbacks for interruption tracking, so agent-loop cannot infer intent
19
- // from `typeof opts.onTextDelta === 'function'`.
20
16
  export function resolveAskLiveProjection(askOpts = {}) {
21
17
  return askOpts?.liveProjection === true;
22
18
  }
@@ -16,7 +16,12 @@ import {
16
16
  } from '../../providers/auto-effort.mjs';
17
17
  import { builtinFeatureActive } from '../../runtime-core/builtin-features.mjs';
18
18
  import { effortOptionsFor, warnEmptyAutoEffortLadder } from '../../runtime-core/effort.mjs';
19
- import { effortJudgeSupportsSteps, judgeTurn, recordEffortDecision } from '../../../../effort-judge/judge-client.mjs';
19
+ import {
20
+ effortJudgeSupportsSteps,
21
+ judgeTurn,
22
+ prewarmEffortJudge,
23
+ recordEffortDecision,
24
+ } from '../../../../effort-judge/judge-client.mjs';
20
25
  import { promptContentText } from './prompt-utils.mjs';
21
26
 
22
27
  // Every cache-safe route judges its tool-result steps the same way. Measured
@@ -53,6 +58,21 @@ export function autoEffortMode() {
53
58
  }
54
59
  }
55
60
 
61
+ /**
62
+ * Starts the judge worker when a session is created or opened on a route that
63
+ * Auto effort can judge, so the first judged turn does not wait for the cold
64
+ * load. Fire-and-forget: it never throws and never waits on the load.
65
+ */
66
+ export function prewarmSessionAutoEffort(session, provider) {
67
+ try {
68
+ if (autoEffortMode() === 'off' || session?.autoEffort === false) return false;
69
+ if (!turnEffortConfigurationMode(session, provider)) return false;
70
+ return prewarmEffortJudge();
71
+ } catch {
72
+ return false;
73
+ }
74
+ }
75
+
56
76
  function lastText(messages, role) {
57
77
  for (let i = (messages?.length || 0) - 1; i >= 0; i--) {
58
78
  const message = messages[i];
@@ -15,7 +15,7 @@ import { filterModelVisibleSessionMessages } from './message-sanitize.mjs';
15
15
  import { _getAgentLoop } from './runtime-loaders.mjs';
16
16
  import { runAbortable, throwIfAborted } from '../../../../shared/abort-race.mjs';
17
17
  import { applyTurnContextMeta, buildUserTurn, startProviderPrewarm, traceTurnContext } from './ask-turn-prepare.mjs';
18
- import { rewindUnansweredPrompt } from './failed-turn-rewind.mjs';
18
+ import { retainedFailedTurnInput, rewindUnansweredPrompt } from './failed-turn-rewind.mjs';
19
19
  import { buildAgentLoopOptions, trackedToolCallHook } from './ask-turn-loop-options.mjs';
20
20
  import { _api_call_with_interrupt } from './ask-call-interrupt.mjs';
21
21
  import { backfillFallbackSessionTitle } from './session-fallback-title.mjs';
@@ -25,6 +25,9 @@ import { backfillFallbackSessionTitle } from './session-fallback-title.mjs';
25
25
  export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, transcriptMeta }) {
26
26
  const { turn, runtime, turnSignal, askGeneration, checkpoint, turnToken, startedAt, codexTurnId } = opened;
27
27
  const session = turn.session;
28
+ const retained = input.retryTurnId
29
+ ? retainedFailedTurnInput(session.messages, input.retryTurnId, input.retryAttemptId)
30
+ : null;
28
31
  const provider = getProvider(session.provider);
29
32
  // Register the live session object for synchronous close snapshots.
30
33
  runtime.session = session;
@@ -44,7 +47,7 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
44
47
  // A failed-turn retry resubmits the prompt the failure left unanswered;
45
48
  // rewind that copy so the model sees the prompt once (an answered tail is
46
49
  // kept and the retry continues from it).
47
- if (input.retryFailedTurn === true) rewindUnansweredPrompt(session, input.prompt);
50
+ if (input.retryFailedTurn === true && !input.retryTurnId) rewindUnansweredPrompt(session, input.prompt);
48
51
  if (session.sessionStartMetaInjected !== true && !hasUserConversationMessage(session.messages)) {
49
52
  refreshSessionBp3Environment(session, effectiveCwd);
50
53
  }
@@ -61,16 +64,37 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
61
64
  });
62
65
  const [autoEffort, userTurn] = await Promise.all([
63
66
  autoEffortPending,
64
- buildUserTurn({
65
- session,
66
- prompt: input.prompt,
67
- context: input.context,
68
- explicitPrefetch: input.explicitPrefetch,
69
- turnSignal,
70
- transcriptMeta,
71
- turnPromptSource: input.promptSource,
72
- effortConfiguration: null,
73
- }),
67
+ retained
68
+ ? (() => {
69
+ const historyMessages = filterModelVisibleSessionMessages(session.messages.slice(0, retained.index));
70
+ const { completion, ...previousTranscript } = retained.message.meta.transcript;
71
+ const userTurnMessage = {
72
+ ...retained.message,
73
+ meta: {
74
+ ...retained.message.meta,
75
+ transcript: {
76
+ ...previousTranscript,
77
+ ...transcriptMeta,
78
+ messageId: previousTranscript.messageId,
79
+ previousCompletions: [
80
+ ...(previousTranscript.previousCompletions || []),
81
+ { ...completion, at: completion.at ?? previousTranscript.at },
82
+ ],
83
+ },
84
+ },
85
+ };
86
+ return { historyMessages, userTurnMessage, outgoing: [...historyMessages, userTurnMessage] };
87
+ })()
88
+ : buildUserTurn({
89
+ session,
90
+ prompt: input.prompt,
91
+ context: input.context,
92
+ explicitPrefetch: input.explicitPrefetch,
93
+ turnSignal,
94
+ transcriptMeta,
95
+ turnPromptSource: input.promptSource,
96
+ effortConfiguration: null,
97
+ }),
74
98
  wireRoutePending,
75
99
  ]);
76
100
  const turnEffort = autoEffort?.applied ? autoEffort.effort : session.effort || null;
@@ -163,6 +187,7 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
163
187
  deferredToolDelta: userTurn.deferredToolDelta,
164
188
  goalReminder: userTurn.goalReminder,
165
189
  workspaceNotice: userTurn.workspaceNotice,
190
+ setupNotice: userTurn.setupNotice,
166
191
  };
167
192
  }
168
193
 
@@ -186,7 +211,7 @@ export async function runAskAgentLoop({
186
211
  session.toolApprovalHook = askOpts.onToolApproval;
187
212
  }
188
213
  try {
189
- if (!input.promptSource) {
214
+ if (!input.promptSource && !input.retryTurnId) {
190
215
  const applied = await prepareExplicitSkills(input.prompt, outgoing, session, {
191
216
  cwd: effectiveCwd,
192
217
  signal: turnSignal,
@@ -17,6 +17,31 @@ import {
17
17
  import { _getRuntimeEntry, markSessionCancelled, markSessionError } from './runtime-liveness.mjs';
18
18
  import { SessionClosedError } from './session-errors.mjs';
19
19
  import { clearTurnCheckpoint } from './turn-checkpoint.mjs';
20
+ import { attachFailedTurnCompletion } from './ask-turn-settle.mjs';
21
+ import { turnFailureRecord } from '../turn-failure.mjs';
22
+ import { transcriptRouteMetadataFields } from '../../../../shared/transcript-metadata.mjs';
23
+
24
+ /** The durable end of a failed turn: the live turndone's status, reason and
25
+ * quota stop, so a reopened session renders the same failure. */
26
+ function failedTurnCompletion({ session, err, transcriptMeta, askStartedAt }) {
27
+ const raw = transcriptMeta && typeof transcriptMeta === 'object' ? transcriptMeta : {};
28
+ const route = { provider: session?.provider || raw.provider, model: session?.model || raw.modelId };
29
+ const { errorKind, quota, detail, errorDetails } = turnFailureRecord(err, route);
30
+ const startedAt = Number(raw.at || askStartedAt || Date.now());
31
+ return {
32
+ status: 'failed',
33
+ attemptId: raw.attemptId || globalThis.crypto.randomUUID(),
34
+ at: startedAt,
35
+ verb: typeof raw.completionVerb === 'string' && raw.completionVerb ? raw.completionVerb : 'Thought',
36
+ elapsedMs: Math.max(0, Date.now() - startedAt),
37
+ ...(typeof raw.checkpointId === 'string' && raw.checkpointId ? { checkpointId: raw.checkpointId } : {}),
38
+ ...transcriptRouteMetadataFields(raw),
39
+ ...(detail ? { detail } : {}),
40
+ ...(errorDetails ? { errorDetails } : {}),
41
+ errorKind,
42
+ ...(quota ? { quota } : {}),
43
+ };
44
+ }
20
45
 
21
46
  /** Durable failure identity: every surfaced (non-cancel) turn error logs ONE
22
47
  * structured line to stderr — the shard host mirrors it into daemon.log — so
@@ -118,6 +143,8 @@ async function finalizeCancelledTurn({
118
143
  * @param {number} input.generation the ask generation every save is scoped to
119
144
  * @param {string} input.turnCheckpointToken
120
145
  * @param {object} input.runtime the session's runtime entry at turn start
146
+ * @param {object} [input.transcriptMeta] the caller's raw transcript metadata
147
+ * @param {number} [input.askStartedAt]
121
148
  */
122
149
  export async function finalizeAskTurnFailure({
123
150
  sessionId,
@@ -129,9 +156,13 @@ export async function finalizeAskTurnFailure({
129
156
  generation,
130
157
  turnCheckpointToken,
131
158
  runtime,
159
+ transcriptMeta = null,
160
+ askStartedAt = 0,
132
161
  }) {
133
162
  checkpoint.stop();
134
163
  const session = turn.session;
164
+ const recordFailure = () =>
165
+ attachFailedTurnCompletion(session.messages, failedTurnCompletion({ session, err, transcriptMeta, askStartedAt }));
135
166
  // Cancellation/error paths bypass the commit point; drop the live-turn
136
167
  // alias so contextStatus() stops estimating from the stale in-flight array
137
168
  // once the turn unwinds.
@@ -187,6 +218,7 @@ export async function finalizeAskTurnFailure({
187
218
  let errorStateDurable = false;
188
219
  if (preserveProviderPartial && session && interruption.hasResponseStarted()) {
189
220
  const finalized = prepareCloseSnapshot('provider-error');
221
+ if (finalized.responsePreserved) recordFailure();
190
222
  errorStateDurable = await persistFinalizedSession({
191
223
  session,
192
224
  sessionId,
@@ -208,6 +240,7 @@ export async function finalizeAskTurnFailure({
208
240
  );
209
241
  const promptPersisted = compactPersist.settled && compactPersist.value === true;
210
242
  if (promptPersisted) {
243
+ recordFailure();
211
244
  errorStateDurable = await persistFinalizedSession({
212
245
  session,
213
246
  sessionId,
@@ -17,6 +17,7 @@ import {
17
17
  suffixUserTurnReminders,
18
18
  buildCurrentTimeBlock,
19
19
  snapshotPendingWorkspaceNotice,
20
+ snapshotPendingSetupNotice,
20
21
  } from './prompt-utils.mjs';
21
22
  import { codexWireSendOpts } from './session-id.mjs';
22
23
  import { _tryBridgeExplicitPrefetch } from './prefetch-bridge.mjs';
@@ -177,8 +178,11 @@ export async function buildUserTurn({
177
178
  // A mid-conversation working-folder change: the system prompt keeps its
178
179
  // old root (cache intact) and the new folder's facts ride this turn.
179
180
  const workspaceNotice = snapshotPendingWorkspaceNotice(session);
181
+ // What preparing a new worktree linked, installed, ran, failed or skipped.
182
+ const setupNotice = snapshotPendingSetupNotice(session);
180
183
  const reminderBlock = [
181
184
  workspaceNotice?.content || '',
185
+ setupNotice?.content || '',
182
186
  currentTimeBlock ? `<system-reminder>\n# Current Time\n${currentTimeBlock}\n</system-reminder>` : '',
183
187
  deferredToolDelta?.content || '',
184
188
  goalReminder?.content || '',
@@ -206,6 +210,7 @@ export async function buildUserTurn({
206
210
  deferredToolDelta,
207
211
  goalReminder,
208
212
  workspaceNotice,
213
+ setupNotice,
209
214
  userTurnMessage,
210
215
  outgoing: [...historyMessages, userTurnMessage],
211
216
  };
@@ -8,7 +8,7 @@ import { ingestSessionTurn } from '../../../../session-search/session-search-ing
8
8
  import { persistedAssistantTranscriptMetadata } from '../../../../shared/transcript-metadata.mjs';
9
9
  import { acknowledgePendingDeferredToolDelta } from '../../runtime-core/deferred-tool-delta.mjs';
10
10
  import { acknowledgePendingGoalReminder } from '../../runtime-core/goal-reminder.mjs';
11
- import { acknowledgePendingWorkspaceNotice } from './prompt-utils.mjs';
11
+ import { acknowledgePendingSetupNotice, acknowledgePendingWorkspaceNotice } from './prompt-utils.mjs';
12
12
  import {
13
13
  finalizePendingMessageDelivery,
14
14
  drainPendingMessages,
@@ -43,6 +43,8 @@ export function attachAssistantTranscriptCompletion(messages, completion, turnSt
43
43
  }
44
44
  for (let index = messages.length - 1; index > turnStart; index -= 1) {
45
45
  const message = messages[index];
46
+ // An earlier turn's recorded end bounds this turn.
47
+ if (message?.meta?.transcript?.completion) break;
46
48
  if (message?.role !== 'assistant') continue;
47
49
  const content = message.content;
48
50
  const hasVisibleText =
@@ -72,6 +74,21 @@ export function attachAssistantTranscriptCompletion(messages, completion, turnSt
72
74
  return false;
73
75
  }
74
76
 
77
+ /** Records a failed turn's end on its last message: its tool result, its
78
+ * last reply, or the prompt itself when the turn produced nothing. Only for
79
+ * a turn whose prompt survived in `messages`, so that message is the turn's. */
80
+ export function attachFailedTurnCompletion(messages, completion) {
81
+ if (!Array.isArray(messages) || !completion || typeof completion !== 'object') return false;
82
+ const index = messages.length - 1;
83
+ const message = messages[index];
84
+ if (!message || message.role === 'system') return false;
85
+ const meta = message.meta && typeof message.meta === 'object' ? message.meta : {};
86
+ const transcript = meta.transcript && typeof meta.transcript === 'object' ? meta.transcript : {};
87
+ // A new object: the save worker detects changed messages by identity.
88
+ messages[index] = { ...message, meta: { ...meta, transcript: { ...transcript, completion } } };
89
+ return true;
90
+ }
91
+
75
92
  /** Commits the loop result into the session: messages, usage, provider state
76
93
  * and queue acknowledgements. Returns the terminal result preview. */
77
94
  export async function commitAskTurn({ sessionId, opened, prepared, result, rawTranscriptMeta, askStartedAt }) {
@@ -125,6 +142,7 @@ export async function commitAskTurn({ sessionId, opened, prepared, result, rawTr
125
142
  if (prepared.workspaceNotice) {
126
143
  acknowledgePendingWorkspaceNotice(session, prepared.workspaceNotice.revision);
127
144
  }
145
+ if (prepared.setupNotice) acknowledgePendingSetupNotice(session, prepared.setupNotice.revision);
128
146
  return {
129
147
  ...result,
130
148
  trimmed: messagesDropped > 0,