mixdog 1.2.1 → 1.2.3

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 (557) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/gate-local.mjs +19 -3
  4. package/scripts/model-catalog-audit.mjs +1 -15
  5. package/scripts/provider-pingpong-live.mjs +509 -0
  6. package/src/agents/advisor/AGENT.md +1 -1
  7. package/src/agents/advisor/agent.json +1 -1
  8. package/src/agents/reviewer/AGENT.md +3 -3
  9. package/src/agents/reviewer/agent.json +1 -1
  10. package/src/defaults/shipped-history.json +6 -0
  11. package/src/defaults/skills/setup/SKILL.md +6 -1
  12. package/src/defaults/skills/setup/references/actions.md +44 -22
  13. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  14. package/src/headless-exec.mjs +15 -8
  15. package/src/lib/keychain-cjs.cjs +7 -4
  16. package/src/output-styles/common.md +11 -10
  17. package/src/repl/slash-commands.mjs +16 -1
  18. package/src/rules/agent/AGENT.md +5 -5
  19. package/src/rules/lead/LEAD.md +5 -5
  20. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
  21. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
  22. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  23. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  24. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  25. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  26. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  27. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  28. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  29. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +36 -7
  30. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +49 -10
  31. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +40 -3
  32. package/src/runtime/agent/orchestrator/mcp/client.mjs +230 -96
  33. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
  34. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
  35. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
  36. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
  37. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
  38. package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
  39. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
  40. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
  41. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +188 -29
  42. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
  43. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  44. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
  45. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +98 -0
  46. package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
  47. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
  48. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +48 -37
  49. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +10 -7
  50. package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
  51. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
  52. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  53. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
  54. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
  55. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
  56. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
  57. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +102 -45
  58. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
  59. package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
  60. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  61. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  62. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  63. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  65. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  66. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  67. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  69. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +40 -7
  70. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
  71. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
  72. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +88 -21
  73. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -10
  74. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +106 -0
  75. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
  76. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +94 -15
  77. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
  79. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  80. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +75 -10
  81. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  82. package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
  83. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +103 -23
  84. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
  85. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
  86. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +32 -6
  87. package/src/runtime/agent/orchestrator/providers/cursor.mjs +27 -3
  88. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
  89. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
  90. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  91. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  92. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  93. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +80 -18
  94. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  95. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +46 -8
  96. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +273 -0
  97. package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
  98. package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
  99. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  100. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
  102. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +369 -112
  103. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +3 -1
  104. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +140 -35
  105. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +70 -24
  106. package/src/runtime/agent/orchestrator/providers/gemini.mjs +80 -29
  107. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  109. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +69 -19
  110. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  111. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  112. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
  113. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  114. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  115. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
  116. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  117. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  118. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  119. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  120. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
  121. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
  122. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  123. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
  124. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
  125. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  126. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  127. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
  128. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
  129. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
  130. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +123 -61
  132. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  133. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +27 -2
  134. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
  135. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  136. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
  137. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
  138. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
  139. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  140. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  141. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
  142. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +64 -23
  143. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +79 -33
  144. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  145. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
  146. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
  147. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +144 -15
  148. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
  149. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
  150. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +9 -2
  151. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  152. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +109 -26
  153. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +27 -6
  154. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +34 -20
  155. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +23 -4
  156. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +37 -28
  157. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
  158. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
  159. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  160. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +43 -15
  161. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  162. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  163. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +5 -2
  164. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
  165. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +7 -3
  166. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  167. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
  168. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
  169. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  170. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +37 -4
  171. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +12 -1
  172. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
  173. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +12 -1
  174. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +76 -33
  175. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  176. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
  177. package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
  178. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
  179. package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
  180. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  181. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
  182. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  183. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
  184. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
  185. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  186. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  187. package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
  188. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +41 -22
  189. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
  190. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
  191. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
  192. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +720 -0
  193. package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
  194. package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
  195. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +123 -219
  196. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
  197. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
  198. package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
  199. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  200. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  201. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
  202. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
  203. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  204. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
  205. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
  206. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
  207. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
  208. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
  210. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
  211. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
  212. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -97
  213. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  214. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  215. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
  216. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  217. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  218. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  219. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
  220. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
  221. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  222. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -1
  223. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  224. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
  225. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  226. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
  227. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  228. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  229. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
  230. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  231. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
  232. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  233. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  234. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  235. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
  236. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
  237. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
  238. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
  239. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
  240. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +104 -19
  241. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  242. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  243. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
  244. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  245. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
  246. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -2
  247. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +30 -2
  248. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +11 -2
  249. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
  250. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  251. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +57 -21
  252. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  253. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  254. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  255. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  256. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +5 -10
  257. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
  258. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +16 -4
  259. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
  260. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  261. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
  262. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
  263. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  264. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
  265. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
  266. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  267. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +168 -29
  268. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  269. package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
  270. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
  271. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  272. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
  273. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
  274. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
  275. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  276. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
  277. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
  278. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
  279. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
  280. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  281. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +6 -0
  282. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +13 -0
  283. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +13 -1
  284. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
  285. package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
  286. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
  287. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
  288. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  289. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  290. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  291. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
  292. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +20 -1
  293. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  294. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
  295. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  296. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
  297. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  298. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
  299. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
  300. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
  301. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  302. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  303. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  304. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  305. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  306. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  307. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  308. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  309. package/src/runtime/computer-bridge/action-schema.mjs +44 -21
  310. package/src/runtime/github/tool.mjs +92 -2
  311. package/src/runtime/memory/index.mjs +1 -0
  312. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  313. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  314. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  315. package/src/runtime/memory/lib/pg/process.mjs +65 -50
  316. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  317. package/src/runtime/memory/lib/pg/supervisor.mjs +124 -16
  318. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  319. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  320. package/src/runtime/office/README.md +2 -2
  321. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  322. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  323. package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
  324. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  325. package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
  326. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  327. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  328. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  329. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  330. package/src/runtime/office/core/office-sessions.mjs +5 -0
  331. package/src/runtime/office/core/office-transactions.mjs +3 -0
  332. package/src/runtime/office/core/office-write-ledger.mjs +98 -0
  333. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  334. package/src/runtime/office/index.mjs +30 -0
  335. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  336. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  337. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  338. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  339. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  340. package/src/runtime/office/shared/values.mjs +0 -5
  341. package/src/runtime/shared/background-tasks.mjs +92 -14
  342. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  343. package/src/runtime/shared/bounded-line-diff.mjs +182 -0
  344. package/src/runtime/shared/buffered-appender.mjs +18 -0
  345. package/src/runtime/shared/config.mjs +78 -18
  346. package/src/runtime/shared/err-text.mjs +31 -0
  347. package/src/runtime/shared/error-presentation.mjs +159 -19
  348. package/src/runtime/shared/file-permissions.d.mts +6 -1
  349. package/src/runtime/shared/file-permissions.mjs +54 -6
  350. package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
  351. package/src/runtime/shared/llm/anthropic-effort.mjs +129 -134
  352. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
  353. package/src/runtime/shared/llm/model-catalog.mjs +53 -40
  354. package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
  355. package/src/runtime/shared/llm/provider-catalog-registry.mjs +11 -0
  356. package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
  357. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  358. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  359. package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
  360. package/src/runtime/shared/loopback-listener.mjs +9 -0
  361. package/src/runtime/shared/model-display.mjs +13 -0
  362. package/src/runtime/shared/provider-api-key.mjs +2 -0
  363. package/src/runtime/shared/quota-resume-store.mjs +11 -0
  364. package/src/runtime/shared/review-diff.mjs +52 -0
  365. package/src/runtime/shared/session-baseline-store.mjs +960 -0
  366. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  367. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  368. package/src/runtime/shared/slow-span.mjs +114 -0
  369. package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
  370. package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
  371. package/src/runtime/shared/task-notification-envelope.mjs +2 -2
  372. package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
  373. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  374. package/src/runtime/shared/tool-card-model.mjs +5 -2
  375. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  376. package/src/runtime/shared/tool-primitives.mjs +13 -0
  377. package/src/runtime/shared/tool-result-summary.mjs +8 -1
  378. package/src/runtime/shared/tool-surface.mjs +18 -3
  379. package/src/runtime/shared/tool-work-units.mjs +40 -4
  380. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  381. package/src/runtime/shared/transcript-writer.mjs +10 -2
  382. package/src/runtime/shared/turn-changes.mjs +670 -274
  383. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  384. package/src/runtime/shared/turn-snapshot-store.mjs +94 -2
  385. package/src/runtime/shared/turn-snapshot.mjs +986 -690
  386. package/src/runtime/shared/turn-worktree-snapshot.mjs +279 -262
  387. package/src/runtime/shared/user-data-guard.mjs +262 -49
  388. package/src/runtime/shared/worktrees/carry.mjs +531 -0
  389. package/src/runtime/shared/worktrees/contract.mjs +34 -24
  390. package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
  391. package/src/runtime/shared/worktrees/git-head.mjs +205 -0
  392. package/src/runtime/shared/worktrees/git.mjs +8 -3
  393. package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
  394. package/src/runtime/shared/worktrees/manager.mjs +156 -8
  395. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  396. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  397. package/src/runtime/shared/worktrees/test-support.mjs +19 -4
  398. package/src/runtime/terminal-bridge/client.mjs +44 -11
  399. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  400. package/src/runtime/tidy/apply.mjs +47 -2
  401. package/src/runtime/tidy/run-engines.mjs +11 -5
  402. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  403. package/src/session-runtime/boot/apis.mjs +19 -5
  404. package/src/session-runtime/boot/facade.mjs +1 -0
  405. package/src/session-runtime/boot/infrastructure.mjs +12 -1
  406. package/src/session-runtime/boot/session.mjs +0 -1
  407. package/src/session-runtime/boot/tools.mjs +4 -1
  408. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  409. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
  410. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  411. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
  412. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
  413. package/src/session-runtime/internal-tool-executor.mjs +6 -2
  414. package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
  415. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  416. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -3
  417. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  418. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
  419. package/src/session-runtime/lifecycle/teardown.mjs +73 -8
  420. package/src/session-runtime/lifecycle-api.mjs +1 -0
  421. package/src/session-runtime/mcp-glue/connect.mjs +46 -14
  422. package/src/session-runtime/mcp-glue/server-catalog.mjs +20 -3
  423. package/src/session-runtime/mcp-glue.mjs +3 -0
  424. package/src/session-runtime/mcp-oauth-login.mjs +174 -0
  425. package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
  426. package/src/session-runtime/model-route/set-route.mjs +85 -17
  427. package/src/session-runtime/model-route/web-search-route.mjs +1 -1
  428. package/src/session-runtime/native-web-search/routes.mjs +22 -3
  429. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  430. package/src/session-runtime/native-web-search.mjs +10 -1
  431. package/src/session-runtime/new-session-config.mjs +4 -2
  432. package/src/session-runtime/provider-auth/login.mjs +4 -0
  433. package/src/session-runtime/provider-models/model-meta.mjs +12 -3
  434. package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
  435. package/src/session-runtime/quick-web-search-models.mjs +13 -38
  436. package/src/session-runtime/resource-extension-sync.mjs +4 -0
  437. package/src/session-runtime/resource-mcp-api.mjs +98 -2
  438. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  439. package/src/session-runtime/runtime-review-api.mjs +21 -2
  440. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  441. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
  442. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
  443. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  444. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  445. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
  446. package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
  447. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
  448. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
  449. package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
  450. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
  451. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
  452. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  453. package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
  454. package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
  455. package/src/session-runtime/services/agent-tool.mjs +3 -0
  456. package/src/session-runtime/services/channel-admin.mjs +19 -3
  457. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  458. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  459. package/src/session-runtime/services/provider-admin.mjs +81 -15
  460. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  461. package/src/session-runtime/session-turn-api.mjs +14 -5
  462. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
  463. package/src/session-runtime/settings-compaction-api.mjs +1 -0
  464. package/src/session-runtime/setup-tool/executor.mjs +36 -6
  465. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  466. package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
  467. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
  468. package/src/session-runtime/skills-api.mjs +3 -5
  469. package/src/session-runtime/tool-surface.mjs +5 -1
  470. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  471. package/src/session-runtime/turn/session-ops.mjs +7 -5
  472. package/src/session-runtime/turn/side-question-ops.mjs +22 -0
  473. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
  474. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
  475. package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
  476. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  477. package/src/session-runtime/turn/turn-run.mjs +25 -9
  478. package/src/session-runtime/usage-stats-api.mjs +43 -11
  479. package/src/session-runtime/workspace/project-branches.mjs +7 -5
  480. package/src/session-runtime/workspace/transition-steps.mjs +129 -31
  481. package/src/session-runtime/workspace/transitions.mjs +190 -15
  482. package/src/standalone/daemon-agent-control.mjs +9 -1
  483. package/src/standalone/daemon-drain-policy.mjs +8 -0
  484. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  485. package/src/standalone/daemon-owner.mjs +17 -4
  486. package/src/standalone/daemon-pg-stop.mjs +51 -0
  487. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  488. package/src/standalone/daemon-stop-budget.mjs +18 -0
  489. package/src/standalone/daemon-stored-session-views.mjs +2 -0
  490. package/src/standalone/daemon-telemetry.mjs +74 -0
  491. package/src/standalone/daemon.mjs +64 -8
  492. package/src/standalone/desktop-service-registry.mjs +5 -0
  493. package/src/standalone/local-session-runtime.mjs +70 -19
  494. package/src/standalone/session-client.mjs +42 -0
  495. package/src/standalone/session-protocol.mjs +14 -0
  496. package/src/standalone/session-proxy/projection.mjs +41 -4
  497. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  498. package/src/standalone/session-runtime-inline-host.mjs +1 -0
  499. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
  500. package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
  501. package/src/standalone/session-service/agent-tree.mjs +12 -0
  502. package/src/standalone/session-service/quota-resume.mjs +8 -0
  503. package/src/standalone/session-service/retention/busy.mjs +15 -1
  504. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  505. package/src/standalone/session-service-api.mjs +11 -1
  506. package/src/standalone/session-service.mjs +1 -0
  507. package/src/standalone/session-state-patch.d.mts +2 -1
  508. package/src/standalone/session-state-patch.mjs +41 -1
  509. package/src/tui/App.jsx +25 -0
  510. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  511. package/src/tui/app/app-view.jsx +1 -0
  512. package/src/tui/app/btw-controller.mjs +118 -0
  513. package/src/tui/app/create-app-pickers.mjs +6 -0
  514. package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
  515. package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
  516. package/src/tui/app/extension-pickers.mjs +2 -1
  517. package/src/tui/app/model-options.mjs +11 -16
  518. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  519. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  520. package/src/tui/app/slash-commands.mjs +20 -5
  521. package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
  522. package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
  523. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  524. package/src/tui/app/use-global-key-input.mjs +5 -12
  525. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  526. package/src/tui/components/BtwPanel.jsx +53 -0
  527. package/src/tui/components/QuestionPanel.jsx +275 -0
  528. package/src/tui/components/StatusLine.jsx +2 -0
  529. package/src/tui/components/question-panel-model.mjs +156 -0
  530. package/src/tui/components/status-line/local-line.mjs +5 -2
  531. package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
  532. package/src/tui/dist/index.mjs +3221 -1500
  533. package/src/tui/session/context-state.mjs +4 -2
  534. package/src/tui/session/quota-resume.mjs +46 -14
  535. package/src/tui/session/session-api/commands.mjs +43 -24
  536. package/src/tui/session/session-api/controls.mjs +2 -2
  537. package/src/tui/session/session-api/extensions.mjs +22 -0
  538. package/src/tui/session/session-api/integrations.mjs +16 -2
  539. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  540. package/src/tui/session/session-api/lifecycle.mjs +7 -2
  541. package/src/tui/session/session-api/routes.mjs +71 -7
  542. package/src/tui/session/session-api/settings.mjs +11 -14
  543. package/src/tui/session/session-api.mjs +1 -0
  544. package/src/tui/session/session-flow/drain.mjs +7 -1
  545. package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
  546. package/src/tui/session/tool-approval.mjs +10 -7
  547. package/src/tui/session/transcript-spill.mjs +14 -7
  548. package/src/tui/session/turn-stream.mjs +174 -31
  549. package/src/tui/session/turn.mjs +46 -16
  550. package/src/tui/statusline-ansi-bridge.mjs +1 -1
  551. package/src/ui/statusline-agents.mjs +15 -4
  552. package/src/ui/statusline.mjs +7 -3
  553. package/src/ui/streaming-markdown-heal.mjs +34 -3
  554. package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
  555. package/src/workflows/default/WORKFLOW.md +3 -1
  556. package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
  557. package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
@@ -1,41 +1,16 @@
1
- // Static quick-pick model ids surfaced during onboarding / web-search setup.
2
- // Limits are intentionally not hardcoded here: rows are hydrated from live
3
- // provider caches and provider-scoped metadata during catalog construction.
1
+ // Offline quick-pick model rows for onboarding / web-search setup. No model id
2
+ // is listed here: when a provider has no live roster yet, its newest rows come
3
+ // from the provider-scoped public catalog, so a new release appears without a
4
+ // code change. Rows are hydrated further during catalog construction.
5
+ import { getModelsDevProviderModelsSync } from '../runtime/shared/llm/model-catalog.mjs';
4
6
 
5
7
  export const ONBOARDING_VERSION = 1;
6
8
 
7
- export const QUICK_WEB_SEARCH_MODELS = Object.freeze({
8
- 'openai-oauth': [
9
- { id: 'gpt-6-sol', display: 'GPT-6 Sol', latest: true },
10
- { id: 'gpt-6-luna', display: 'GPT-6 Luna', latest: true },
11
- { id: 'gpt-5.6-sol', display: 'GPT-5.6 Sol' },
12
- { id: 'gpt-5.6-terra', display: 'GPT-5.6 Terra' },
13
- { id: 'gpt-5.6-luna', display: 'GPT-5.6 Luna' },
14
- ],
15
- openai: [
16
- { id: 'gpt-5.5', display: 'GPT-5.5', latest: true },
17
- { id: 'gpt-5.4', display: 'GPT-5.4', latest: true },
18
- { id: 'gpt-5', display: 'GPT-5' },
19
- { id: 'gpt-4.1', display: 'GPT-4.1' },
20
- { id: 'gpt-4o', display: 'GPT-4o' },
21
- ],
22
- 'grok-oauth': [{ id: 'grok-4.5', display: 'Grok 4.5', latest: true }],
23
- xai: [{ id: 'grok-4.5', display: 'Grok 4.5', latest: true }],
24
- gemini: [
25
- { id: 'gemini-3.6-flash', display: 'Gemini 3.6 Flash', latest: true },
26
- { id: 'gemini-3.5-flash-lite', display: 'Gemini 3.5 Flash Lite', latest: true },
27
- { id: 'gemini-3.1-pro-preview', display: 'Gemini 3.1 Pro Preview' },
28
- ],
29
- 'anthropic-oauth': [
30
- { id: 'claude-opus-5-5', display: 'Claude Opus 5.5', latest: true },
31
- { id: 'claude-sonnet-5', display: 'Claude Sonnet 5', latest: true },
32
- { id: 'claude-fable-5', display: 'Claude Fable 5', latest: true },
33
- { id: 'claude-haiku-4-5-20251001', display: 'Claude Haiku 4.5' },
34
- ],
35
- anthropic: [
36
- { id: 'claude-opus-5-5', display: 'Claude Opus 5.5', latest: true },
37
- { id: 'claude-sonnet-5', display: 'Claude Sonnet 5', latest: true },
38
- { id: 'claude-fable-5', display: 'Claude Fable 5', latest: true },
39
- { id: 'claude-haiku-4-5-20251001', display: 'Claude Haiku 4.5' },
40
- ],
41
- });
9
+ const QUICK_ROWS_PER_PROVIDER = 5;
10
+
11
+ export function quickWebSearchModels(provider, models = getModelsDevProviderModelsSync(provider)) {
12
+ return Object.entries(models || {})
13
+ .map(([id, row]) => ({ id, display: row?.name || id, releaseDate: row?.release_date || null }))
14
+ .sort((a, b) => (Date.parse(b.releaseDate) || 0) - (Date.parse(a.releaseDate) || 0))
15
+ .slice(0, QUICK_ROWS_PER_PROVIDER);
16
+ }
@@ -5,6 +5,7 @@ import { publishGlobalExtensionChange, subscribeGlobalExtensionChanges } from '.
5
5
 
6
6
  export function createExtensionSync({
7
7
  connectConfiguredMcp,
8
+ cancelMcpLogin,
8
9
  invalidatePreSessionToolSurface,
9
10
  refreshEmptySessionToolPolicy,
10
11
  reloadFullConfig,
@@ -60,6 +61,9 @@ export function createExtensionSync({
60
61
  const chain = mcpToggleChains.get(serverName) || { desired: enabled, running: null };
61
62
  chain.desired = enabled;
62
63
  mcpToggleChains.set(serverName, chain);
64
+ // A disable riding the chain would otherwise wait out an explicit sign-in
65
+ // (beginMcpOAuthLogin) of this server still in flight.
66
+ if (enabled === false) cancelMcpLogin?.(serverName);
63
67
  if (!chain.running) {
64
68
  chain.running = (async () => {
65
69
  let status;
@@ -7,8 +7,20 @@ import {
7
7
  mergeMcpServerConfig,
8
8
  MCP_TIMEOUT_FIELD_GROUPS,
9
9
  } from '../runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs';
10
+ import { resolveMcpOAuthUrl } from '../runtime/agent/orchestrator/mcp/client-config.mjs';
10
11
  import { withAdoptedCopies, withPinnedCollisionNames, withPluginServerIntent } from './mcp-glue/plugin-servers.mjs';
11
12
  import { findRegisteredPlugin } from './resource-plugins-api.mjs';
13
+ import { createMcpOAuthLogins } from './mcp-oauth-login.mjs';
14
+
15
+ /** The URL a server's OAuth credentials are stored under, or null. */
16
+ function oauthUrlOf(cfg) {
17
+ try {
18
+ return resolveMcpOAuthUrl(cfg);
19
+ } catch {
20
+ // No valid remote URL: such a server never logged in.
21
+ return null;
22
+ }
23
+ }
12
24
 
13
25
  /** The `mcpServers` map of a config as a fresh object (never the live one). */
14
26
  function mcpServersOf(config) {
@@ -59,14 +71,45 @@ export function createMcpResourceApi({ deps, sync, decorate }) {
59
71
  mcpStatus,
60
72
  getMcpServerConfig,
61
73
  connectConfiguredMcp,
74
+ clearMcpServerOAuth,
62
75
  reloadFullConfig,
63
76
  awaitKeychainPrewarm,
64
77
  pluginsStatus,
65
- resolveMcpCatalog = () => ({ adoption: null, plugins: {}, entries: {} }),
78
+ resolveMcpCatalog = () => ({ servers: {}, adoption: null, plugins: {}, entries: {} }),
79
+ resolveConfiguredMcpCatalog = resolveMcpCatalog,
66
80
  pluginMcpServer = () => null,
67
81
  flushSkillsSave,
82
+ cancelMcpLogin = () => {},
83
+ completeMcpLogin,
84
+ getMcpServerOAuthState = () => null,
85
+ probeMcpServerAuth,
68
86
  } = deps;
69
87
 
88
+ // Explicit OAuth sign-in: the one interactive MCP connect. On success the
89
+ // other runtimes reconnect the server non-interactively with the new tokens.
90
+ const oauthLogins = createMcpOAuthLogins({
91
+ async connect(name, openBrowser) {
92
+ const status = await connectConfiguredMcp({ only: name, enabled: true, login: { openBrowser } });
93
+ const row = status?.servers?.find((server) => server.name === name);
94
+ return { connected: row?.connected === true, error: row?.error || null };
95
+ },
96
+ cancel: (name) => cancelMcpLogin(name),
97
+ completeCallback: completeMcpLogin,
98
+ onComplete: (name) => sync.announce('mcp', { detail: { mcpChanges: [{ name, enabled: true }] } }),
99
+ });
100
+ /** The effective config of a server that signs in with MCP OAuth (HTTP/SSE
101
+ * without configured authentication). */
102
+ const oauthServerConfig = async (name) => {
103
+ const serverName = clean(name);
104
+ if (!serverName) throw new Error('MCP server name is required');
105
+ await awaitKeychainPrewarm();
106
+ reloadFullConfig();
107
+ const cfg = resolveMcpCatalog().servers[serverName];
108
+ if (!cfg) throw new Error(`MCP server not configured: ${serverName}`);
109
+ if (!getMcpServerOAuthState(cfg)) throw new Error(`MCP server "${serverName}" does not use OAuth sign-in`);
110
+ return { serverName, cfg };
111
+ };
112
+
70
113
  /** The config with any adoptable plugin server copies already adopted, so
71
114
  * every write also persists the adoption and never re-adds a copy. */
72
115
  const adoptedConfig = () => withAdoptedCopies(getConfig(), resolveMcpCatalog().adoption);
@@ -115,6 +158,49 @@ export function createMcpResourceApi({ deps, sync, decorate }) {
115
158
  const { enabled } = getMcpServerConfig(serverName);
116
159
  return sync.reconnectMcpAndAnnounce({ only: serverName, enabled });
117
160
  },
161
+ /** `{ flowId, state: 'pending', url }` once the browser login starts
162
+ * (`options.openBrowser === false` leaves opening `url` to the caller), or
163
+ * `{ flowId, state: 'complete' }` when stored credentials sufficed. */
164
+ async beginMcpOAuthLogin(name, options = {}) {
165
+ const { serverName, cfg } = await oauthServerConfig(name);
166
+ if (cfg.enabled === false) throw new Error(`MCP server is disabled: ${serverName}`);
167
+ return oauthLogins.begin(serverName, options);
168
+ },
169
+ /** `{ flowId, state: 'pending' | 'complete' | 'failed' | 'cancelled', error? }` */
170
+ getMcpOAuthLoginStatus(flowId) {
171
+ return oauthLogins.status(flowId);
172
+ },
173
+ cancelMcpOAuthLogin(flowId) {
174
+ return oauthLogins.cancel(flowId);
175
+ },
176
+ /** Remote / headless sign-in: complete the pending flow with the redirect
177
+ * URL pasted from the browser. `{ flowId, state: 'complete' | 'failed',
178
+ * error? }`; an invalid paste throws a fixed message and stays pending. */
179
+ completeMcpOAuthLogin(flowId, callbackUrl) {
180
+ return oauthLogins.complete(flowId, callbackUrl);
181
+ },
182
+ /** Forget the server's stored OAuth credentials (shared by every server
183
+ * with the same exact URL) and reconnect without a login, here and on
184
+ * peers, so it reports sign-in required. */
185
+ async signOutMcpServer(name) {
186
+ const { serverName, cfg } = await oauthServerConfig(name);
187
+ // A begin issued meanwhile waits until the credentials are gone.
188
+ return oauthLogins.cancelServer(serverName, async () => {
189
+ await clearMcpServerOAuth(cfg);
190
+ return sync.reconnectMcpAndAnnounce({ only: serverName, enabled: cfg.enabled !== false });
191
+ });
192
+ },
193
+ /** `{ auth: 'oauth' | 'none' | 'configured' | 'unreachable', error? }` for an
194
+ * HTTP/SSE config, without credentials or a browser. */
195
+ probeMcpServerAuth(cfg) {
196
+ if (!cfg || typeof cfg !== 'object' || Array.isArray(cfg)) throw new TypeError('MCP server config is required');
197
+ const probe = {};
198
+ for (const key of ['type', 'url', 'headers', 'bearer_token_env_var', 'env_http_headers']) {
199
+ if (cfg[key] !== undefined) probe[key] = cfg[key];
200
+ }
201
+ if (probe.type !== 'http' && probe.type !== 'sse') throw new TypeError("type must be 'http' or 'sse'");
202
+ return probeMcpServerAuth(probe);
203
+ },
118
204
  async addMcpServer(input = {}) {
119
205
  const { name, config: serverConfig } = normalizeMcpServerInput(input);
120
206
  const servers = userServers();
@@ -162,9 +248,19 @@ export function createMcpResourceApi({ deps, sync, decorate }) {
162
248
  refusePluginServer(serverName);
163
249
  throw new Error(`MCP server not configured: ${serverName}`);
164
250
  }
251
+ const removed = servers[serverName];
165
252
  delete servers[serverName];
166
253
  saveServers(servers);
167
- return sync.reconnectMcpAndAnnounce({ drop: [serverName] });
254
+ const status = await sync.reconnectMcpAndAnnounce({ drop: [serverName] });
255
+ // A removed server keeps no OAuth tokens or client registration, unless
256
+ // another configured server (plugin or disabled ones included, even
257
+ // with MCP disabled for this runtime) still uses them through the same
258
+ // exact URL.
259
+ const url = oauthUrlOf(removed);
260
+ if (url && !Object.values(resolveConfiguredMcpCatalog().servers).some((cfg) => oauthUrlOf(cfg) === url)) {
261
+ await clearMcpServerOAuth(removed);
262
+ }
263
+ return status;
168
264
  },
169
265
  async setMcpServerEnabled(name, enabled) {
170
266
  const serverName = clean(name);
@@ -14,8 +14,13 @@ function listOf(status, key) {
14
14
  }
15
15
 
16
16
  export function createScopeDecorators({ getConfig, getCurrentCwd }) {
17
- function scopeInfo(kind, name, pluginId = '', cwd = getCurrentCwd()) {
18
- const scopes = extensionScopesFromConfig(getConfig());
17
+ function scopeInfo(
18
+ kind,
19
+ name,
20
+ pluginId = '',
21
+ cwd = getCurrentCwd(),
22
+ scopes = extensionScopesFromConfig(getConfig())
23
+ ) {
19
24
  const scope = extensionScopeProjects(scopes, kind, name);
20
25
  const inheritedScope = pluginId ? extensionScopeProjects(scopes, 'plugins', pluginId) : null;
21
26
  const activeHere =
@@ -35,11 +40,13 @@ export function createScopeDecorators({ getConfig, getCurrentCwd }) {
35
40
  },
36
41
  /** `cwd`: decide `activeHere` for that folder instead of the current one. */
37
42
  skills(status, cwd = getCurrentCwd()) {
43
+ // One scope read for the whole list, not one per skill.
44
+ const scopes = extensionScopesFromConfig(getConfig());
38
45
  return {
39
46
  ...status,
40
47
  skills: listOf(status, 'skills').map((skill) => ({
41
48
  ...skill,
42
- ...scopeInfo('skills', skill.name, skill?.owner?.kind === 'plugin' ? clean(skill.owner.id) : '', cwd),
49
+ ...scopeInfo('skills', skill.name, skill?.owner?.kind === 'plugin' ? clean(skill.owner.id) : '', cwd, scopes),
43
50
  })),
44
51
  };
45
52
  },
@@ -1,19 +1,34 @@
1
1
  import { registerCacheInvalidationListener } from '../runtime/agent/orchestrator/tools/builtin/cache-layers.mjs';
2
2
  import { turnReviewReply } from '../runtime/shared/turn-review-reply.mjs';
3
3
  import {
4
+ clearSessionChangeHistory,
4
5
  getSessionReviewDiff,
6
+ getSessionReviewFilePatch,
5
7
  getTurnChanges,
6
8
  getTurnReviewDiff,
9
+ getTurnReviewFilePatch,
7
10
  reapplyTurnChanges,
8
11
  revertTurnChanges,
9
12
  revertTurnReview,
10
13
  revertTurnReviewFile,
11
14
  } from '../runtime/shared/turn-snapshot.mjs';
12
15
  import { noteTurnWorktreeChange } from '../runtime/shared/turn-worktree-snapshot.mjs';
16
+ import { forgetSessionChangeHistoryMarker } from '../runtime/shared/turn-snapshot-store.mjs';
17
+ import { forgetSessionBaselines } from '../runtime/shared/session-baseline-store.mjs';
18
+ import { registerSessionPurgeHook } from '../runtime/agent/orchestrator/session/store.mjs';
19
+
20
+ // A deleted history stays deleted for as long as its session exists; the
21
+ // session's own deletion takes the marker — and its stored first-seen file
22
+ // contents — with it.
23
+ registerSessionPurgeHook((sessionId) => {
24
+ void forgetSessionChangeHistoryMarker(sessionId);
25
+ void forgetSessionBaselines(sessionId);
26
+ });
13
27
 
14
28
  // Tool writes (apply_patch, mutating shell commands, git, watcher events)
15
- // reach the live review snapshot as its change signal: a review poll right
16
- // after them captures the worktree, an unsignaled poll may reuse the last one.
29
+ // reach the turn's worktree snapshot as its change signal: a session review
30
+ // read right after them captures the worktree, an unsignaled one may reuse
31
+ // the last capture.
17
32
  registerCacheInvalidationListener((paths) => noteTurnWorktreeChange(paths));
18
33
 
19
34
  export function createRuntimeReviewApi({ getCwd, getSessionId }) {
@@ -23,6 +38,9 @@ export function createRuntimeReviewApi({ getCwd, getSessionId }) {
23
38
  getTurnReviewDiff: (options = {}) =>
24
39
  turnReviewReply((reviewOptions) => getTurnReviewDiff(getCwd(), getSessionId(), reviewOptions), options),
25
40
  getSessionReviewDiff: () => getSessionReviewDiff(getCwd(), getSessionId()),
41
+ // One listed file's whole patch (a reply lists a large one `patchOmitted`).
42
+ getSessionReviewFilePatch: (file, oldPath) => getSessionReviewFilePatch(getCwd(), getSessionId(), file, oldPath),
43
+ getTurnReviewFilePatch: (file) => getTurnReviewFilePatch(getCwd(), getSessionId(), file),
26
44
  revertTurnReview: (checkpointId) => revertTurnReview(getCwd(), getSessionId(), checkpointId),
27
45
  revertTurnReviewFile: (file, checkpointId) => revertTurnReviewFile(getCwd(), getSessionId(), file, checkpointId),
28
46
  // Historical per-turn changes, addressed by checkpointId (TurnChangesReply).
@@ -31,5 +49,6 @@ export function createRuntimeReviewApi({ getCwd, getSessionId }) {
31
49
  revertTurnChanges(getSessionId(), checkpointId, file, revision),
32
50
  reapplyTurnChanges: (checkpointId, file, revision) =>
33
51
  reapplyTurnChanges(getSessionId(), checkpointId, file, revision),
52
+ clearSessionChangeHistory: () => clearSessionChangeHistory(getSessionId()),
34
53
  };
35
54
  }
@@ -20,6 +20,7 @@ import { registerJsonProjection } from '../../../runtime/shared/pending-json-pro
20
20
  import { sleep } from '../../../runtime/shared/sleep.mjs';
21
21
 
22
22
  const RETRY_DELAYS_MS = [50, 250, 1000];
23
+ const RETRY_AFTER_FAILURE_MS = 15_000;
23
24
  const unsettled = new Set(); // queues holding unpersisted writes
24
25
  // Exit is the one place a bounded synchronous lock wait is acceptable: the
25
26
  // loop is gone, and a dropped settlement would leave rows "running" forever.
@@ -122,8 +123,15 @@ function replayBatch(batch, args, mergeSet) {
122
123
  replayRun();
123
124
  }
124
125
 
126
+ // A write that cannot reach disk loses a state change other processes rely on
127
+ // (e.g. a deleted Lead row that never leaves the pool), so every failure is
128
+ // reported. In the daemon stderr IS daemon.log (daemon-log.mjs installRedirect).
125
129
  function reportFailure(file, what, error) {
126
- process.stderr.write(`[index-write] ${file}: ${what}: ${error?.message || error}\n`);
130
+ try {
131
+ process.stderr.write(`[index-write] ${file}: ${what}: ${error?.message || error}\n`);
132
+ } catch {
133
+ /* logging is best effort */
134
+ }
127
135
  }
128
136
 
129
137
  /**
@@ -151,9 +159,15 @@ export function createIndexWriteQueue({
151
159
  let pending = []; // op sets not yet handed to a job
152
160
  let inflight = []; // op sets of the running job
153
161
  let running = null;
162
+ const failures = new WeakMap(); // settled job → the error that failed it
154
163
  let timer = null;
164
+ let retryTimer = null;
155
165
 
156
166
  function clearTimer() {
167
+ if (retryTimer) {
168
+ clearTimeout(retryTimer);
169
+ retryTimer = null;
170
+ }
157
171
  if (!timer) return;
158
172
  clearImmediate(timer);
159
173
  timer = null;
@@ -173,8 +187,8 @@ export function createIndexWriteQueue({
173
187
  return;
174
188
  } catch (error) {
175
189
  if (attempt >= RETRY_DELAYS_MS.length) {
176
- reportFailure(file, `dropped ${batch.length} unpersisted write(s)`, error);
177
- return;
190
+ reportFailure(file, `${batch.length} unpersisted write(s) kept queued after retries`, error);
191
+ throw error;
178
192
  }
179
193
  await sleep(RETRY_DELAYS_MS[attempt]);
180
194
  }
@@ -187,23 +201,45 @@ export function createIndexWriteQueue({
187
201
  inflight = pending;
188
202
  pending = [];
189
203
  const batch = inflight;
190
- running = persist(batch).then(() => {
191
- inflight = [];
192
- running = null;
193
- onPersisted();
194
- if (pending.length === 0) {
195
- projection = null;
196
- unsettled.delete(self);
204
+ const job = persist(batch).then(
205
+ () => {
206
+ inflight = [];
207
+ running = null;
208
+ onPersisted();
209
+ if (pending.length === 0) {
210
+ projection = null;
211
+ unsettled.delete(self);
212
+ }
213
+ schedule();
214
+ },
215
+ (error) => {
216
+ // Persistent failure: nothing reached disk. Requeue the batch ahead of
217
+ // newer writes (the projection and `unsettled` keep covering it) so a
218
+ // later flush, write or exit flush retries. Do not reschedule at once,
219
+ // a held foreign lock would otherwise be hammered; a slow unref'd retry
220
+ // keeps a failed LAST write (a delete) from waiting for unrelated traffic.
221
+ failures.set(job, error);
222
+ pending = [...batch, ...pending];
223
+ inflight = [];
224
+ running = null;
225
+ retryTimer = setTimeout(() => {
226
+ retryTimer = null;
227
+ schedule();
228
+ }, RETRY_AFTER_FAILURE_MS);
229
+ retryTimer.unref?.();
197
230
  }
198
- schedule();
199
- });
231
+ );
232
+ running = job;
200
233
  }
201
234
 
202
- /** Resolves once everything written so far is on disk (or dropped). */
235
+ /** Resolves once everything written so far is on disk; rejects when a persist
236
+ * failed for good (the writes stay queued for a later flush). */
203
237
  async function flush() {
204
238
  for (;;) {
205
239
  if (running) {
206
- await running;
240
+ const job = running;
241
+ await job;
242
+ if (failures.has(job)) throw failures.get(job);
207
243
  continue;
208
244
  }
209
245
  if (pending.length === 0) return;
@@ -212,10 +248,16 @@ export function createIndexWriteQueue({
212
248
  }
213
249
  }
214
250
 
215
- /** Exit path: persist inflight + pending ops synchronously (bounded lock wait). */
251
+ /** Persist pending ops synchronously (bounded lock wait). While an async job
252
+ * runs it owns the lock (and its ops are in flight): never wait on it, take
253
+ * over its lock, or replay its ops — report false and let that job and its
254
+ * follow-ups drain. At the last-resort process 'exit' hook that is
255
+ * best-effort: the graceful shutdown path drains before exit. */
216
256
  function flushSync() {
217
- const ops = [...inflight, ...pending];
218
- if (!file || ops.length === 0) return true;
257
+ if (!file) return true;
258
+ if (running) return false;
259
+ const ops = pending;
260
+ if (ops.length === 0) return true;
219
261
  clearTimer();
220
262
  pending = [];
221
263
  try {
@@ -225,10 +267,10 @@ export function createIndexWriteQueue({
225
267
  });
226
268
  } catch (error) {
227
269
  reportFailure(file, `synchronous flush of ${ops.length} write(s) failed; kept queued`, error);
228
- pending = ops;
270
+ pending = [...ops, ...pending];
271
+ schedule();
229
272
  return false;
230
273
  }
231
- inflight = [];
232
274
  projection = null;
233
275
  unsettled.delete(self);
234
276
  onPersisted();
@@ -251,9 +293,11 @@ export function createIndexWriteQueue({
251
293
  version += 1;
252
294
  pending.push(rerun ? mutator : ops);
253
295
  unsettled.add(self);
296
+ installProcessExitFlush();
254
297
  schedule();
255
298
  return next;
256
- } catch {
299
+ } catch (error) {
300
+ reportFailure(file, 'write rejected (mutator or document rewrite threw); nothing queued', error);
257
301
  return null;
258
302
  }
259
303
  },
@@ -266,6 +310,23 @@ export function createIndexWriteQueue({
266
310
  };
267
311
  }
268
312
 
313
+ let processExitFlushInstalled = false;
314
+
315
+ /** The process owns last-resort exit flushing of every queue holding unpersisted
316
+ * writes, so a disposed (e.g. evicted) runtime needs no exit callback of its
317
+ * own. Best effort: a persist still running is left to the graceful drain. */
318
+ function installProcessExitFlush() {
319
+ if (processExitFlushInstalled) return;
320
+ processExitFlushInstalled = true;
321
+ process.on('exit', () => {
322
+ try {
323
+ flushAllIndexWritesSync();
324
+ } catch {
325
+ /* exit flush is best effort */
326
+ }
327
+ });
328
+ }
329
+
269
330
  /** Synchronous variant (exit paths, tests that read the file directly). */
270
331
  export function flushAllIndexWritesSync() {
271
332
  for (const queue of [...unsettled]) queue.flushSync();
@@ -19,7 +19,7 @@
19
19
  // Every call is idempotent (the first terminal state wins, so the outer reject
20
20
  // path cannot double-notify) and absorbs its own errors, so reporting on a
21
21
  // turn can never break the turn.
22
- import { reconcileBackgroundTask } from '../../../runtime/shared/background-tasks.mjs';
22
+ import { reconcileBackgroundTask, settleCancelledBackgroundTask } from '../../../runtime/shared/background-tasks.mjs';
23
23
 
24
24
  function reconcileJobTerminalResult(job, value) {
25
25
  if (!job?.taskId) return;
@@ -50,6 +50,8 @@ export function terminalResultHook({ job, turnReview, completionValue, notifyEar
50
50
  turnReview.complete();
51
51
  const value = completionValue(terminalResult);
52
52
  job._terminalResultValue = value;
53
+ // A cancelled job reports once, as `cancelled`, when its turn settles.
54
+ if (job.status === 'cancelled') return;
53
55
  notifyEarly(job, value, notifyContext || {});
54
56
  reconcileJobTerminalResult(job, value);
55
57
  };
@@ -67,6 +69,16 @@ export function reconcileJobWatchdogPartial(job, value) {
67
69
  } catch {}
68
70
  }
69
71
 
72
+ /** The cancelled turn stopped: deliver the owner's single `cancelled`
73
+ * notification, carrying the output the turn produced before it stopped
74
+ * (header-only when it produced none). */
75
+ export function reconcileJobCancelled(job, value) {
76
+ if (!job?.taskId) return;
77
+ try {
78
+ settleCancelledBackgroundTask(job.taskId, value?.content ? { result: value } : {});
79
+ } catch {}
80
+ }
81
+
70
82
  export function reconcileJobStreamStalled(job, error) {
71
83
  if (!job?.taskId || job._terminalResultValue !== undefined) return;
72
84
  try {
@@ -5,6 +5,8 @@ import { ACTIVE_STAGES } from '../tool-def.mjs';
5
5
  import { isTerminalWorkerStatus } from '../worker-rows.mjs';
6
6
  import { sessionUsageTotals } from '../../../../runtime/shared/session-usage-totals.mjs';
7
7
 
8
+ const CANCELLED_WORKER_STATUS = /^(?:cancelled|canceled|killed|cancel[-_\s]?(?:unconfirmed|pending))$/;
9
+
8
10
  // Idle, closed, errored and reaped/unknown rows are history and stay reachable
9
11
  // through the task section (status/read keep their terminal result).
10
12
  export function isActiveWorkerRow(row = {}) {
@@ -14,8 +16,11 @@ export function isActiveWorkerRow(row = {}) {
14
16
  const status = String(row.status ?? '')
15
17
  .trim()
16
18
  .toLowerCase();
17
- if (ACTIVE_STAGES.has(stage) || ACTIVE_STAGES.has(status)) return true;
18
- const effective = stage || status;
19
+ // `status` decides; the stage is the runtime phase and only stands in for a
20
+ // row with no status. A cancel in either field is not work.
21
+ if (CANCELLED_WORKER_STATUS.test(stage) || CANCELLED_WORKER_STATUS.test(status)) return false;
22
+ const effective = status || stage;
23
+ if (ACTIVE_STAGES.has(effective)) return true;
19
24
  if (!effective || effective === 'unknown') return false;
20
25
  return !isTerminalWorkerStatus(effective);
21
26
  }
@@ -0,0 +1,29 @@
1
+ // Ids of deleted Leads, shared by every lead-index instance of the process that
2
+ // uses one data dir. The delete runs in the control runtime while the deleted
3
+ // session's own (still loaded) runtime keeps settling turns through ITS index
4
+ // instance; a per-instance set never sees the delete, so that late idle upsert
5
+ // wrote the row back. The store's write fence (explicit deletes) is consulted
6
+ // as well, so a fenced id can never be added whichever instance asks.
7
+ import { resolve } from 'node:path';
8
+ import { isSessionWriteFenced } from '../../../../runtime/agent/orchestrator/session/store/live-state.mjs';
9
+
10
+ const FORGOTTEN_LEADS_MAX = 1024;
11
+ const registries = new Map(); // resolved data dir -> Set<sessionId>
12
+
13
+ export function createForgottenLeads(dataDir) {
14
+ const key = dataDir ? resolve(dataDir) : '';
15
+ let ids = registries.get(key);
16
+ if (!ids) {
17
+ ids = new Set();
18
+ registries.set(key, ids);
19
+ }
20
+ return {
21
+ /** A deleted Lead must never be written to the index again. */
22
+ forget(sessionId) {
23
+ ids.delete(sessionId);
24
+ ids.add(sessionId);
25
+ if (ids.size > FORGOTTEN_LEADS_MAX) ids.delete(ids.values().next().value);
26
+ },
27
+ isForgotten: (sessionId) => ids.has(sessionId) || isSessionWriteFenced(sessionId),
28
+ };
29
+ }
@@ -42,7 +42,7 @@ export function createLeadIndexFile({ dataDir }) {
42
42
  return parsed ? normalizeLeadRows(parsed) : [];
43
43
  }
44
44
 
45
- const write = (mutator) => queue.write(mutator);
45
+ const write = (mutator, options) => queue.write(mutator, options);
46
46
 
47
47
  return { path, read, write, flush: queue.flush, flushSync: queue.flushSync };
48
48
  }