mixdog 1.2.0 → 1.2.2

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 (386) hide show
  1. package/README.md +7 -5
  2. package/package.json +1 -1
  3. package/scripts/gate-local.mjs +19 -3
  4. package/scripts/model-catalog-audit.mjs +1 -15
  5. package/src/agents/reviewer/AGENT.md +3 -3
  6. package/src/agents/reviewer/agent.json +1 -1
  7. package/src/defaults/shipped-history.json +5 -0
  8. package/src/defaults/skills/pptx/SKILL.md +6 -6
  9. package/src/defaults/skills/pptx/references/review.md +6 -4
  10. package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
  11. package/src/defaults/skills/setup/references/actions.md +13 -3
  12. package/src/defaults/skills/visualize/SKILL.md +12 -9
  13. package/src/repl/slash-commands.mjs +16 -1
  14. package/src/rules/shared/60-verification.md +3 -1
  15. package/src/rules/shared/70-delivery.md +4 -2
  16. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
  17. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
  18. package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
  19. package/src/runtime/agent/orchestrator/config.mjs +10 -4
  20. package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
  21. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
  22. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
  23. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +122 -15
  24. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
  25. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
  26. package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
  27. package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
  28. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
  29. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
  30. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
  31. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
  32. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
  33. package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
  34. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
  35. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
  36. package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
  37. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
  38. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
  39. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
  40. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -0
  41. package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
  42. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
  43. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +25 -21
  44. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
  45. package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
  46. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
  49. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
  50. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
  51. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
  52. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +73 -35
  53. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
  54. package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
  55. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +8 -1
  56. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
  57. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
  58. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
  59. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +30 -14
  60. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
  61. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
  62. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
  63. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
  64. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
  65. package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
  66. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +447 -0
  67. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
  68. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  69. package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
  70. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +102 -23
  71. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
  73. package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
  74. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
  75. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
  76. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
  77. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
  78. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -0
  79. package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
  80. package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
  81. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
  82. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
  83. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +21 -82
  84. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
  85. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
  86. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
  87. package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
  88. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  89. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
  90. package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
  91. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
  92. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
  93. package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
  94. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
  95. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
  96. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
  97. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
  98. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
  103. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
  104. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
  108. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -1
  112. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
  113. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
  114. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
  115. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
  116. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
  117. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
  119. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +18 -11
  120. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -2
  121. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
  122. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +2 -3
  123. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
  125. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +34 -3
  126. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
  127. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
  128. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
  129. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
  130. package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
  132. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
  133. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
  134. package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
  135. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
  136. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
  137. package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
  138. package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
  139. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -219
  140. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
  141. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
  142. package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
  143. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
  146. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
  147. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
  148. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
  149. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
  150. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +268 -181
  151. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
  152. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
  153. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
  154. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
  155. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -0
  156. package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
  157. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
  158. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
  159. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
  160. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
  161. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
  162. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
  163. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
  164. package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
  165. package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
  166. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
  167. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
  169. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
  170. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
  171. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
  172. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
  173. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
  174. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
  175. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
  176. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
  177. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
  178. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
  179. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
  180. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
  181. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
  182. package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
  183. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
  184. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
  185. package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
  186. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
  187. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
  188. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
  189. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
  190. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +819 -0
  191. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
  192. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -12
  193. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
  194. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
  195. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
  196. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
  197. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +41 -3
  198. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
  199. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
  200. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
  201. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
  202. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
  203. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
  205. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
  206. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
  207. package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
  208. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
  209. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
  210. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
  211. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
  212. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
  213. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
  214. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
  215. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
  216. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
  217. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
  218. package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
  219. package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
  220. package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
  221. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
  222. package/src/runtime/attachments/store.d.mts +3 -0
  223. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
  224. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
  225. package/src/runtime/channels/lib/worker-main.mjs +17 -14
  226. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
  227. package/src/runtime/effort-judge/judge-client.mjs +56 -18
  228. package/src/runtime/memory/lib/memory.mjs +1 -1
  229. package/src/runtime/memory/lib/pg/process.mjs +34 -24
  230. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
  231. package/src/runtime/memory/lib/session-ingest.mjs +2 -2
  232. package/src/runtime/office/README.md +1 -1
  233. package/src/runtime/office/shared/values.mjs +0 -5
  234. package/src/runtime/shared/atomic-file.mjs +25 -4
  235. package/src/runtime/shared/background-tasks.mjs +92 -14
  236. package/src/runtime/shared/err-text.mjs +25 -0
  237. package/src/runtime/shared/error-presentation.mjs +159 -19
  238. package/src/runtime/shared/extension-scopes.mjs +5 -3
  239. package/src/runtime/shared/file-lock.mjs +37 -11
  240. package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
  241. package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
  242. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
  243. package/src/runtime/shared/llm/model-catalog.mjs +53 -52
  244. package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
  245. package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
  246. package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
  247. package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
  248. package/src/runtime/shared/model-display.mjs +13 -0
  249. package/src/runtime/shared/plugin-manifest.mjs +18 -9
  250. package/src/runtime/shared/pristine-execution-contract.json +9 -2
  251. package/src/runtime/shared/pristine-execution.mjs +28 -4
  252. package/src/runtime/shared/provider-accounts.mjs +124 -20
  253. package/src/runtime/shared/provider-api-key.mjs +12 -0
  254. package/src/runtime/shared/quota-resume-store.mjs +11 -0
  255. package/src/runtime/shared/session-baseline-store.mjs +960 -0
  256. package/src/runtime/shared/shell-display.mjs +9 -3
  257. package/src/runtime/shared/skill-mentions.d.mts +10 -0
  258. package/src/runtime/shared/skill-mentions.mjs +133 -0
  259. package/src/runtime/shared/skill-script-runtime.mjs +264 -0
  260. package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
  261. package/src/runtime/shared/task-notification-envelope.mjs +2 -2
  262. package/src/runtime/shared/tool-primitives.mjs +35 -2
  263. package/src/runtime/shared/turn-changes.mjs +447 -219
  264. package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
  265. package/src/runtime/shared/turn-snapshot.mjs +170 -48
  266. package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
  267. package/src/runtime/shared/worker-requests.mjs +15 -2
  268. package/src/runtime/shared/worktrees/contract.mjs +0 -24
  269. package/src/runtime/shared/worktrees/test-support.mjs +19 -4
  270. package/src/session-runtime/automation-agents.mjs +8 -2
  271. package/src/session-runtime/boot/apis.mjs +61 -0
  272. package/src/session-runtime/boot/config.mjs +5 -2
  273. package/src/session-runtime/boot/facade.mjs +1 -0
  274. package/src/session-runtime/boot/infrastructure.mjs +35 -18
  275. package/src/session-runtime/conversation-import/discovery.mjs +698 -0
  276. package/src/session-runtime/conversation-import/service.mjs +369 -0
  277. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
  278. package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
  279. package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
  280. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  281. package/src/session-runtime/mcp-glue/connect.mjs +83 -16
  282. package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
  283. package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
  284. package/src/session-runtime/mcp-glue.mjs +25 -2
  285. package/src/session-runtime/mcp-oauth-login.mjs +174 -0
  286. package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
  287. package/src/session-runtime/model-route/set-route.mjs +83 -15
  288. package/src/session-runtime/model-route/web-search-route.mjs +1 -1
  289. package/src/session-runtime/native-web-search/routes.mjs +22 -3
  290. package/src/session-runtime/new-session-config.mjs +3 -2
  291. package/src/session-runtime/notification-bus.mjs +9 -2
  292. package/src/session-runtime/provider-auth/accounts.mjs +33 -15
  293. package/src/session-runtime/provider-models/model-meta.mjs +12 -3
  294. package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
  295. package/src/session-runtime/provider-readiness.mjs +16 -10
  296. package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
  297. package/src/session-runtime/quick-web-search-models.mjs +13 -38
  298. package/src/session-runtime/resource-extension-sync.mjs +24 -5
  299. package/src/session-runtime/resource-mcp-api.mjs +198 -78
  300. package/src/session-runtime/resource-plugins-api.mjs +29 -41
  301. package/src/session-runtime/resource-scope-decorate.mjs +6 -8
  302. package/src/session-runtime/resource-skills-api.mjs +23 -2
  303. package/src/session-runtime/runtime-review-api.mjs +13 -0
  304. package/src/session-runtime/schedule-session-run.mjs +1 -1
  305. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
  306. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
  307. package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
  308. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
  309. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
  310. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
  311. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
  312. package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
  313. package/src/session-runtime/services/channel-session-router.mjs +4 -1
  314. package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
  315. package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
  316. package/src/session-runtime/services/provider-admin.mjs +64 -18
  317. package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
  318. package/src/session-runtime/settings-compaction-api.mjs +1 -0
  319. package/src/session-runtime/setup-tool/executor.mjs +12 -1
  320. package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
  321. package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
  322. package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
  323. package/src/session-runtime/skills-api.mjs +7 -3
  324. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  325. package/src/session-runtime/webhook-session-run.mjs +16 -4
  326. package/src/skill-script-entry.mjs +36 -0
  327. package/src/standalone/daemon-drain-policy.mjs +8 -0
  328. package/src/standalone/daemon-stored-session-views.mjs +11 -3
  329. package/src/standalone/daemon-telemetry.mjs +55 -0
  330. package/src/standalone/daemon.mjs +44 -11
  331. package/src/standalone/session-protocol.mjs +12 -0
  332. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
  333. package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
  334. package/src/standalone/session-service/agent-tree.mjs +12 -0
  335. package/src/standalone/session-service/quota-resume.mjs +8 -0
  336. package/src/standalone/session-service/retention/busy.mjs +15 -1
  337. package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
  338. package/src/standalone/session-service-api.mjs +5 -0
  339. package/src/standalone/session-service.mjs +1 -0
  340. package/src/tui/App.jsx +9 -1
  341. package/src/tui/app/app-view/floating-panel.jsx +9 -1
  342. package/src/tui/app/app-view.jsx +7 -0
  343. package/src/tui/app/create-app-pickers.mjs +4 -0
  344. package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
  345. package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
  346. package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
  347. package/src/tui/app/extension-pickers.mjs +2 -1
  348. package/src/tui/app/model-options.mjs +13 -16
  349. package/src/tui/app/skill-mention-palette.mjs +88 -0
  350. package/src/tui/app/slash-commands.mjs +7 -2
  351. package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
  352. package/src/tui/app/slash-palette.mjs +23 -7
  353. package/src/tui/app/transcript-row-estimate.mjs +11 -3
  354. package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
  355. package/src/tui/app/use-prompt-state.mjs +5 -0
  356. package/src/tui/components/Message.jsx +22 -1
  357. package/src/tui/components/PromptInput.jsx +21 -3
  358. package/src/tui/components/SlashCommandPalette.jsx +12 -3
  359. package/src/tui/components/StatusLine.jsx +2 -0
  360. package/src/tui/components/TranscriptItem.jsx +9 -1
  361. package/src/tui/components/prompt-input/key-handler.mjs +21 -8
  362. package/src/tui/components/status-line/local-line.mjs +5 -2
  363. package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
  364. package/src/tui/components/user-message-skills.mjs +38 -0
  365. package/src/tui/dist/index.mjs +1323 -214
  366. package/src/tui/session/queue-helpers.mjs +7 -2
  367. package/src/tui/session/quota-resume.mjs +46 -14
  368. package/src/tui/session/session-api/commands.mjs +33 -24
  369. package/src/tui/session/session-api/extensions.mjs +26 -2
  370. package/src/tui/session/session-api/integrations.mjs +7 -0
  371. package/src/tui/session/session-api/lifecycle.mjs +5 -1
  372. package/src/tui/session/session-api/routes.mjs +71 -7
  373. package/src/tui/session/session-api/settings.mjs +12 -14
  374. package/src/tui/session/session-flow/drain.mjs +21 -5
  375. package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
  376. package/src/tui/session/tui-steering-persist.mjs +25 -9
  377. package/src/tui/session/turn.mjs +55 -15
  378. package/src/tui/statusline-ansi-bridge.mjs +1 -1
  379. package/src/ui/statusline-agents.mjs +15 -4
  380. package/src/ui/statusline.mjs +7 -3
  381. package/src/ui/streaming-markdown-heal.mjs +34 -3
  382. package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
  383. package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
  384. package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
  385. package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
  386. package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
@@ -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
  }
@@ -1,12 +1,14 @@
1
1
  import {
2
2
  resolveAgentWatchdogPolicy,
3
3
  resolveHandoffMessageStartIndex,
4
+ turnPartialHandoff,
4
5
  watchdogPartialHandoffFromError,
5
6
  watchdogStoppedHandoff,
6
7
  } from '../../../runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs';
7
8
  import { clean, normalizeAgentName, resolvePrompt } from './helpers.mjs';
8
9
  import { abnormalEmptyFinishError, renderResult } from './render.mjs';
9
10
  import {
11
+ reconcileJobCancelled,
10
12
  reconcileJobFinally,
11
13
  reconcileJobStreamStalled,
12
14
  reconcileJobWatchdogPartial,
@@ -93,6 +95,18 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
93
95
  turnStartedAt: new Date().toISOString(),
94
96
  });
95
97
  let handoffMsgStart = 0;
98
+ // A cancelled turn reports the output it produced before it stopped.
99
+ const settleCancelled = (error, result = null) => {
100
+ finalStatus = 'cancelled';
101
+ reconcileJobCancelled(job, {
102
+ tag,
103
+ sessionId,
104
+ agent: session.agent || null,
105
+ provider: session.provider,
106
+ model: session.model,
107
+ content: turnPartialHandoff(error, mgr.getSession(sessionId), handoffMsgStart) || result?.content || '',
108
+ });
109
+ };
96
110
  try {
97
111
  handoffMsgStart = resolveHandoffMessageStartIndex(mgr.getSession(sessionId));
98
112
  const turnHooks = buildTurnHooks({ sessionId, notifyContext, job, turnReview, completionValue });
@@ -100,6 +114,10 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
100
114
  // Early preview no longer suppresses the canonical body notification;
101
115
  // notifyTaskCompletion fires once with output via resolve/reconcile.
102
116
  const finalValue = completionValue(result);
117
+ if (job?.status === 'cancelled') {
118
+ settleCancelled(null, result);
119
+ return finalValue;
120
+ }
103
121
  if (finalValue.error) {
104
122
  finalStatus = 'error';
105
123
  if (job) job._terminalResultValue = finalValue;
@@ -107,6 +125,10 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
107
125
  }
108
126
  return finalValue;
109
127
  } catch (error) {
128
+ if (job?.status === 'cancelled') {
129
+ settleCancelled(error);
130
+ throw error;
131
+ }
110
132
  const partial = watchdogPartialHandoffFromError(error, mgr.getSession(sessionId), handoffMsgStart);
111
133
  if (partial) {
112
134
  finalStatus = 'idle';
@@ -123,10 +145,6 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
123
145
  reconcileJobWatchdogPartial(job, value);
124
146
  return value;
125
147
  }
126
- if (job?.status === 'cancelled') {
127
- finalStatus = 'cancelled';
128
- throw error;
129
- }
130
148
  finalStatus = 'error';
131
149
  reconcileJobStreamStalled(job, error);
132
150
  throw error;
@@ -44,6 +44,8 @@ export function createJobStarter({ mgr, notifyStatusChange, notifySessionComplet
44
44
  meta: jobMeta,
45
45
  resultType: 'agent_task_result',
46
46
  renderResult: (result) => renderResult(result),
47
+ // Cancellation reaches the owner once, with the worker's partial output.
48
+ notifyOnCancel: true,
47
49
  cancel: () => {
48
50
  try {
49
51
  admissionController.abort(new Error('agent task cancelled before resource admission'));
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { createNotify } from '../notify.mjs';
8
8
  import {
9
+ reconcileJobCancelled,
9
10
  reconcileJobFinally,
10
11
  reconcileJobStreamStalled,
11
12
  reconcileJobWatchdogPartial,
@@ -15,11 +16,13 @@ import { abnormalEmptyFinishError } from '../render.mjs';
15
16
  import { createProgressWatchdogRegistry } from '../../agent-watchdog-registry.mjs';
16
17
  import {
17
18
  resolveHandoffMessageStartIndex,
19
+ turnPartialHandoff,
18
20
  watchdogPartialHandoffFromError,
19
21
  watchdogStoppedHandoff,
20
22
  } from '../../../../runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs';
21
23
  import { saveSessionAsync } from '../../../../runtime/agent/orchestrator/session/store.mjs';
22
24
  import { presetDescriptor } from './spawn-prep.mjs';
25
+ import { workerStageForStatus } from '../worker-rows.mjs';
23
26
 
24
27
  // Mid-turn worker persistence cadence. The watchdog sweep runs every second;
25
28
  // a transcript save is far more expensive than a bookkeeping stamp, so the
@@ -68,7 +71,7 @@ export function createSpawnRunner({
68
71
  const messages = Number(progress?.messages) || 0;
69
72
  upsertWorkerSessionDeferred(session, tag, {
70
73
  status: 'running',
71
- stage: progress.stage || 'running',
74
+ stage: workerStageForStatus('running', progress.stage),
72
75
  ...(messages > 0 ? { messages } : {}),
73
76
  });
74
77
  // The canonical runtime owns persistence; this session is only its descriptor.
@@ -135,6 +138,16 @@ export function createSpawnRunner({
135
138
  });
136
139
  notifyStatusChange();
137
140
  let handoffMsgStart = 0;
141
+ // A cancelled turn reports the output it produced before it stopped.
142
+ const settleCancelled = (error, result = null) => {
143
+ finalStatus = 'cancelled';
144
+ reconcileJobCancelled(job, {
145
+ tag,
146
+ sessionId: session.id,
147
+ ...presetDescriptor(agent, preset, presetName),
148
+ content: turnPartialHandoff(error, mgr.getSession(session.id), handoffMsgStart) || result?.content || '',
149
+ });
150
+ };
138
151
  try {
139
152
  handoffMsgStart = resolveHandoffMessageStartIndex(mgr.getSession(session.id));
140
153
  const turnHooks = {
@@ -157,6 +170,10 @@ export function createSpawnRunner({
157
170
  // notifyTaskCompletion is left to fire exactly once with output via the
158
171
  // resolve/reconcile/finally path.
159
172
  const finalValue = completionValue(result);
173
+ if (job?.status === 'cancelled') {
174
+ settleCancelled(null, result);
175
+ return finalValue;
176
+ }
160
177
  // Non-job return path (or job path where the terminal-result reconcile
161
178
  // already ran): if the finish was abnormal-empty, surface it as a thrown
162
179
  // error so finalStatus becomes 'error' and the caller's error path (and
@@ -168,6 +185,10 @@ export function createSpawnRunner({
168
185
  }
169
186
  return finalValue;
170
187
  } catch (error) {
188
+ if (job?.status === 'cancelled') {
189
+ settleCancelled(error);
190
+ throw error;
191
+ }
171
192
  const partial = watchdogPartialHandoffFromError(error, mgr.getSession(session.id), handoffMsgStart);
172
193
  if (partial) {
173
194
  finalStatus = 'idle';
@@ -182,10 +203,6 @@ export function createSpawnRunner({
182
203
  reconcileJobWatchdogPartial(job, value);
183
204
  return value;
184
205
  }
185
- if (job?.status === 'cancelled') {
186
- finalStatus = 'cancelled';
187
- throw error;
188
- }
189
206
  finalStatus = 'error';
190
207
  reconcileJobStreamStalled(job, error);
191
208
  throw error;
@@ -11,8 +11,15 @@ const ACTIVE_WORKER_STATUS =
11
11
  /^(?:connecting|requesting|streaming|tool[-_\s]?running|running|queued|pending|starting|cancelling)$/i;
12
12
  const WORKER_POOL_FRESH_MS = 2 * 60 * 1000;
13
13
 
14
+ const CANCELLED_WORKER_STATUS = /^(?:cancelled|canceled|killed|cancel[-_\s]?(?:unconfirmed|pending))$/i;
15
+
16
+ /** `status` decides; `stage` is the runtime phase copied in by the progress
17
+ * sweep and only decides for a row with no status. A cancel in either field
18
+ * is not work (bare `cancelling` still is). */
14
19
  export const isActiveWorkerRow = (row) =>
15
- ACTIVE_WORKER_STATUS.test(clean(row?.status)) || ACTIVE_WORKER_STATUS.test(clean(row?.stage));
20
+ !CANCELLED_WORKER_STATUS.test(clean(row?.status)) &&
21
+ !CANCELLED_WORKER_STATUS.test(clean(row?.stage)) &&
22
+ ACTIVE_WORKER_STATUS.test(clean(row?.status) || clean(row?.stage));
16
23
 
17
24
  /** A persisted approval wait whose runtime is gone: the in-memory wait died
18
25
  * with that process (daemon restart), so the flag must not stick. */
@@ -2,7 +2,7 @@
2
2
  // The one row shape of the worker index: coercing whatever a stored file or a
3
3
  // caller hands in, and projecting a live session into a row.
4
4
  import { agentTagOf, clean, positiveInt } from '../helpers.mjs';
5
- import { isLeadPoolAgent } from '../worker-rows.mjs';
5
+ import { isLeadPoolAgent, workerStageForStatus } from '../worker-rows.mjs';
6
6
 
7
7
  /** An explicit boolean wins; otherwise the session's own fast flag (true) or unknown. */
8
8
  function fastFlag(explicit, sessionFast) {
@@ -72,7 +72,7 @@ export function workerRowFromSession(session, fallbackTag = '', extra = {}, getS
72
72
  if (!tag || !sessionId) return null;
73
73
  const runtime = getSessionRuntime(sessionId);
74
74
  const status = clean(extra.status) || (session?.closed === true ? 'closed' : clean(session?.status) || 'idle');
75
- const stage = clean(extra.stage) || clean(runtime?.stage) || status;
75
+ const stage = clean(extra.stage) || workerStageForStatus(status, runtime?.stage);
76
76
  const nowIso = new Date().toISOString();
77
77
  return {
78
78
  tag,
@@ -1,4 +1,5 @@
1
1
  import { agentTagOf, clean, positiveInt, stampMs } from './helpers.mjs';
2
+ import { ACTIVE_STAGES } from './tool-def.mjs';
2
3
 
3
4
  import { TAG_TOMBSTONE_TTL_MS, tagTombstoneKey } from '../../../runtime/shared/agent-reap-state.mjs';
4
5
  export { TAG_TOMBSTONE_TTL_MS, tagTombstoneKey };
@@ -27,6 +28,22 @@ export function isTerminalWorkerStatus(status) {
27
28
  );
28
29
  }
29
30
 
31
+ const WORKING_WORKER_STATUS =
32
+ /^(?:connecting|requesting|streaming|tool[-_\s]?running|running|queued|pending|starting|cancelling)$/i;
33
+ const WORKING_WORKER_STAGES = new Set([...ACTIVE_STAGES, 'resource_wait']);
34
+
35
+ /** The `stage` to store beside a worker `status`, from a stage read off the
36
+ * live runtime. That stage is the runtime's own phase, so mid-work it can say
37
+ * `idle`/`done`/`error` (a fresh or just-settled runtime entry) while the
38
+ * worker is still running. Stored next to a working status it made a mixed
39
+ * row that readers classified as finished, so a working status keeps a
40
+ * working stage and falls back to the status itself. */
41
+ export function workerStageForStatus(status, runtimeStage) {
42
+ const stage = clean(runtimeStage);
43
+ if (!WORKING_WORKER_STATUS.test(clean(status))) return stage || clean(status);
44
+ return WORKING_WORKER_STAGES.has(stage.toLowerCase()) ? stage : clean(status);
45
+ }
46
+
30
47
  export function recoverTagTombstoneOwner(row, sessions) {
31
48
  if (clean(row.parentSessionId || row.ownerSessionId)) return row;
32
49
  const pid = positiveInt(row.clientHostPid);
@@ -19,7 +19,10 @@ export function createChannelSessionRouter({ getSessionService, getSessionId, lo
19
19
  service.submitSession({
20
20
  sessionId,
21
21
  prompt: content,
22
- options: { source: 'channel' },
22
+ // A channel notification (webhook event rules carry fenced external
23
+ // values) is queued as a task notification, never as typed input, so
24
+ // nothing inside it selects a skill.
25
+ options: { source: 'channel', mode: 'task-notification' },
23
26
  })
24
27
  ).catch((error) => {
25
28
  log(`channel session delivery failed session=${sessionId}: ${error?.message || error}`);
@@ -3,6 +3,7 @@ import { spawn, spawnSync } from 'node:child_process';
3
3
  import { MAX_BUFFER_BYTES } from './constants.mjs';
4
4
  import { handlerTimeoutS } from './handler-timeout.mjs';
5
5
  import { abortReason, throwIfAborted } from '../../../runtime/shared/abort-race.mjs';
6
+ import { scrubRuntimeRootVars } from '../../../runtime/agent/orchestrator/tools/env-scrub.mjs';
6
7
 
7
8
  function resolvePlaceholders(str, projectDir, pluginData, pluginRoot = null) {
8
9
  if (typeof str !== 'string') return str;
@@ -88,8 +89,10 @@ function hookEnv(projectDir, pluginData, payload, pluginRoot = null) {
88
89
  const resolvedProject = projectDir || process.cwd();
89
90
  const resolvedPluginRoot = pluginRoot || resolvedProject;
90
91
  const resolvedPluginData = pluginData || resolvedProject;
92
+ // Hooks are user commands like model shells: the host's runtime root,
93
+ // identity and Electron node-mode must not reach them.
91
94
  const env = {
92
- ...process.env,
95
+ ...scrubRuntimeRootVars({ ...process.env }),
93
96
  MIXDOG_PROJECT_DIR: resolvedProject,
94
97
  MIXDOG_PLUGIN_ROOT: resolvedPluginRoot,
95
98
  MIXDOG_PLUGIN_DATA: resolvedPluginData,
@@ -1,6 +1,7 @@
1
1
  import { readResponseBuffer } from '../../../runtime/shared/bounded-download.mjs';
2
2
  import { runAbortable, throwIfAborted } from '../../../runtime/shared/abort-race.mjs';
3
3
  import { assertPublicUrl, pinnedFetch } from '../../../runtime/web-search/lib/ssrf-guard.mjs';
4
+ import { providerSafeMcpToolName } from '../../../runtime/agent/orchestrator/mcp/client-config.mjs';
4
5
  import { handlerTimeoutS } from './handler-timeout.mjs';
5
6
  export { handlerTimeoutS } from './handler-timeout.mjs';
6
7
  export { defaultShellKind, runCommandHandler } from './command-handler.mjs';
@@ -216,8 +217,9 @@ export async function runMcpToolHandler(handler, payload, eventName, mcpToolRunn
216
217
  throwIfAborted(signal);
217
218
  const timeoutMs = Math.round(handlerTimeoutS(handler, eventName) * 1000);
218
219
  let name = String(handler.tool || '').trim();
219
- if (handler.server && !name.startsWith('mcp__')) {
220
- name = `mcp__${String(handler.server).trim()}__${name}`;
220
+ if (handler.server && name && !name.startsWith('mcp__')) {
221
+ // The same provider-safe name the server's tool was registered under.
222
+ name = providerSafeMcpToolName(String(handler.server).trim(), name);
221
223
  }
222
224
  if (!name) {
223
225
  return {
@@ -241,7 +243,9 @@ export async function runMcpToolHandler(handler, payload, eventName, mcpToolRunn
241
243
  onTimeout: () => {
242
244
  try {
243
245
  controller.abort(new Error(`mcp_tool hook timed out: ${name}`));
244
- } catch {}
246
+ } catch {
247
+ // Abort is best-effort; the timeout error below is what callers see.
248
+ }
245
249
  return new Error(`mcp_tool hook timed out: ${name}`);
246
250
  },
247
251
  }
@@ -54,6 +54,15 @@ import {
54
54
  beginOAuthLogin as beginMuseCodeOAuthLogin,
55
55
  loginOAuth as loginMuseCodeOAuth,
56
56
  } from '../../runtime/agent/orchestrator/providers/muse-code-oauth-login.mjs';
57
+ import {
58
+ describeCommandCodeOAuthCredentials,
59
+ forgetCommandCodeOAuthCredentials,
60
+ hasCommandCodeOAuthCredentials,
61
+ } from '../../runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs';
62
+ import {
63
+ beginOAuthLogin as beginCommandCodeOAuthLogin,
64
+ loginOAuth as loginCommandCodeOAuth,
65
+ } from '../../runtime/agent/orchestrator/providers/command-code-oauth-login.mjs';
57
66
  import {
58
67
  beginCursorOAuthLogin,
59
68
  describeCursorOAuthCredentials,
@@ -80,6 +89,7 @@ import {
80
89
  changeProviderAccounts,
81
90
  removeProviderAccount,
82
91
  clearProviderAccountQuotaState,
92
+ providerAccountLimit,
83
93
  ACCOUNT_PROVIDERS,
84
94
  } from '../../runtime/shared/provider-accounts.mjs';
85
95
  import { currentProviderAccountId, withProviderAccount } from '../../runtime/shared/provider-auth-binding.mjs';
@@ -154,6 +164,16 @@ const OAUTH_PROVIDERS = Object.freeze([
154
164
  begin: beginMuseCodeOAuthLogin,
155
165
  login: loginMuseCodeOAuth,
156
166
  }),
167
+ Object.freeze({
168
+ id: 'command-code-oauth',
169
+ name: 'Command Code',
170
+ desc: 'Sign in with your Command Code account',
171
+ has: hasCommandCodeOAuthCredentials,
172
+ describe: describeCommandCodeOAuthCredentials,
173
+ forget: forgetCommandCodeOAuthCredentials,
174
+ begin: beginCommandCodeOAuthLogin,
175
+ login: loginCommandCodeOAuth,
176
+ }),
157
177
  Object.freeze({
158
178
  id: 'mimo-oauth',
159
179
  name: 'MiMo',
@@ -421,6 +441,12 @@ function customProviderRow(id, entry, checkSecrets = true) {
421
441
  const keyless = (config?.auth ?? entry.auth) === 'none';
422
442
  const stored = checkSecrets ? hasStoredSecret(SECRET_ACCOUNTS.agentApiKey(id)) : false;
423
443
  const unstoredStatus = configuredEnabled ? 'No Key' : 'Off';
444
+ let status = stored ? 'Set' : unstoredStatus;
445
+ let detail = stored ? 'stored in keychain' : 'custom endpoint';
446
+ if (keyless) {
447
+ status = configuredEnabled ? 'Keyless' : 'Off';
448
+ detail = 'no API key required';
449
+ }
424
450
  const row = {
425
451
  id,
426
452
  name: entry.name,
@@ -431,12 +457,12 @@ function customProviderRow(id, entry, checkSecrets = true) {
431
457
  group: 'api',
432
458
  type: 'api-key',
433
459
  enabled: configuredEnabled,
434
- authenticated: keyless ? true : checkSecrets ? stored : configuredEnabled,
460
+ authenticated: keyless || (checkSecrets ? stored : configuredEnabled),
435
461
  stored,
436
462
  env: false,
437
463
  envName: null,
438
- status: keyless ? (configuredEnabled ? 'Keyless' : 'Off') : stored ? 'Set' : unstoredStatus,
439
- detail: keyless ? 'no API key required' : stored ? 'stored in keychain' : 'custom endpoint',
464
+ status,
465
+ detail,
440
466
  };
441
467
  row.schemaVersion = config?.schemaVersion ?? entry.schemaVersion;
442
468
  row.auth = keyless ? 'none' : 'key';
@@ -584,7 +610,7 @@ export async function loginOAuthProvider(cfgMod, provider) {
584
610
  updateConfigProvider(cfgMod, id, { enabled: true });
585
611
  // Same reason as the interactive add-account flow: a fresh credential says
586
612
  // nothing about the quota the previous one exhausted.
587
- if (ACCOUNT_PROVIDERS.includes(id)) clearProviderAccountQuotaState(id, currentProviderAccountId(id));
613
+ if (ACCOUNT_PROVIDERS.includes(id)) await clearProviderAccountQuotaState(id, currentProviderAccountId(id));
588
614
  }
589
615
  return { provider: id, type: 'oauth', authenticated: Boolean(auth.authenticated), status: auth.status || null };
590
616
  }
@@ -621,7 +647,7 @@ function rosterAccountForIdentity(id, oauth, newAccountId, auth) {
621
647
  return match?.id || null;
622
648
  }
623
649
 
624
- function settleOAuthLogin(
650
+ async function settleOAuthLogin(
625
651
  { cfgMod, id, accountId: signedInId, addAccount, includeDefault, label, inAccount, oauth },
626
652
  result
627
653
  ) {
@@ -635,11 +661,11 @@ function settleOAuthLogin(
635
661
  renameSync(providerAccountPath(id, signedInId), providerAccountPath(id, existingId));
636
662
  accountId = existingId;
637
663
  }
638
- registerProviderAccount(id, accountId, { includeDefault, label });
664
+ await registerProviderAccount(id, accountId, { includeDefault, label });
639
665
  // A re-connect can follow a re-created subscription under the same
640
666
  // account id: start it from no recorded quota rather than from the
641
667
  // exhausted window the previous credential earned.
642
- clearProviderAccountQuotaState(id, accountId);
668
+ await clearProviderAccountQuotaState(id, accountId);
643
669
  updateConfigProvider(cfgMod, id, { enabled: true });
644
670
  }
645
671
  return {
@@ -688,12 +714,20 @@ export async function beginOAuthProviderLogin(cfgMod, provider, options = {}) {
688
714
  // The callback and a pasted code can both deliver the same sign-in; it must
689
715
  // settle once, because settling may move the credential to an existing id.
690
716
  let settled = null;
717
+ let settling = null;
691
718
  const finish = async (result) => {
692
719
  if (!result || cancelled) return null;
693
720
  if (settled) return settled;
694
- const outcome = settleOAuthLogin(login, result);
695
- if (outcome.authenticated) settled = outcome;
696
- return outcome;
721
+ // Settling is async now: a second delivery arriving mid-write shares it.
722
+ if (settling) return settling;
723
+ settling = settleOAuthLogin(login, result);
724
+ try {
725
+ const outcome = await settling;
726
+ if (outcome.authenticated) settled = outcome;
727
+ return outcome;
728
+ } finally {
729
+ settling = null;
730
+ }
697
731
  };
698
732
  return {
699
733
  provider: id,
@@ -721,9 +755,11 @@ export function listProviderAccounts(provider) {
721
755
  if (!oauth) throw new TypeError('Unknown OAuth provider.');
722
756
  const pool = readProviderAccountPool(provider);
723
757
  const accounts = pool.accounts.length ? pool.accounts : defaultAccountRows(provider, oauth);
758
+ const now = Date.now();
724
759
  return {
725
760
  provider,
726
761
  auto: pool.auto !== false,
762
+ policy: pool.policy,
727
763
  useCredits: pool.useCredits === true,
728
764
  selectedId: pool.selectedId || accounts[0]?.id || null,
729
765
  accounts: accounts.map((row) => {
@@ -740,6 +776,9 @@ export function listProviderAccounts(provider) {
740
776
  reauthRequired: auth.reauthRequired === true,
741
777
  usage: row.usage || null,
742
778
  blockedUntil: row.blockedUntil || null,
779
+ // The limit holding the account now: account-wide, or only for one
780
+ // model family ("7D Fable") while other models still run.
781
+ limit: providerAccountLimit(row, now, { useCredits: pool.useCredits === true }),
743
782
  ...(identity ? { identity } : {}),
744
783
  ...(typeof auth.email === 'string' && auth.email.trim() ? { email: auth.email.trim() } : {}),
745
784
  };
@@ -753,17 +792,23 @@ function defaultAccountRows(provider, oauth) {
753
792
  return authenticated ? [{ id: 'default', label: 'Account 1' }] : [];
754
793
  }
755
794
 
756
- export function updateProviderAccounts(provider, change) {
795
+ // Store the implicit signed-in `default` account in the roster, so a change or
796
+ // a usage measurement has a row to land on. Returns the current roster view.
797
+ export async function materializeProviderAccounts(provider) {
757
798
  const current = listProviderAccounts(provider);
758
- if (!readProviderAccountPool(provider).accounts.length && current.accounts.length) {
759
- registerProviderAccount(provider, 'default', { label: 'Account 1' });
760
- }
761
- changeProviderAccounts(provider, change);
799
+ if (readProviderAccountPool(provider).accounts.length || !current.accounts.length) return current;
800
+ await registerProviderAccount(provider, 'default', { label: 'Account 1' });
801
+ return listProviderAccounts(provider);
802
+ }
803
+
804
+ export async function updateProviderAccounts(provider, change) {
805
+ await materializeProviderAccounts(provider);
806
+ await changeProviderAccounts(provider, change);
762
807
  // Picking an account by hand is a decision to use it NOW, so the refusal
763
808
  // window and meter stored against it — both describing the state the user
764
809
  // just changed — are dropped here. Never in the pool's own fallback commit,
765
810
  // where clearing them would send the request back to a spent account.
766
- if (change?.selectedId !== undefined) clearProviderAccountQuotaState(provider, change.selectedId);
811
+ if (change?.selectedId !== undefined) await clearProviderAccountQuotaState(provider, change.selectedId);
767
812
  return listProviderAccounts(provider);
768
813
  }
769
814
 
@@ -859,7 +904,8 @@ async function resolveCustomInput(cfgMod, rawInput, options) {
859
904
  const config = normalizeCustomProviderConfig(input, options);
860
905
  const typed = typeof input.apiKey === 'string' ? input.apiKey.trim() : '';
861
906
  const keyless = config.auth === 'none';
862
- const apiKey = keyless ? '' : typed || (id ? getAgentApiKey(id) || '' : '');
907
+ let apiKey = '';
908
+ if (!keyless) apiKey = typed || (id ? getAgentApiKey(id) || '' : '');
863
909
  return { id, config, typed: keyless ? '' : typed, apiKey, keyless };
864
910
  }
865
911
 
@@ -1078,7 +1124,7 @@ export async function forgetProviderAuth(cfgModOrProvider, maybeProvider, reques
1078
1124
  throw new TypeError('Account is no longer connected.');
1079
1125
  }
1080
1126
  const result = withProviderAccount(id, accountId, () => oauth.forget());
1081
- const pool = removeProviderAccount(id, accountId);
1127
+ const pool = await removeProviderAccount(id, accountId);
1082
1128
  if (cfgMod) updateConfigProvider(cfgMod, id, { enabled: pool.accounts.length > 0 });
1083
1129
  return { provider: id, type: 'oauth', forgotten: true, removed: Boolean(result?.removed) };
1084
1130
  }
@@ -236,6 +236,8 @@ function providerDescription(id, group) {
236
236
  return 'Grok Build subscription quota';
237
237
  case 'muse-code-oauth':
238
238
  return 'Muse Code subscription quota';
239
+ case 'command-code-oauth':
240
+ return 'Command Code subscription quota';
239
241
  case 'mimo-oauth':
240
242
  return 'MiMo Token Plan subscription quota';
241
243
  case 'antigravity-oauth':
@@ -343,6 +345,7 @@ const PROVIDER_RANKS = {
343
345
  'anthropic-oauth': 20,
344
346
  'grok-oauth': 30,
345
347
  'muse-code-oauth': 33,
348
+ 'command-code-oauth': 33.5,
346
349
  'mimo-oauth': 34,
347
350
  'cursor-oauth': 35,
348
351
  'antigravity-oauth': 36,
@@ -82,6 +82,7 @@ export function createCompactionSettings({
82
82
  const next = { ...current };
83
83
  if (hasOwn(input, 'auto')) next.auto = input.auto !== false;
84
84
  if (hasOwn(input, 'enabled')) next.auto = input.enabled !== false;
85
+ if (hasOwn(input, 'onModelChange')) next.onModelChange = input.onModelChange !== false;
85
86
  // Legacy Compact type fields are intentionally ignored. There is one
86
87
  // fresh-context Compact contract for every session.
87
88
  // A new budget representation replaces the previous one. Otherwise a
@@ -146,6 +146,7 @@ function publicAccounts(pool) {
146
146
  return {
147
147
  selectedId: pool.selectedId,
148
148
  auto: pool.auto,
149
+ ...(pool.policy ? { policy: pool.policy } : {}),
149
150
  useCredits: pool.useCredits === true,
150
151
  accounts: pool.accounts.map(({ id, label, authenticated, reauthRequired }) => ({
151
152
  id,
@@ -166,9 +167,15 @@ function mcpRows(status) {
166
167
  transport: server.transport || server.type || '',
167
168
  toolCount: Number(server.toolCount || 0),
168
169
  source: server.source || '',
170
+ ...(server.owner?.kind === 'plugin'
171
+ ? { plugin: server.owner.id, pluginServer: server.owner.key, disabledReason: server.disabledReason || null }
172
+ : {}),
169
173
  error: server.error || null,
174
+ ...(server.warnings?.length ? { warnings: server.warnings } : {}),
170
175
  scope: Array.isArray(server.scope) ? server.scope : null,
171
176
  })),
177
+ ...(status?.warnings?.length ? { warnings: status.warnings } : {}),
178
+ ...(status?.declarationErrors?.length ? { declarationErrors: status.declarationErrors } : {}),
172
179
  };
173
180
  }
174
181
 
@@ -577,7 +584,11 @@ const SETUP_ACTION_HANDLERS = {
577
584
  const plugin = ((await rt.pluginsStatus())?.plugins || []).find((row) => row.name === name || row.id === name);
578
585
  if (!plugin) throw new Error(`plugin "${name}" not found`);
579
586
  const result = await rt.enablePluginMcp(plugin);
580
- return { serverName: result.serverName, mcp: mcpRows(result.status) };
587
+ return {
588
+ serverName: result.serverName,
589
+ ...(result.serverNames ? { serverNames: result.serverNames } : {}),
590
+ mcp: mcpRows(result.status),
591
+ };
581
592
  },
582
593
  };
583
594
 
@@ -34,6 +34,7 @@ function publicMcpConfig(row) {
34
34
  return {
35
35
  name: row.name,
36
36
  source: row.source,
37
+ ...(row.owner?.kind === 'plugin' ? { plugin: row.owner.id, pluginServer: row.owner.key, readOnly: true } : {}),
37
38
  enabled: row.enabled !== false,
38
39
  type: config.type || 'stdio',
39
40
  cwd: config.cwd || '',
@@ -196,6 +196,7 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
196
196
  runInBackground: boolean,
197
197
  turnNotifications: boolean,
198
198
  usagePinned: boolean,
199
+ usageRailShortLong: boolean,
199
200
  computerObserveOnly: boolean,
200
201
  notificationVolume: {
201
202
  type: 'integer',
@@ -227,7 +227,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
227
227
  type: 'string',
228
228
  enum: [...INSTRUCTION_FILES_MODES],
229
229
  description:
230
- 'set_instruction_files: which user instruction files new sessions load (global ~/.codex/AGENTS.md, ~/.claude/CLAUDE.md, then the Project root\'s AGENTS.md/CLAUDE.md).',
230
+ "set_instruction_files: which user instruction files new sessions load (global ~/.codex/AGENTS.md, ~/.claude/CLAUDE.md, then the Project root's AGENTS.md/CLAUDE.md).",
231
231
  },
232
232
  name: {
233
233
  type: 'string',
@@ -244,6 +244,12 @@ export const SETUP_TOOL_DEFS = Object.freeze([
244
244
  properties: {
245
245
  selectedId: { type: 'string', description: 'Account to use now.' },
246
246
  auto: { type: 'boolean', description: 'Automatic switching to another account when one is exhausted.' },
247
+ policy: {
248
+ type: 'string',
249
+ enum: ['manual', 'limit', 'headroom'],
250
+ description:
251
+ 'Account switching: manual = selected account only; limit = switch when it reaches a limit; headroom = each new session starts on the account with the most headroom.',
252
+ },
247
253
  useCredits: { type: 'boolean', description: 'Allow paid credits once plan limits are reached.' },
248
254
  order: {
249
255
  type: 'array',
@@ -24,8 +24,8 @@ const DEFAULT_SKILL_BODY = '# Instructions\n\nDescribe how to use this skill.';
24
24
  export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
25
25
  const globalSkillsRoot = () => resolve(resolvePluginData(), 'skills');
26
26
 
27
- function skillsStatus() {
28
- const cwd = getCwd();
27
+ /** `cwd` overrides the session's folder (already validated by the caller). */
28
+ function skillsStatus({ cwd = getCwd() } = {}) {
29
29
  const skills = typeof contextMod.collectSkillsCached === 'function' ? contextMod.collectSkillsCached(cwd) : [];
30
30
  const norm = (value) =>
31
31
  String(value || '')
@@ -54,7 +54,10 @@ export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
54
54
  const source = sourceForSkill(skill);
55
55
  return {
56
56
  name: skill.name,
57
- enabled: !(contextMod.isSkillDisabled?.(skill.name) || contextMod.skillMissingFeature?.(skill.name)),
57
+ enabled: !(
58
+ contextMod.isSkillDisabled?.(skill.name, null, skills) ||
59
+ contextMod.skillMissingFeature?.(skill.name, null, skills)
60
+ ),
58
61
  description: skill.description || '',
59
62
  whenToUse: skill.whenToUse || '',
60
63
  filePath: skill.filePath || null,
@@ -90,6 +93,7 @@ export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
90
93
  if (typeof contextMod.isSkillDisabled === 'function' && contextMod.isSkillDisabled(skillName)) {
91
94
  return `Error: skill "${skillName}" is disabled`;
92
95
  }
96
+ if (contextMod.skillOutsideScope?.(skillName, getCwd())) return contextMod.skillOutsideScopeError(skillName);
93
97
  const skill = skillContent(skillName);
94
98
  // The general tool envelope keeps the main/Lead session identical to agent
95
99
  // loops: the model-visible tool_result is the short stub and the SKILL.md
@@ -91,6 +91,7 @@ export function createAskCallbacks({ transcript, notifyFnForSession, scheduleSea
91
91
  onStreamDelta: streamDelta(turn, options),
92
92
  drainSteering: options.drainSteering,
93
93
  onSteerMessage: options.onSteerMessage,
94
+ onSkillsApplied: options.onSkillsApplied,
94
95
  notifyFn: notifyFnForSession(session0.id),
95
96
  signal: turn.signal,
96
97
  };