mixdog 1.1.2 → 1.2.1

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 (424) hide show
  1. package/README.md +8 -5
  2. package/package.json +2 -1
  3. package/scripts/lib/run-node-tests.mjs +9 -0
  4. package/scripts/prune-desktop-runtime.mjs +3 -0
  5. package/scripts/test-direct.mjs +4 -2
  6. package/src/defaults/shipped-history.json +10 -0
  7. package/src/defaults/skills/pptx/SKILL.md +6 -6
  8. package/src/defaults/skills/pptx/references/review.md +6 -4
  9. package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
  10. package/src/defaults/skills/setup/references/actions.md +18 -5
  11. package/src/defaults/skills/visualize/SKILL.md +160 -0
  12. package/src/defaults/skills/visualize/references/craft.md +88 -0
  13. package/src/headless-command.mjs +56 -3
  14. package/src/headless-exec.mjs +17 -1
  15. package/src/help.mjs +2 -0
  16. package/src/rules/shared/60-verification.md +3 -1
  17. package/src/rules/shared/70-delivery.md +4 -2
  18. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  19. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
  20. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
  21. package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
  22. package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
  23. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
  24. package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
  25. package/src/runtime/agent/orchestrator/config.mjs +19 -5
  26. package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
  27. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
  28. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
  29. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +133 -15
  30. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +55 -8
  31. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +86 -8
  32. package/src/runtime/agent/orchestrator/mcp/client.mjs +474 -164
  33. package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
  34. package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
  35. package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
  36. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
  37. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  38. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
  39. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
  40. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -12
  41. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
  42. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
  43. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
  44. package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
  45. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +444 -0
  46. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
  47. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
  49. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
  50. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +21 -6
  51. package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
  52. package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
  53. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  54. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  55. package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
  56. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
  57. package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
  58. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
  59. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
  60. package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
  61. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +82 -0
  62. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +556 -0
  63. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
  64. package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
  65. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
  66. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +15 -0
  67. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
  68. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
  69. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
  70. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +2 -1
  72. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +15 -4
  73. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
  74. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
  75. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
  76. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
  77. package/src/runtime/agent/orchestrator/providers/registry.mjs +47 -7
  78. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
  79. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
  80. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -11
  81. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
  82. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
  83. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +16 -1
  84. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +278 -84
  85. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
  86. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
  87. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
  88. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -3
  89. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
  90. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
  91. package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
  92. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
  93. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -0
  94. package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
  95. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
  96. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +10 -3
  97. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +24 -13
  98. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
  99. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
  100. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
  101. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
  102. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
  103. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
  104. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
  105. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
  106. package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
  107. package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
  108. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
  109. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
  110. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +1 -1
  111. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
  112. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
  113. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
  114. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +5 -3
  115. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -4
  116. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +21 -10
  117. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
  118. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
  119. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
  120. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +15 -3
  121. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +22 -12
  122. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
  123. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +9 -3
  124. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
  125. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
  126. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
  127. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
  128. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
  129. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
  130. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
  131. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
  132. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
  133. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
  134. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
  135. package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
  136. package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
  137. package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
  138. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +33 -22
  139. package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
  140. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
  141. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
  142. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
  143. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
  144. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
  145. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +36 -0
  146. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +23 -12
  147. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
  148. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +202 -374
  149. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
  150. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
  151. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
  152. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +48 -9
  153. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +161 -0
  154. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
  155. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
  156. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +52 -2
  157. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
  158. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
  159. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
  160. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
  161. package/src/runtime/agent/orchestrator/tools/builtin/read-cache-policy.mjs +8 -0
  162. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +203 -33
  163. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
  164. package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
  165. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
  166. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
  167. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +83 -68
  168. package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
  169. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +20 -3
  170. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
  171. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
  172. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
  173. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
  174. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
  175. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
  176. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
  177. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
  178. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
  179. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +56 -13
  180. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
  181. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
  182. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
  183. package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +25 -1
  184. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
  185. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
  186. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
  187. package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
  188. package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
  189. package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
  190. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +78 -5
  191. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
  192. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
  193. package/src/runtime/attachments/store.d.mts +3 -0
  194. package/src/runtime/attachments/store.mjs +38 -0
  195. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
  196. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
  197. package/src/runtime/channels/lib/worker-main.mjs +17 -14
  198. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
  199. package/src/runtime/effort-judge/judge-client.mjs +56 -18
  200. package/src/runtime/memory/lib/memory.mjs +1 -1
  201. package/src/runtime/memory/lib/session-ingest.mjs +2 -2
  202. package/src/runtime/shared/atomic-file.mjs +33 -6
  203. package/src/runtime/shared/best-effort-stderr.mjs +8 -0
  204. package/src/runtime/shared/code-graph-state.mjs +12 -0
  205. package/src/runtime/shared/defaults-separation.mjs +2 -0
  206. package/src/runtime/shared/extension-scopes.mjs +5 -3
  207. package/src/runtime/shared/file-lock.mjs +37 -11
  208. package/src/runtime/shared/git-runner-worker.mjs +3 -2
  209. package/src/runtime/shared/git-runner.mjs +4 -3
  210. package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
  211. package/src/runtime/shared/llm/default-context-window.mjs +6 -0
  212. package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
  213. package/src/runtime/shared/llm/model-catalog.mjs +240 -130
  214. package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
  215. package/src/runtime/shared/llm/provider-catalog-registry.mjs +162 -0
  216. package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
  217. package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
  218. package/src/runtime/shared/model-proxy-mode.mjs +19 -0
  219. package/src/runtime/shared/plugin-manifest.mjs +18 -9
  220. package/src/runtime/shared/pristine-execution-contract.json +9 -2
  221. package/src/runtime/shared/pristine-execution.mjs +28 -4
  222. package/src/runtime/shared/provider-accounts.mjs +125 -21
  223. package/src/runtime/shared/provider-api-key.mjs +33 -1
  224. package/src/runtime/shared/schedule-model-ref.mjs +11 -2
  225. package/src/runtime/shared/session-usage-totals.mjs +19 -0
  226. package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
  227. package/src/runtime/shared/shell-display.mjs +9 -3
  228. package/src/runtime/shared/singleton-owner.mjs +36 -6
  229. package/src/runtime/shared/skill-mentions.d.mts +10 -0
  230. package/src/runtime/shared/skill-mentions.mjs +133 -0
  231. package/src/runtime/shared/skill-script-runtime.mjs +264 -0
  232. package/src/runtime/shared/statusline/statusline-segments.mjs +68 -14
  233. package/src/runtime/shared/tool-primitives.mjs +35 -2
  234. package/src/runtime/shared/tool-surface.mjs +7 -0
  235. package/src/runtime/shared/tool-work-units.mjs +14 -0
  236. package/src/runtime/shared/transcript-metadata.mjs +17 -1
  237. package/src/runtime/shared/turn-changes.mjs +791 -0
  238. package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
  239. package/src/runtime/shared/turn-snapshot.mjs +690 -81
  240. package/src/runtime/shared/turn-worktree-snapshot.mjs +185 -15
  241. package/src/runtime/shared/worker-requests.mjs +15 -2
  242. package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
  243. package/src/runtime/shared/worktrees/contract.mjs +551 -0
  244. package/src/runtime/shared/worktrees/disk.mjs +57 -0
  245. package/src/runtime/shared/worktrees/git.mjs +247 -0
  246. package/src/runtime/shared/worktrees/include.mjs +480 -0
  247. package/src/runtime/shared/worktrees/lock.mjs +46 -0
  248. package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
  249. package/src/runtime/shared/worktrees/manager.mjs +1215 -0
  250. package/src/runtime/shared/worktrees/merge.mjs +182 -0
  251. package/src/runtime/shared/worktrees/owner.mjs +46 -0
  252. package/src/runtime/shared/worktrees/paths.mjs +62 -0
  253. package/src/runtime/shared/worktrees/registry.mjs +110 -0
  254. package/src/runtime/shared/worktrees/settings.mjs +84 -0
  255. package/src/runtime/shared/worktrees/slug.mjs +62 -0
  256. package/src/runtime/shared/worktrees/test-support.mjs +96 -0
  257. package/src/runtime/visualize-bridge/client.mjs +181 -0
  258. package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
  259. package/src/session-runtime/automation-agents.mjs +8 -2
  260. package/src/session-runtime/boot/apis.mjs +90 -0
  261. package/src/session-runtime/boot/config.mjs +7 -2
  262. package/src/session-runtime/boot/facade.mjs +21 -0
  263. package/src/session-runtime/boot/infrastructure.mjs +30 -18
  264. package/src/session-runtime/boot/session.mjs +1 -0
  265. package/src/session-runtime/boot/tools.mjs +4 -0
  266. package/src/session-runtime/config-lifecycle.mjs +10 -1
  267. package/src/session-runtime/conversation-import/discovery.mjs +698 -0
  268. package/src/session-runtime/conversation-import/service.mjs +369 -0
  269. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +21 -6
  270. package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
  271. package/src/session-runtime/global-extensions.mjs +2 -2
  272. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
  273. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
  274. package/src/session-runtime/internal-tool-executor.mjs +9 -1
  275. package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
  276. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
  277. package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
  278. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
  279. package/src/session-runtime/mcp-glue/connect.mjs +68 -16
  280. package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
  281. package/src/session-runtime/mcp-glue/server-catalog.mjs +122 -33
  282. package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
  283. package/src/session-runtime/mcp-glue.mjs +22 -2
  284. package/src/session-runtime/model-route/route-persist.mjs +3 -0
  285. package/src/session-runtime/model-route/set-route.mjs +15 -2
  286. package/src/session-runtime/new-session-config.mjs +3 -2
  287. package/src/session-runtime/notification-bus.mjs +18 -3
  288. package/src/session-runtime/provider-auth/accounts.mjs +33 -15
  289. package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
  290. package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
  291. package/src/session-runtime/provider-readiness.mjs +16 -10
  292. package/src/session-runtime/resource-extension-sync.mjs +45 -7
  293. package/src/session-runtime/resource-mcp-api.mjs +121 -84
  294. package/src/session-runtime/resource-plugins-api.mjs +29 -41
  295. package/src/session-runtime/resource-scope-decorate.mjs +6 -8
  296. package/src/session-runtime/resource-skills-api.mjs +23 -2
  297. package/src/session-runtime/route-resolution.mjs +10 -1
  298. package/src/session-runtime/route-state.mjs +16 -2
  299. package/src/session-runtime/runtime-core.mjs +5 -0
  300. package/src/session-runtime/runtime-facade.mjs +8 -0
  301. package/src/session-runtime/runtime-review-api.mjs +9 -0
  302. package/src/session-runtime/schedule-session-run.mjs +1 -1
  303. package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
  304. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
  305. package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
  306. package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
  307. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
  308. package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
  309. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
  310. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
  311. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  312. package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
  313. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
  314. package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
  315. package/src/session-runtime/services/agent-tool.mjs +1 -0
  316. package/src/session-runtime/services/channel-session-router.mjs +4 -1
  317. package/src/session-runtime/services/daemon-candidate.mjs +3 -2
  318. package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
  319. package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
  320. package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
  321. package/src/session-runtime/services/provider-admin.mjs +64 -18
  322. package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
  323. package/src/session-runtime/session-create/session-options.mjs +10 -1
  324. package/src/session-runtime/session-turn-api.mjs +1 -0
  325. package/src/session-runtime/settings-api.mjs +4 -2
  326. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
  327. package/src/session-runtime/settings-worktree-api.mjs +17 -0
  328. package/src/session-runtime/setup-tool/executor.mjs +23 -5
  329. package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
  330. package/src/session-runtime/setup-tool/settings-contract.mjs +4 -1
  331. package/src/session-runtime/setup-tool/tool-defs.mjs +38 -4
  332. package/src/session-runtime/skills-api.mjs +7 -3
  333. package/src/session-runtime/turn/agent-ops.mjs +12 -1
  334. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +14 -3
  335. package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
  336. package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
  337. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
  338. package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
  339. package/src/session-runtime/turn/turn-run.mjs +6 -7
  340. package/src/session-runtime/webhook-session-run.mjs +16 -4
  341. package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
  342. package/src/session-runtime/workspace/admission-gate.mjs +197 -0
  343. package/src/session-runtime/workspace/project-branches.mjs +136 -0
  344. package/src/session-runtime/workspace/transition-steps.mjs +364 -0
  345. package/src/session-runtime/workspace/transitions.mjs +651 -0
  346. package/src/session-runtime/workspace/workspace-state.mjs +112 -0
  347. package/src/skill-script-entry.mjs +36 -0
  348. package/src/standalone/channel-transport/http-routes.mjs +17 -0
  349. package/src/standalone/channel-transport.mjs +13 -1
  350. package/src/standalone/daemon-desktop-runtime.mjs +1 -0
  351. package/src/standalone/daemon-owner.mjs +372 -0
  352. package/src/standalone/daemon-stored-session-views.mjs +15 -4
  353. package/src/standalone/daemon.mjs +179 -8
  354. package/src/standalone/desktop-service-registry.mjs +20 -0
  355. package/src/standalone/local-session-runtime.mjs +11 -0
  356. package/src/standalone/session-client/attachment-calls.mjs +3 -1
  357. package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
  358. package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
  359. package/src/standalone/session-client.mjs +104 -13
  360. package/src/standalone/session-protocol.mjs +21 -0
  361. package/src/standalone/session-proxy.mjs +3 -0
  362. package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
  363. package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
  364. package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
  365. package/src/standalone/session-service/projection/revisions.mjs +2 -0
  366. package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
  367. package/src/standalone/session-service/projection/workspace.mjs +14 -0
  368. package/src/standalone/session-service/session-calls/session-action.mjs +17 -4
  369. package/src/standalone/session-transport/call-route.mjs +13 -0
  370. package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
  371. package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
  372. package/src/standalone/session-transport/client-registry.mjs +20 -3
  373. package/src/standalone/session-transport/routes.mjs +79 -2
  374. package/src/standalone/session-transport/stack.mjs +2 -0
  375. package/src/standalone/session-transport.mjs +24 -1
  376. package/src/tui/App.jsx +9 -1
  377. package/src/tui/app/app-view/floating-panel.jsx +9 -1
  378. package/src/tui/app/app-view.jsx +6 -0
  379. package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
  380. package/src/tui/app/message-selector.mjs +2 -1
  381. package/src/tui/app/model-options.mjs +37 -5
  382. package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
  383. package/src/tui/app/model-picker.mjs +4 -2
  384. package/src/tui/app/skill-mention-palette.mjs +88 -0
  385. package/src/tui/app/slash-palette.mjs +23 -7
  386. package/src/tui/app/transcript-row-estimate.mjs +11 -3
  387. package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
  388. package/src/tui/app/use-prompt-state.mjs +5 -0
  389. package/src/tui/components/Message.jsx +22 -1
  390. package/src/tui/components/PromptInput.jsx +21 -3
  391. package/src/tui/components/SlashCommandPalette.jsx +12 -3
  392. package/src/tui/components/TranscriptItem.jsx +9 -1
  393. package/src/tui/components/prompt-input/key-handler.mjs +21 -8
  394. package/src/tui/components/user-message-skills.mjs +38 -0
  395. package/src/tui/dist/index.mjs +839 -207
  396. package/src/tui/index.jsx +10 -2
  397. package/src/tui/session/compaction-view.mjs +147 -0
  398. package/src/tui/session/context-state.mjs +6 -0
  399. package/src/tui/session/initial-state.mjs +3 -0
  400. package/src/tui/session/queue-helpers.mjs +7 -2
  401. package/src/tui/session/quota-resume.mjs +2 -1
  402. package/src/tui/session/session-api/commands.mjs +10 -2
  403. package/src/tui/session/session-api/controls.mjs +4 -0
  404. package/src/tui/session/session-api/extensions.mjs +4 -2
  405. package/src/tui/session/session-api/intake/rewind.mjs +2 -1
  406. package/src/tui/session/session-api/integrations.mjs +17 -0
  407. package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
  408. package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
  409. package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
  410. package/src/tui/session/session-api/routes.mjs +10 -1
  411. package/src/tui/session/session-api/settings.mjs +9 -0
  412. package/src/tui/session/session-api/worktree.mjs +60 -0
  413. package/src/tui/session/session-api.mjs +2 -0
  414. package/src/tui/session/session-flow/auto-clear.mjs +31 -12
  415. package/src/tui/session/session-flow/drain.mjs +27 -3
  416. package/src/tui/session/session-flow/session-reset.mjs +4 -3
  417. package/src/tui/session/session-flow.mjs +2 -0
  418. package/src/tui/session/transcript-intake.mjs +14 -5
  419. package/src/tui/session/tui-steering-persist.mjs +25 -9
  420. package/src/tui/session/turn-stream.mjs +32 -4
  421. package/src/tui/session/turn-tool-cards.mjs +10 -2
  422. package/src/tui/session/turn.mjs +56 -10
  423. package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
  424. package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
@@ -65,7 +65,7 @@ export async function runScheduleSession(schedule, { config = null, prompt: prom
65
65
  const result = await runAutomationTurns(
66
66
  session.id,
67
67
  () => askSession(session.id, content, null, null, cwd || undefined),
68
- (completions) => askSession(session.id, completions, null, null, cwd || undefined)
68
+ (completions, askOpts) => askSession(session.id, completions, null, null, cwd || undefined, undefined, askOpts)
69
69
  );
70
70
  return { sessionId: session.id, result: String(result?.content || '') };
71
71
  }
@@ -12,6 +12,7 @@ import {
12
12
  import { PRESET_ALIASES } from './tool-def.mjs';
13
13
  import { positiveInt } from '../../../runtime/shared/numbers.mjs';
14
14
  import { clean } from '../../../runtime/shared/clean.mjs';
15
+ import { normalizeContextTokens } from '../../../runtime/shared/llm/default-context-window.mjs';
15
16
 
16
17
  export { positiveInt };
17
18
 
@@ -220,10 +221,14 @@ export function normalizeAgentRoute(routeLike) {
220
221
  model,
221
222
  effort: clean(routeLike?.effort) || undefined,
222
223
  fast: routeLike?.fast === true,
224
+ ...(routeLike?.autoEffort === false ? { autoEffort: false } : {}),
223
225
  ...(routeLike?.modelParameters && typeof routeLike.modelParameters === 'object'
224
226
  ? { modelParameters: { ...routeLike.modelParameters } }
225
227
  : {}),
226
228
  ...(Number(routeLike?.contextPercent) > 0 ? { contextPercent: Number(routeLike.contextPercent) } : {}),
229
+ ...(normalizeContextTokens(routeLike?.contextTokens)
230
+ ? { contextTokens: normalizeContextTokens(routeLike.contextTokens) }
231
+ : {}),
227
232
  };
228
233
  }
229
234
 
@@ -3,6 +3,7 @@
3
3
  // progress, filtered by default to workers that can still do work.
4
4
  import { ACTIVE_STAGES } from '../tool-def.mjs';
5
5
  import { isTerminalWorkerStatus } from '../worker-rows.mjs';
6
+ import { sessionUsageTotals } from '../../../../runtime/shared/session-usage-totals.mjs';
6
7
 
7
8
  // Idle, closed, errored and reaped/unknown rows are history and stay reachable
8
9
  // through the task section (status/read keep their terminal result).
@@ -36,6 +37,7 @@ function agentRow({ tag, session, runtime, progress, now, indexRow = null }) {
36
37
  preset: session.presetName || null,
37
38
  effort: session.effort || null,
38
39
  fast: session.fast === true,
40
+ ...(session.autoEffort === false ? { autoEffort: false } : {}),
39
41
  // Additive: route model parameters (e.g. Daybreak Blue) when the route has any.
40
42
  ...(session.modelParameters && Object.keys(session.modelParameters).length
41
43
  ? { modelParameters: { ...session.modelParameters } }
@@ -51,6 +53,7 @@ function agentRow({ tag, session, runtime, progress, now, indexRow = null }) {
51
53
  clientHostPid: session.clientHostPid || null,
52
54
  lastStreamDeltaAt: runtime?.lastStreamDeltaAt ? new Date(runtime.lastStreamDeltaAt).toISOString() : null,
53
55
  staleSeconds: runtime?.lastStreamDeltaAt ? Math.floor((now - runtime.lastStreamDeltaAt) / 1000) : null,
56
+ ...sessionUsageTotals(session),
54
57
  windowTokens: Number(session.lastContextTokens ?? session.lastInputTokens) || 0,
55
58
  windowCap: Number(session.contextWindow) || null,
56
59
  permission: session.permission || null,
@@ -69,6 +69,7 @@ export function createJobLookup({ mgr, tags, refreshTagsFromSessions }) {
69
69
  model: session.model || null,
70
70
  effort: session.effort || null,
71
71
  fast: session.fast === true,
72
+ ...(session.autoEffort === false ? { autoEffort: false } : {}),
72
73
  },
73
74
  };
74
75
  }
@@ -16,6 +16,7 @@ export function preparedSpawnMeta(prepared, extras = {}) {
16
16
  model: prepared.preset.model,
17
17
  effort: prepared.preset.effort || null,
18
18
  fast: prepared.preset.fast === true,
19
+ ...(prepared.preset.autoEffort === false ? { autoEffort: false } : {}),
19
20
  });
20
21
  }
21
22
 
@@ -72,6 +72,20 @@ export function createLeadWorkerIndex({ dataDir, cfgMod, workerRowFromSession })
72
72
  return true;
73
73
  }
74
74
 
75
+ /** A workspace transition moved the Lead: its existing row follows (status,
76
+ * reap deadline and liveness stamps unchanged). No row: nothing to write. */
77
+ function updateLeadWorkerCwd(sessionId, cwd) {
78
+ const id = clean(sessionId);
79
+ const next = clean(cwd);
80
+ if (!id || !next) return false;
81
+ index.write((byKey) => {
82
+ const current = byKey.get(id);
83
+ if (!current || current.cwd === next) return;
84
+ byKey.set(id, { ...current, cwd: next });
85
+ });
86
+ return true;
87
+ }
88
+
75
89
  /** Graceful-exit settlement: every turn this process still claims goes idle
76
90
  * before the runtime disappears. */
77
91
  function flushActiveLeadRows() {
@@ -147,6 +161,7 @@ export function createLeadWorkerIndex({ dataDir, cfgMod, workerRowFromSession })
147
161
  /** Resolves once every queued Lead index write is on disk. */
148
162
  flushLeadWorkerIndexWrites: index.flush,
149
163
  upsertLeadSession,
164
+ updateLeadWorkerCwd,
150
165
  removeLeadWorkerRow,
151
166
  flushActiveLeadRows,
152
167
  recoverStaleLeadRows,
@@ -180,6 +180,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
180
180
  preset: session.presetName || null,
181
181
  effort: session.effort || null,
182
182
  fast: session.fast === true,
183
+ ...(session.autoEffort === false ? { autoEffort: false } : {}),
183
184
  },
184
185
  (job, ownerNotifyContext) => runSend(prepared, ownerNotifyContext, job),
185
186
  notifyContext
@@ -17,6 +17,7 @@ import { isAgentDisabled } from '../../../../runtime/shared/agent-route-config.m
17
17
  import { normalizeAgentPermission } from '../../../../runtime/shared/markdown-frontmatter.mjs';
18
18
  import { resolveAgentSpawnPreset } from '../spawn-preset.mjs';
19
19
  import { AGENT_OWNER } from '../../../../runtime/agent/orchestrator/agent-owner.mjs';
20
+ import { workspaceCwdLock } from '../../../workspace/admission-gate.mjs';
20
21
 
21
22
  export function createSpawnPlanner({
22
23
  cfgMod,
@@ -52,8 +53,15 @@ export function createSpawnPlanner({
52
53
  if (resolveTag(tag, context, { scanSessions: wantsSessionScan(args) })) {
53
54
  throw new Error(`agent spawn: tag "${tag}" already exists`);
54
55
  }
55
- const baseCwd = resolve(callerCwd || defaultCwd || process.cwd());
56
- const workerCwd = clean(args.cwd) ? resolve(baseCwd, args.cwd) : baseCwd;
56
+ // Workers share their Lead's execution root. While the Lead runs in its
57
+ // worktree, that root is locked: neither args.cwd nor an inherited
58
+ // (pre-transition) cwd can send a worker elsewhere.
59
+ const lockedCwd = workspaceCwdLock([
60
+ context?.ownerSessionId,
61
+ context?.callerSessionId || context?.sessionId,
62
+ ]);
63
+ const baseCwd = resolve(lockedCwd || callerCwd || defaultCwd || process.cwd());
64
+ const workerCwd = !lockedCwd && clean(args.cwd) ? resolve(baseCwd, args.cwd) : baseCwd;
57
65
  const prompt = await resolvePrompt(args, workerCwd);
58
66
  if (prepState?.timedOut) {
59
67
  throw new Error('agent spawn prep timed out before session bind');
@@ -10,6 +10,7 @@ import { prepareAgentSession } from '../../../../runtime/agent/orchestrator/agen
10
10
  import { getProvider } from '../../../../runtime/agent/orchestrator/providers/registry.mjs';
11
11
  import { resolveRouteContextState } from '../../../route-state.mjs';
12
12
  import { createSpawnPlanner } from './spawn-plan.mjs';
13
+ import { enterWorkerSpawn } from '../../../workspace/admission-gate.mjs';
13
14
 
14
15
  /** The route fields every worker-row and tag record carries. */
15
16
  export function presetDescriptor(agent, preset, presetName) {
@@ -20,6 +21,7 @@ export function presetDescriptor(agent, preset, presetName) {
20
21
  model: preset.model,
21
22
  effort: preset.effort || null,
22
23
  fast: preset.fast === true,
24
+ ...(preset.autoEffort === false ? { autoEffort: false } : {}),
23
25
  };
24
26
  }
25
27
 
@@ -84,9 +86,9 @@ export function createSpawnPreparer({
84
86
  // A sub-100 context share needs the window it selects; a percent alone
85
87
  // keeps the full served window.
86
88
  const sessionSpec = { ...spec };
87
- if (plan.preset.contextPercent) {
88
- const { contextPercent, selectedContextWindow } = resolveRouteContextState(plan.preset, null);
89
- Object.assign(sessionSpec, { contextPercent, selectedContextWindow });
89
+ if (plan.preset.contextPercent || plan.preset.contextTokens) {
90
+ const { contextPercent, selectedContextWindow, contextTokens } = resolveRouteContextState(plan.preset, null);
91
+ Object.assign(sessionSpec, { contextPercent, selectedContextWindow }, contextTokens ? { contextTokens } : {});
90
92
  }
91
93
  if (sessionSurface?.canonical === true && typeof sessionSurface.createChild === 'function') {
92
94
  return sessionSurface.createChild({ spec: sessionSpec, prompt: plan.prompt, tag: plan.tag });
@@ -99,10 +101,20 @@ export function createSpawnPreparer({
99
101
  }
100
102
 
101
103
  async function prepareSpawnInProcess(args, callerCwd = null, context = {}, prepState = null) {
102
- const plan = await resolveSpawnPlan(args, callerCwd, context, prepState);
103
- const spec = spawnSessionSpec(plan, args, context);
104
- const { session, effectiveCwd } = await createSpawnedSession(plan, spec, prepState);
105
- bindSpawnedSession(session, plan);
104
+ // Shared admission with Lead workspace transitions: no spawn is prepared
105
+ // while the Lead's workspace changes, no transition starts mid-spawn.
106
+ const leaveSpawn = enterWorkerSpawn([context?.ownerSessionId, context?.callerSessionId || context?.sessionId]);
107
+ let plan;
108
+ let session;
109
+ let effectiveCwd;
110
+ try {
111
+ plan = await resolveSpawnPlan(args, callerCwd, context, prepState);
112
+ const spec = spawnSessionSpec(plan, args, context);
113
+ ({ session, effectiveCwd } = await createSpawnedSession(plan, spec, prepState));
114
+ bindSpawnedSession(session, plan);
115
+ } finally {
116
+ leaveSpawn();
117
+ }
106
118
  if (sessionSurface?.canonical !== true) {
107
119
  maybePrewarmSpawnTransport(plan, session);
108
120
  }
@@ -20,6 +20,7 @@ export function resolveAgentSpawnPreset(config, args = {}) {
20
20
  model: clean(args.model),
21
21
  effort: clean(args.effort) || undefined,
22
22
  fast: args.fast === true,
23
+ ...(args.autoEffort === false ? { autoEffort: false } : {}),
23
24
  tools: 'full',
24
25
  },
25
26
  };
@@ -42,8 +43,10 @@ export function resolveAgentSpawnPreset(config, args = {}) {
42
43
  model: agentRoute.model,
43
44
  effort: agentRoute.effort,
44
45
  fast: agentRoute.fast === true,
46
+ ...(agentRoute.autoEffort === false ? { autoEffort: false } : {}),
45
47
  ...(agentRoute.modelParameters ? { modelParameters: agentRoute.modelParameters } : {}),
46
48
  ...(agentRoute.contextPercent ? { contextPercent: agentRoute.contextPercent } : {}),
49
+ ...(agentRoute.contextTokens ? { contextTokens: agentRoute.contextTokens } : {}),
47
50
  tools: 'full',
48
51
  },
49
52
  };
@@ -29,7 +29,7 @@ export function createTagRegistry({ dataDir, cfgMod, mgr }) {
29
29
  workerRowFromSession: index.workerRowFromSession,
30
30
  });
31
31
 
32
- const { upsertLeadSession } = leadIndex;
32
+ const { upsertLeadSession, updateLeadWorkerCwd } = leadIndex;
33
33
 
34
34
  function dispose(options) {
35
35
  try {
@@ -103,6 +103,7 @@ export function createTagRegistry({ dataDir, cfgMod, mgr }) {
103
103
  upsertWorkerSession: index.upsertWorkerSession,
104
104
  upsertWorkerSessionDeferred,
105
105
  upsertLeadSession,
106
+ updateLeadWorkerCwd,
106
107
  removeWorkerRow,
107
108
  refreshTagsFromIndex,
108
109
  tags,
@@ -38,6 +38,7 @@ export function normalizeWorkerRows(value) {
38
38
  preset: clean(row.preset) || null,
39
39
  effort: clean(row.effort) || null,
40
40
  fast: typeof row.fast === 'boolean' ? row.fast : null,
41
+ ...(row.autoEffort === false ? { autoEffort: false } : {}),
41
42
  status: clean(row.status) || 'idle',
42
43
  stage: clean(row.stage) || clean(row.status) || 'idle',
43
44
  createdAt: clean(row.createdAt) || null,
@@ -87,6 +88,10 @@ export function workerRowFromSession(session, fallbackTag = '', extra = {}, getS
87
88
  preset: clean(extra.preset) || clean(session?.presetName) || null,
88
89
  effort: clean(extra.effort) || clean(session?.effort) || null,
89
90
  fast: fastFlag(extra.fast, session?.fast),
91
+ // Absent means Auto effort is on; an explicit boolean wins over the session's.
92
+ ...((typeof extra.autoEffort === 'boolean' ? extra.autoEffort : session?.autoEffort) === false
93
+ ? { autoEffort: false }
94
+ : {}),
90
95
  status,
91
96
  stage,
92
97
  createdAt: clean(session?.createdAt) || clean(extra.createdAt) || nowIso,
@@ -133,6 +133,7 @@ export function workerRowToSession(row = {}) {
133
133
  presetName: row.preset || null,
134
134
  effort: row.effort || null,
135
135
  fast: row.fast === true,
136
+ ...(row.autoEffort === false ? { autoEffort: false } : {}),
136
137
  status: row.status || 'idle',
137
138
  stage: row.stage || row.status || 'idle',
138
139
  createdAt: row.createdAt || null,
@@ -146,6 +146,7 @@ export function createStandaloneAgent({
146
146
  getStatus,
147
147
  recoverWorkers,
148
148
  upsertLeadSession: registry.upsertLeadSession,
149
+ updateLeadWorkerCwd: registry.updateLeadWorkerCwd,
149
150
  closeAll: closeFlow.closeAll,
150
151
  dispose: (options) => registry.dispose(options),
151
152
  };
@@ -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}`);
@@ -5,7 +5,8 @@
5
5
  // ready handoff so the daemon's code/signal is recorded against its pid, boot
6
6
  // time and ready state. Resolves once the candidate reported ready, exited,
7
7
  // failed to spawn, or the timeout elapsed; the caller then re-reads discovery
8
- // and attaches to whoever won.
8
+ // and attaches to whoever won. The resolved `summary()` describes this boot as
9
+ // observed when called, for a caller that has to give up.
9
10
  import { fork } from 'node:child_process';
10
11
  import { beginDaemonSpawnCapture } from './daemon-crash-capture.mjs';
11
12
 
@@ -34,7 +35,7 @@ export function forkDaemonCandidate({
34
35
  // Boot diagnostics written to fd 2 reach this log exactly once, even when
35
36
  // the candidate never reached ready.
36
37
  capture.mirror();
37
- resolve();
38
+ resolve({ summary: capture.summary });
38
39
  };
39
40
  let child;
40
41
  try {
@@ -20,6 +20,11 @@ const CAPTURE_ID_ATTEMPTS = 8;
20
20
  const MIRROR_MAX_BYTES = 16 * 1024;
21
21
  const MESSAGE_MAX_CHARS = 512;
22
22
  const HEAP_FLAG_RE = /^--max-(?:old-space|semi-space|heap)-size=/;
23
+ // Bytes of fd 2 a failure summary scans (the newest ones when larger).
24
+ const SUMMARY_SCAN_MAX_BYTES = 256 * 1024;
25
+ // Node's uncaught-error report (`TypeError: …`, `Error [ERR_…]: …`), V8's
26
+ // fatal abort and the daemon's own `fatal boot error` log line.
27
+ const STDERR_ERROR_LINE_RE = /\b[A-Z][A-Za-z]*Error\b(?: \[[A-Z0-9_]+\])?:|^Error\b|FATAL ERROR|(?<!non-)\bfatal\b/;
23
28
 
24
29
  function stamp(ms) {
25
30
  const iso = new Date(ms).toISOString();
@@ -256,6 +261,8 @@ function noteSpawnError(capture, error) {
256
261
  // this stream, so nothing here extends its lifetime.
257
262
  function drainStderrPipe(capture, stream) {
258
263
  const onData = (chunk) => {
264
+ // No capture file to read back: keep the newest bytes for summary().
265
+ capture.pipeText = `${capture.pipeText}${chunk}`.slice(-SUMMARY_SCAN_MAX_BYTES);
259
266
  mirrorText(capture.log, chunk);
260
267
  };
261
268
  stream.on('data', onData);
@@ -272,6 +279,52 @@ function drainStderrPipe(capture, stream) {
272
279
  });
273
280
  }
274
281
 
282
+ /** The candidate's fd 2 as text: the capture file (its newest bytes when
283
+ * large) or, when fd 2 fell back to a pipe, what that pipe delivered. */
284
+ function stderrText(capture) {
285
+ if (!capture.capturePath || capture.removed) return capture.pipeText;
286
+ try {
287
+ const handle = fs.openSync(capture.capturePath, 'r');
288
+ try {
289
+ const size = fs.fstatSync(handle).size;
290
+ const length = Math.min(size, SUMMARY_SCAN_MAX_BYTES);
291
+ const buffer = Buffer.allocUnsafe(length);
292
+ const bytesRead = fs.readSync(handle, buffer, 0, length, size - length);
293
+ return buffer.subarray(0, bytesRead).toString('utf8');
294
+ } finally {
295
+ fs.closeSync(handle);
296
+ }
297
+ } catch {
298
+ return capture.pipeText;
299
+ }
300
+ }
301
+
302
+ /** What a launcher that gave up on this boot needs to name its cause: the
303
+ * lifecycle as far as observed, the first error line on fd 2 (else its last
304
+ * line, where a stalled boot stopped) and where the full text is. */
305
+ function summarize(capture) {
306
+ const { record } = capture;
307
+ const lines = stderrText(capture)
308
+ .split(/\r?\n/)
309
+ .map((line) => line.trim())
310
+ .filter(Boolean);
311
+ const errorLine = lines.find((line) => STDERR_ERROR_LINE_RE.test(line));
312
+ return {
313
+ pid: record.pid,
314
+ ready: record.ready,
315
+ spawnedAt: record.spawnedAt,
316
+ exitedAt: record.exitedAt,
317
+ exitCode: record.exitCode,
318
+ exitSignal: record.exitSignal,
319
+ exitReason: record.exitReason ?? null,
320
+ uptimeMs: record.uptimeMs,
321
+ error: record.error,
322
+ stderrErrorLine: errorLine ? boundedMessage(errorLine) : null,
323
+ stderrLastLine: lines.length > 0 ? boundedMessage(lines.at(-1)) : null,
324
+ stderrPath: capture.removed ? null : capture.capturePath,
325
+ };
326
+ }
327
+
275
328
  /** Attach to the forked child: record its identity and keep a lifetime
276
329
  * listener that survives the ready handoff, so a later exit is still
277
330
  * correlated to this pid, boot time and ready state. */
@@ -347,6 +400,7 @@ export function beginDaemonSpawnCapture({
347
400
  readOffset: 0,
348
401
  removed: false,
349
402
  pipeDrained: null,
403
+ pipeText: '',
350
404
  stderrStdio: 'pipe',
351
405
  };
352
406
  openCapture(capture, { captureDir, prune, launcherPid, nonce });
@@ -377,5 +431,6 @@ export function beginDaemonSpawnCapture({
377
431
  * recording anything — the child, if any, keeps its duplicate. */
378
432
  release: () => closeWriteFd(capture),
379
433
  snapshot: () => ({ ...capture.record }),
434
+ summary: () => summarize(capture),
380
435
  };
381
436
  }
@@ -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,