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
@@ -15,6 +15,8 @@ import { crossTurnSignature, isEditProgressTool } from '../loop/completion-guard
15
15
  import { isEagerDispatchable, isToolCallDedupEligible, parseNativeToolSearchPayload } from '../loop/tool-helpers.mjs';
16
16
  import { restoreToolCallBodyForId } from '../loop/stored-tool-args.mjs';
17
17
  import { stageToolResult } from './state.mjs';
18
+ import { providerConsumesReadWindows } from '../../providers/registry.mjs';
19
+ import { remoteReadWindowReport } from '../../tools/builtin/external-tool-adapters.mjs';
18
20
  import { toolMetaPatchFromMessage } from '../transcript-restore/tool-result-status.mjs';
19
21
  import {
20
22
  compactToolResultImage,
@@ -42,12 +44,30 @@ export async function finalizeBatchResults(batch) {
42
44
  for (const state of offloadStates) {
43
45
  if (state?.result && typeof state.result === 'object') state.result = await compactResultImages(state.result);
44
46
  }
47
+ await reportReadWindows(batch);
45
48
  for (let index = 0; index < batch.completed.length; index += 1) {
46
49
  postProcessCompleted(batch, batch.completed[index], offloadStates[index]);
47
50
  batch.throwIfAborted();
48
51
  }
49
52
  }
50
53
 
54
+ // A provider that declares `consumesReadWindows` (also through a remote/proxy
55
+ // stand-in) only receives the read text. Its read results carry the
56
+ // structured clip report next to the text, for every serving path (live,
57
+ // eager or cached). Failure fails closed.
58
+ async function reportReadWindows(batch) {
59
+ if (!providerConsumesReadWindows(batch.sessionRef?.provider)) return;
60
+ for (const completed of batch.completed) {
61
+ if (!completed.executeOk || !_isReadTool(completed.call.name)) continue;
62
+ try {
63
+ const report = await remoteReadWindowReport(completed.call.arguments, batch.cwd, completed.result);
64
+ if (report) completed.readWindow = report;
65
+ } catch {
66
+ completed.readWindow = { lineClipped: true };
67
+ }
68
+ }
69
+ }
70
+
51
71
  // An image no provider can take is replaced by fixed text here, before it can
52
72
  // reach the transcript and fail every later send.
53
73
  const unsupportedImageText = (mimeType) => `[image omitted: ${mimeType} is not a supported image type]`;
@@ -57,7 +77,10 @@ const UNDECODABLE_IMAGE_TEXT = '[image omitted: could not be decoded]';
57
77
  // inline image is fully decoded (not only large ones); with no decoder
58
78
  // installed the image is kept as is.
59
79
  async function rejectedImageText(base64, rawMime) {
60
- const mimeType = String(rawMime || 'image/png').split(';')[0].trim().toLowerCase();
80
+ const mimeType = String(rawMime || 'image/png')
81
+ .split(';')[0]
82
+ .trim()
83
+ .toLowerCase();
61
84
  if (!SUPPORTED_IMAGE_MIME_TYPES.has(mimeType)) return unsupportedImageText(mimeType);
62
85
  try {
63
86
  await resizeImageBuffer(Buffer.from(base64, 'base64'), mimeType.split('/')[1]);
@@ -73,8 +96,8 @@ async function rejectedImageText(base64, rawMime) {
73
96
  // the result reaches the read cache or the transcript; stored history is never
74
97
  // revisited.
75
98
  export async function compactResultImages(result) {
76
- const parts = Array.isArray(result) ? result : Array.isArray(result?.content) ? result.content : null;
77
- if (!parts) return result;
99
+ const parts = Array.isArray(result) ? result : result?.content;
100
+ if (!Array.isArray(parts)) return result;
78
101
  let changed = false;
79
102
  const next = [];
80
103
  for (const part of parts) {
@@ -101,16 +124,16 @@ export async function compactResultImages(result) {
101
124
  if (dims.originalWidth !== dims.displayWidth || dims.originalHeight !== dims.displayHeight) {
102
125
  next.push({ type: 'text', text: supersedingImageMetadataText(dims) });
103
126
  }
104
- next.push(
105
- source
106
- ? { ...part, source: { ...source, data: compacted.data, media_type: compacted.mimeType } }
107
- : {
108
- ...part,
109
- data: compacted.data,
110
- mimeType: compacted.mimeType,
111
- ...(part.mediaType ? { mediaType: compacted.mimeType } : {}),
112
- }
113
- );
127
+ if (source) {
128
+ next.push({ ...part, source: { ...source, data: compacted.data, media_type: compacted.mimeType } });
129
+ } else {
130
+ next.push({
131
+ ...part,
132
+ data: compacted.data,
133
+ mimeType: compacted.mimeType,
134
+ ...(part.mediaType ? { mediaType: compacted.mimeType } : {}),
135
+ });
136
+ }
114
137
  }
115
138
  if (!changed) return result;
116
139
  return Array.isArray(result) ? next : { ...result, content: next };
@@ -281,6 +304,7 @@ function completedToolResult(completed, result, postprocessStartedAt) {
281
304
  toolKind: completed.resultKind,
282
305
  toolTiming: toolTiming(completed, postprocessStartedAt),
283
306
  ...(completed.nativeToolSearch ? { nativeToolSearch: completed.nativeToolSearch } : {}),
307
+ ...(completed.readWindow ? { readWindow: completed.readWindow } : {}),
284
308
  ...(uiDiff !== null ? { uiDiff } : {}),
285
309
  ...toolMetaPatchFromMessage(completed.result),
286
310
  };
@@ -3,7 +3,12 @@
3
3
  // and the repeat-failure / argument-shape guards. `skip` is the staged tool
4
4
  // message for a resolved call, or null when the call may execute.
5
5
  import { appendAgentTrace } from '../../agent-trace.mjs';
6
- import { _argShapeSig, _repeatFailureSig, _repeatFailurePatternWouldContinue } from '../loop/tool-classify.mjs';
6
+ import {
7
+ _argShapeSig,
8
+ _repeatFailureSig,
9
+ _repeatFailurePatternWouldContinue,
10
+ requiresReadBody,
11
+ } from '../loop/tool-classify.mjs';
7
12
  import { preDispatchDenyForSession } from '../loop/pre-dispatch-deny.mjs';
8
13
  import { crossTurnSignature, crossTurnDedupStub } from '../loop/completion-guards.mjs';
9
14
  import { isToolCallDedupEligible } from '../loop/tool-helpers.mjs';
@@ -27,7 +32,7 @@ export function preDispatchSkip(batch, call) {
27
32
  'error'
28
33
  );
29
34
  }
30
- if (plan.duplicateCallIds.has(call.id)) {
35
+ if (plan.duplicateCallIds.has(call.id) && !requiresReadBody(call.name, sessionRef)) {
31
36
  const firstId = plan.dupFirstId.get(call.id);
32
37
  // Explicitly NOT a success: no tool executed for this call. 'skipped'
33
38
  // keeps the transcript/UI non-error while the unresolved-tool-failure
@@ -43,7 +48,7 @@ export function preDispatchSkip(batch, call) {
43
48
  let ctSig = null;
44
49
  if (isToolCallDedupEligible(call.name, tools)) {
45
50
  ctSig = crossTurnSignature(call.name, call.arguments);
46
- const stub = crossTurnStub(batch, call, ctSig);
51
+ const stub = requiresReadBody(call.name, sessionRef) ? null : crossTurnStub(batch, call, ctSig);
47
52
  if (stub !== null) return skipped(stub, 'skipped', ctSig);
48
53
  }
49
54
  const sigs = {
@@ -60,7 +65,13 @@ export function preDispatchSkip(batch, call) {
60
65
  function crossTurnStub(batch, call, ctSig) {
61
66
  const prior = batch.crossTurnCalls.get(ctSig);
62
67
  if (!prior || prior.firstIteration >= batch.iterations) return null;
63
- const cached = lookupToolResultReuse({ sessionId: batch.sessionId, call, cwd: batch.cwd, touch: false });
68
+ const cached = lookupToolResultReuse({
69
+ sessionId: batch.sessionId,
70
+ call,
71
+ cwd: batch.cwd,
72
+ touch: false,
73
+ sessionRef: batch.sessionRef,
74
+ });
64
75
  if (!cached || !prior.toolUseId || cached.entry.firstToolUseId !== prior.toolUseId) {
65
76
  batch.crossTurnCalls.delete(ctSig);
66
77
  return null;
@@ -61,13 +61,15 @@ export function rejectedToolSchema(error, { sendTools, sessionRef, opts }) {
61
61
  const nativeCount = providerNativeToolPrefixCount(tools);
62
62
  // The wire list: the request's tools minus those the wire left out.
63
63
  const wire = tools.filter((tool) => !providerToolExclusionReason(sessionRef, tool?.name));
64
- const hosted = sessionRef?.wireRoute?.wire !== 'chat' && Array.isArray(opts?.nativeTools) ? opts.nativeTools.length : 0;
64
+ const hosted =
65
+ sessionRef?.wireRoute?.wire !== 'chat' && Array.isArray(opts?.nativeTools) ? opts.nativeTools.length : 0;
65
66
  const entries = evidence(error);
66
67
  let name = '';
67
68
  for (const entry of entries) {
68
69
  const found = target(entry);
69
70
  if (!found) continue;
70
- const tool = found.name ? wire.find((t) => t?.name === found.name) : wire[found.index - (found.shifted ? hosted : 0)];
71
+ const shift = found.shifted ? hosted : 0;
72
+ const tool = found.name ? wire.find((t) => t?.name === found.name) : wire[found.index - shift];
71
73
  name = typeof tool?.name === 'string' ? tool.name : '';
72
74
  if (name) break;
73
75
  }
@@ -37,8 +37,24 @@ import {
37
37
  isTranscriptCancelledStatusText,
38
38
  } from '../../../../shared/tool-execution-contract.mjs';
39
39
  import { toolResultTerminalStatus } from '../../../../shared/tool-status.mjs';
40
- import { transcriptRouteMetadataFields } from '../../../../shared/transcript-metadata.mjs';
40
+ import { transcriptAttachmentFields, transcriptRouteMetadataFields } from '../../../../shared/transcript-metadata.mjs';
41
41
  import { isImportedMessage } from '../imported-message.mjs';
42
+ import { isContextAckMessage } from '../compact/user-message-kind.mjs';
43
+
44
+ /** A failed turn's recorded end: its route, reason and quota stop, the same
45
+ * fields the live turndone carries. */
46
+ function restoredFailureFields(value) {
47
+ if (value.status !== 'failed') return {};
48
+ const errorKind = value.errorKind && typeof value.errorKind === 'object' ? value.errorKind : null;
49
+ const quota = value.quota && typeof value.quota === 'object' ? value.quota : null;
50
+ return {
51
+ ...transcriptRouteMetadataFields(value),
52
+ ...(typeof value.detail === 'string' && value.detail ? { detail: value.detail } : {}),
53
+ ...(typeof value.errorDetails === 'string' && value.errorDetails ? { errorDetails: value.errorDetails } : {}),
54
+ ...(errorKind && typeof errorKind.kind === 'string' ? { errorKind: { ...errorKind } } : {}),
55
+ ...(quota && typeof quota.provider === 'string' ? { quota: { ...quota } } : {}),
56
+ };
57
+ }
42
58
 
43
59
  function restoredTranscriptMetadata(message) {
44
60
  const value = message?.meta?.transcript;
@@ -53,6 +69,10 @@ function restoredTranscriptMetadata(message) {
53
69
  if (typeof completionValue.checkpointId === 'string' && completionValue.checkpointId) {
54
70
  completion.checkpointId = completionValue.checkpointId;
55
71
  }
72
+ Object.assign(completion, restoredFailureFields(completionValue));
73
+ const attemptId = completionValue.attemptId || value.attemptId;
74
+ if (typeof attemptId === 'string' && attemptId) completion.attemptId = attemptId;
75
+ if (Number.isFinite(Number(completionValue.at))) completion.at = Number(completionValue.at);
56
76
  }
57
77
  return {
58
78
  // The stable message id lets a live view map a compaction's dropped
@@ -63,6 +83,9 @@ function restoredTranscriptMetadata(message) {
63
83
  ...(typeof value.sender === 'string' && value.sender ? { sender: value.sender } : {}),
64
84
  ...(typeof value.device === 'string' && value.device ? { device: value.device } : {}),
65
85
  ...(typeof value.checkpointId === 'string' && value.checkpointId ? { checkpointId: value.checkpointId } : {}),
86
+ // The attachments this prompt carried, by content hash: a restored row
87
+ // opens/downloads them by id from the attachment store.
88
+ ...transcriptAttachmentFields(value),
66
89
  // Skills this user turn explicitly loaded (header selection or `$name`).
67
90
  ...(Array.isArray(value.appliedSkills) && value.appliedSkills.length
68
91
  ? { appliedSkills: value.appliedSkills.filter((name) => typeof name === 'string' && name) }
@@ -71,24 +94,45 @@ function restoredTranscriptMetadata(message) {
71
94
  };
72
95
  }
73
96
 
97
+ function restoredTurnDoneItem(completion, metadata, nextId, finalAssistantId = '') {
98
+ const at = Number.isFinite(completion.at) ? completion.at : metadata.at;
99
+ return {
100
+ kind: 'turndone',
101
+ id: nextId(),
102
+ ...completion,
103
+ ...(completion.status === 'done' && finalAssistantId ? { finalAssistantId } : {}),
104
+ ...(Number.isFinite(at) ? { at } : {}),
105
+ ...(metadata.messageId ? { messageId: metadata.messageId } : {}),
106
+ };
107
+ }
108
+
74
109
  function restoredAssistantTranscriptItems(message, nextId) {
75
110
  const text = (typeof message?.content === 'string' ? message.content : toolResultText(message?.content)).trim();
76
111
  if (!text) return [];
77
112
  const { completion, ...metadata } = restoredTranscriptMetadata(message);
78
113
  const items = [{ kind: 'assistant', id: nextId(), text, ...metadata }];
79
- if (completion) {
80
- items.push({
81
- kind: 'turndone',
82
- id: nextId(),
83
- ...completion,
84
- ...(completion.status === 'done' ? { finalAssistantId: items[0].id } : {}),
85
- ...(metadata.at ? { at: metadata.at } : {}),
86
- ...(metadata.messageId ? { messageId: metadata.messageId } : {}),
87
- });
114
+ // A failed end follows the message's tool calls (restoreTranscriptRange).
115
+ if (completion && completion.status !== 'failed') {
116
+ items.push(restoredTurnDoneItem(completion, metadata, nextId, items[0].id));
88
117
  }
89
118
  return items;
90
119
  }
91
120
 
121
+ /** The failed end recorded on a message that holds no reply text before it:
122
+ * the prompt itself, a tool call or a tool result. */
123
+ function restoredFailedTurnItems(message, nextId) {
124
+ const { completion, ...metadata } = restoredTranscriptMetadata(message);
125
+ const previous = Array.isArray(message?.meta?.transcript?.previousCompletions)
126
+ ? message.meta.transcript.previousCompletions
127
+ : [];
128
+ const items = previous.flatMap((value) => {
129
+ const historical = restoredTranscriptMetadata({ meta: { transcript: { completion: value, at: value?.at } } });
130
+ return historical.completion ? [restoredTurnDoneItem(historical.completion, historical, nextId)] : [];
131
+ });
132
+ if (completion?.status === 'failed') items.push(restoredTurnDoneItem(completion, metadata, nextId));
133
+ return items;
134
+ }
135
+
92
136
  // Restored tool cards: stored assistant messages keep their (compacted)
93
137
  // tool_calls and the follow-up role:'tool' results. Rebuild one transcript
94
138
  // tool item per call and attach its result by tool_call_id, so a reopened
@@ -289,13 +333,17 @@ function restoredMessageItemUpperBound(message) {
289
333
  const boundaries =
290
334
  (Array.isArray(message?.meta?.sessionInheritances) ? message.meta.sessionInheritances.length : 0) +
291
335
  (Array.isArray(message?.meta?.modelSwitches) ? message.meta.modelSwitches.length : 0);
292
- if (message?.role === 'user') return 1 + boundaries;
293
- if (message?.role !== 'assistant') return boundaries;
336
+ const completionCount =
337
+ Number(Boolean(message?.meta?.transcript?.completion)) +
338
+ (Array.isArray(message?.meta?.transcript?.previousCompletions)
339
+ ? message.meta.transcript.previousCompletions.length
340
+ : 0);
341
+ if (message?.role === 'user') return 1 + completionCount + boundaries;
342
+ if (message?.role !== 'assistant') return completionCount + boundaries;
294
343
  const calls = restoredMessageToolCalls(message);
295
344
  const content = message?.content;
296
345
  const hasContent = typeof content === 'string' ? content.length > 0 : Array.isArray(content) && content.length > 0;
297
- const hasCompletion = Boolean(message?.meta?.transcript?.completion);
298
- return Number(hasContent) + Number(hasCompletion) + calls.length + boundaries;
346
+ return Number(hasContent) + completionCount + calls.length + boundaries;
299
347
  }
300
348
 
301
349
  // One restored tool card for a parsed notification/completion envelope.
@@ -404,12 +452,14 @@ function restoreTranscriptRange(messages, start, sessionId) {
404
452
  const restoredId = () => `hist_${sessionId}_${index}_${++part}`;
405
453
  if (message?.role === 'user') {
406
454
  items.push(...restoredUserTranscriptItems(message, restoredId));
407
- } else if (message?.role === 'assistant') {
455
+ } else if (message?.role === 'assistant' && !isContextAckMessage(message, messages[index - 1])) {
408
456
  items.push(...restoredAssistantTranscriptItems(message, restoredId));
409
457
  items.push(...restoredToolCallItems(message, restoredId, pendingToolCalls));
410
458
  } else if (message?.role === 'tool') {
411
459
  attachRestoredToolResult(message, pendingToolCalls);
412
460
  }
461
+ const eventStart = items.length;
462
+ items.push(...restoredFailedTurnItems(message, restoredId));
413
463
  for (const boundary of Array.isArray(message?.meta?.sessionInheritances) ? message.meta.sessionInheritances : []) {
414
464
  if (!boundary?.sessionId || !boundary?.provider || !boundary?.modelId) continue;
415
465
  items.push({
@@ -427,6 +477,13 @@ function restoreTranscriptRange(messages, start, sessionId) {
427
477
  if (!boundary?.provider || !boundary?.modelId) continue;
428
478
  items.push(modelSwitchItem(restoredId(), boundary));
429
479
  }
480
+ if (message?.meta?.transcript?.previousCompletions?.length) {
481
+ const events = items.slice(eventStart);
482
+ if (events.every((item) => Number.isFinite(item.at))) {
483
+ events.sort((left, right) => left.at - right.at);
484
+ items.splice(eventStart, events.length, ...events);
485
+ }
486
+ }
430
487
  }
431
488
  return mergeRestoredToolItems(items);
432
489
  }
@@ -0,0 +1,45 @@
1
+ // The failed-turn record shared by the live turn close (tui/session/turn.mjs)
2
+ // and the durable turn end (manager/ask-turn-failure.mjs), so a reopened
3
+ // session shows the same failure, reason and quota stop as the live one.
4
+ import { errText } from '../../../shared/err-text.mjs';
5
+ import { safeErrorDetails } from '../../../shared/error-presentation.mjs';
6
+ import { providerErrorKind } from '../providers/provider-error-kind.mjs';
7
+ import { toolErrorDisplay } from './transcript-restore/tool-result-text.mjs';
8
+
9
+ /**
10
+ * `{ providerKind, errorKind, quota, detail, errorDetails }` for one turn
11
+ * error. `quota` is null unless the pool validated an exhaustion or the
12
+ * provider named the real reset time; `route` fills its provider/model.
13
+ */
14
+ export function turnFailureRecord(error, route = {}) {
15
+ // Presentation only: legacy untyped failure text may still name a usage limit.
16
+ const providerKind = providerErrorKind(error, { legacyQuotaWording: true });
17
+ const errorKind = {
18
+ kind: providerKind.kind,
19
+ code: providerKind.code,
20
+ status: providerKind.status,
21
+ retryAfterMs: providerKind.retryAfterMs,
22
+ resetAt: providerKind.resetAt,
23
+ };
24
+ const exhausted = error?.quotaExhausted;
25
+ const resetKnown = providerKind.kind === 'quota_exhausted' && Number.isFinite(providerKind.resetAt);
26
+ let quota = null;
27
+ if ((exhausted && typeof exhausted === 'object') || resetKnown) {
28
+ const source = exhausted && typeof exhausted === 'object' ? exhausted : {};
29
+ let resetAt = null;
30
+ if (Number.isFinite(source.resetAt)) resetAt = source.resetAt;
31
+ else if (Number.isFinite(providerKind.resetAt)) resetAt = providerKind.resetAt;
32
+ quota = {
33
+ provider: String(source.provider || route.provider || ''),
34
+ model: String(source.model || route.model || ''),
35
+ resetAt,
36
+ };
37
+ }
38
+ return {
39
+ providerKind,
40
+ errorKind,
41
+ quota,
42
+ detail: toolErrorDisplay(error, 'turn').replace(/^Error:\s*/i, ''),
43
+ errorDetails: safeErrorDetails(errText(error)),
44
+ };
45
+ }
@@ -259,6 +259,56 @@ export const PROVIDER_WS_SEMANTIC_IDLE_TIMEOUT_MS = resolveTimeoutMs(
259
259
  { minMs: 10_000, maxMs: Math.max(10_000, STALL_ABORT_MS - STALL_TICK_MS) }
260
260
  );
261
261
 
262
+ /**
263
+ * The longest a provider's own first-byte handling may legitimately run
264
+ * before it gives up, over every attempt it permits: `windowMs(n)` is the wait
265
+ * of attempt n, applied to the response headers and again to the first chunk,
266
+ * and `backoffMs[n]` the sleep before attempt n (index 0 unused, the last
267
+ * value repeats). `transportMs` covers the header stage only; `semanticMs`
268
+ * covers headers plus first chunk. The agent watchdog's first-response
269
+ * deadlines sit above these, so the provider's timeout and retry decide first.
270
+ */
271
+ export function providerFirstResponseBudget({ attempts, windowMs, backoffMs = [] }) {
272
+ let transportMs = 0;
273
+ let semanticMs = 0;
274
+ for (let attempt = 0; attempt < Math.max(1, attempts); attempt++) {
275
+ const backoff = attempt > 0 ? (backoffMs[Math.min(attempt, backoffMs.length - 1)] ?? 0) : 0;
276
+ const window = windowMs(attempt);
277
+ transportMs += backoff + window;
278
+ semanticMs += backoff + 2 * window;
279
+ }
280
+ return { transportMs, semanticMs };
281
+ }
282
+
283
+ /**
284
+ * A provider's first-byte policy `{ timeoutMs, maxMs, retries }`: `timeoutMs`
285
+ * is the first attempt's window (headers, and again the first chunk); each
286
+ * first-byte timeout doubles the next window up to `maxMs`, and `retries` caps
287
+ * how many of those timeouts are retried. `retries: null` leaves first-byte
288
+ * timeouts to the provider's ordinary ladder, every attempt on `timeoutMs`.
289
+ * Returns the window of an attempt after `timeouts` first-byte timeouts.
290
+ */
291
+ export function firstByteWindowMs(policy, timeouts = 0) {
292
+ if (policy.retries == null) return policy.timeoutMs;
293
+ return Math.min(policy.timeoutMs * 2 ** timeouts, Math.max(policy.timeoutMs, policy.maxMs));
294
+ }
295
+
296
+ /**
297
+ * providerFirstResponseBudget for a first-byte policy over a ladder of
298
+ * `attempts` sends. Connection drops and 5xx responses share that ladder with
299
+ * first-byte timeouts, and such a failure can land just before the timeout, so
300
+ * every attempt is budgeted a full window. A window only grows with the
301
+ * timeouts before it and at most `retries` timeouts are retried, so the worst
302
+ * case has the timeouts first, then later attempts at the widest window.
303
+ */
304
+ export function firstBytePolicyBudget(policy, { attempts, backoffMs }) {
305
+ return providerFirstResponseBudget({
306
+ attempts,
307
+ windowMs: (attempt) => firstByteWindowMs(policy, Math.min(attempt, policy.retries ?? 0)),
308
+ backoffMs,
309
+ });
310
+ }
311
+
262
312
  // First retry has a small floor (250ms) instead of 0ms: an immediate reissue on
263
313
  // a transient 5xx burst lets parallel workers thundering-herd the backend in
264
314
  // lockstep (jitter alone can't decluster a 0ms base). Subsequent steps keep the
@@ -1,5 +1,6 @@
1
1
  import { renderBackgroundTask, startBackgroundTask } from '../../../../../shared/background-tasks.mjs';
2
2
  import { killShellDescendants, waitForShellDescendants } from '../../lib/shell-descendants.mjs';
3
+ import { releaseShellJobWorkspace } from '../lib/shell-job-records.mjs';
3
4
  import { consumeFilterTeeCapture } from '../shell-analysis.mjs';
4
5
  import { compactShellOutputLosslessly, renderShellOutputBody } from '../shell-lossless-compact.mjs';
5
6
  import { removeTransportFileNow } from './transport-artifacts.mjs';
@@ -33,7 +34,10 @@ function trackSurvivingDescendants(handle, { command, cwd, options, startedAtMs
33
34
  meta: { task_id: handle.taskId, stdout: null, stderr: null, cwd, timeoutMs: 0 },
34
35
  resultType: 'shell_task_result',
35
36
  run: async () => {
36
- await waitForShellDescendants(handle, { pollMs: 1_000 });
37
+ await waitForShellDescendants(handle);
38
+ // The folder reservation the finished command handed to its
39
+ // survivors ends with the last of them.
40
+ releaseShellJobWorkspace(handle.taskId);
37
41
  return {
38
42
  task_id: handle.taskId,
39
43
  status: 'completed',
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { writeFileSync } from 'node:fs';
2
3
  import { tmpdir } from 'node:os';
3
4
  import { join as pathJoin } from 'node:path';
@@ -23,12 +24,15 @@ export function hoistInlineScript(command, shellType) {
23
24
  planLongShellScriptFileTransport(command, transport);
24
25
  if (!hoist) return { command, hoistPath: null };
25
26
  try {
26
- const file = pathJoin(tmpdir(), `mixdog-inline-${process.pid}-${Date.now().toString(36)}${hoist.extension}`);
27
+ // One file per command: parallel calls start within the same millisecond,
28
+ // and a shared name let a later script overwrite an earlier one before it
29
+ // ran. The exclusive flag refuses any name that already exists.
30
+ const file = pathJoin(tmpdir(), `mixdog-inline-${process.pid}-${randomUUID()}${hoist.extension}`);
27
31
  // Windows PowerShell 5.1 interprets UTF-8 without BOM as the active ANSI
28
32
  // codepage. Preserve non-ASCII command text when the transport changes a
29
33
  // long command into a .ps1 file.
30
34
  const fileBody = hoist.extension === '.ps1' ? `\uFEFF${hoist.body}` : hoist.body;
31
- writeFileSync(file, fileBody, 'utf8');
35
+ writeFileSync(file, fileBody, { encoding: 'utf8', flag: 'wx' });
32
36
  return { command: hoist.replace(file.replace(/\\/g, '/')), hoistPath: file };
33
37
  } catch {
34
38
  return { command, hoistPath: null };