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
@@ -16,6 +16,7 @@
16
16
  import { isActualUserInstructionMessage, isInjectedSkillBodyMessage, isSummaryMessage } from './compact/messages.mjs';
17
17
  import { ACTIVE_TURN_CONTINUATION_ANCHOR, ACTIVE_TURN_CONTINUATION_SOURCE } from './compact/continuation.mjs';
18
18
  import { parseTaskNotification } from '../../../shared/task-notification-envelope.mjs';
19
+ import { isImportedMessage } from './imported-message.mjs';
19
20
 
20
21
  export const SYNTHETIC_USER_ENVELOPE_TAG = 'mixdog-runtime';
21
22
 
@@ -62,7 +63,8 @@ function isAlreadyEnveloped(text) {
62
63
 
63
64
  // null => a real user instruction (or nothing to wrap); otherwise the kind.
64
65
  export function classifySyntheticUserMessage(message) {
65
- if (message?.role !== 'user') return null;
66
+ // Imported prose stays the user's own (unwrapped) voice.
67
+ if (message?.role !== 'user' || isImportedMessage(message)) return null;
66
68
  const text = messageText(message);
67
69
  if (!text.trim()) return null;
68
70
  if (isAlreadyEnveloped(text)) return null;
@@ -92,7 +92,7 @@ function crossTurnStub(batch, call, ctSig) {
92
92
  // (which spans ONE assistant turn): when the model re-issues an IDENTICAL
93
93
  // normalized call that has already failed repeatFailLimit times in a row
94
94
  // across iterations, stop re-executing — the result will not change, and
95
- // each retry burns a full LLM round-trip until the hard iteration cap. The
95
+ // each retry burns a full LLM round-trip with no iteration cap to end it. The
96
96
  // call stays unresolved; the guard only skips re-execution.
97
97
  function repeatFailureSkip(batch, call, sigs) {
98
98
  const { sessionRef, repeatFailLimit } = batch;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { contextMeasurementStats } from '../../../../shared/context-measurement.mjs';
8
8
  import { toolResultText } from './tool-result-text.mjs';
9
- import { restoredUserText } from './user-text.mjs';
9
+ import { restoredUserImageRefs, restoredUserText } from './user-text.mjs';
10
10
  import {
11
11
  completionCardFromExecution,
12
12
  parseModelVisibleCompletionWrapper,
@@ -38,6 +38,7 @@ import {
38
38
  } from '../../../../shared/tool-execution-contract.mjs';
39
39
  import { toolResultTerminalStatus } from '../../../../shared/tool-status.mjs';
40
40
  import { transcriptRouteMetadataFields } from '../../../../shared/transcript-metadata.mjs';
41
+ import { isImportedMessage } from '../imported-message.mjs';
41
42
 
42
43
  function restoredTranscriptMetadata(message) {
43
44
  const value = message?.meta?.transcript;
@@ -62,6 +63,10 @@ function restoredTranscriptMetadata(message) {
62
63
  ...(typeof value.sender === 'string' && value.sender ? { sender: value.sender } : {}),
63
64
  ...(typeof value.device === 'string' && value.device ? { device: value.device } : {}),
64
65
  ...(typeof value.checkpointId === 'string' && value.checkpointId ? { checkpointId: value.checkpointId } : {}),
66
+ // Skills this user turn explicitly loaded (header selection or `$name`).
67
+ ...(Array.isArray(value.appliedSkills) && value.appliedSkills.length
68
+ ? { appliedSkills: value.appliedSkills.filter((name) => typeof name === 'string' && name) }
69
+ : {}),
65
70
  ...(completion ? { completion } : {}),
66
71
  };
67
72
  }
@@ -281,7 +286,9 @@ function mergeRestoredToolItems(items) {
281
286
  }
282
287
 
283
288
  function restoredMessageItemUpperBound(message) {
284
- const boundaries = Array.isArray(message?.meta?.sessionInheritances) ? message.meta.sessionInheritances.length : 0;
289
+ const boundaries =
290
+ (Array.isArray(message?.meta?.sessionInheritances) ? message.meta.sessionInheritances.length : 0) +
291
+ (Array.isArray(message?.meta?.modelSwitches) ? message.meta.modelSwitches.length : 0);
285
292
  if (message?.role === 'user') return 1 + boundaries;
286
293
  if (message?.role !== 'assistant') return boundaries;
287
294
  const calls = restoredMessageToolCalls(message);
@@ -322,6 +329,11 @@ function restoredUserTranscriptItems(message, nextId) {
322
329
  // skill bodies (meta:'skill'), hook/system reminders, and tag-wrapped context
323
330
  // blocks must not restore as user bubbles in any client.
324
331
  if (message?.meta === 'skill' || message?.meta === 'hook') return [];
332
+ // Imported prose renders verbatim: never a control row, card or display rewrite.
333
+ if (isImportedMessage(message)) {
334
+ const text = (typeof message.content === 'string' ? message.content : toolResultText(message.content)).trim();
335
+ return text ? [{ kind: 'user', id: nextId(), text, ...restoredTranscriptMetadata(message) }] : [];
336
+ }
325
337
  const text = restoredUserText(message?.content).trim();
326
338
  // Persisted async-completion wrappers ("Async shell task ... finished. Result:
327
339
  // > ...") are the only durable record of a background completion — the live
@@ -353,11 +365,33 @@ function restoredUserTranscriptItems(message, nextId) {
353
365
  }
354
366
  const synthetic = parseSyntheticAgentMessage(text);
355
367
  if (!synthetic) {
356
- return [{ kind: 'user', id: nextId(), text, ...restoredTranscriptMetadata(message) }];
368
+ const imageRefs = restoredUserImageRefs(message?.content);
369
+ return [
370
+ {
371
+ kind: 'user',
372
+ id: nextId(),
373
+ text,
374
+ ...restoredTranscriptMetadata(message),
375
+ ...(imageRefs.length ? { imageRefs } : {}),
376
+ },
377
+ ];
357
378
  }
358
379
  return [restoredNotificationToolItem(synthetic, text, message, nextId, /^(failed|error|killed|cancelled)$/i)];
359
380
  }
360
381
 
382
+ /** The transcript row of an in-place model switch (live and restored). */
383
+ export function modelSwitchItem(id, boundary) {
384
+ return {
385
+ kind: 'statusdone',
386
+ id,
387
+ status: 'model-switched',
388
+ label: 'Model switched',
389
+ provider: boundary.provider,
390
+ modelId: boundary.modelId,
391
+ at: boundary.at,
392
+ };
393
+ }
394
+
361
395
  function restoreTranscriptRange(messages, start, sessionId) {
362
396
  const items = [];
363
397
  const pendingToolCalls = new Map();
@@ -389,6 +423,10 @@ function restoreTranscriptRange(messages, start, sessionId) {
389
423
  at: boundary.at,
390
424
  });
391
425
  }
426
+ for (const boundary of Array.isArray(message?.meta?.modelSwitches) ? message.meta.modelSwitches : []) {
427
+ if (!boundary?.provider || !boundary?.modelId) continue;
428
+ items.push(modelSwitchItem(restoredId(), boundary));
429
+ }
392
430
  }
393
431
  return mergeRestoredToolItems(items);
394
432
  }
@@ -21,9 +21,7 @@ const FEEDBACK_BLOCK = /<visualize_feedback>\n([\s\S]*?)\n?<\/visualize_feedback
21
21
  // on the blob itself: the reference's claimed sizeBytes is not trusted.
22
22
  const FEEDBACK_MAX_BYTES = 128 * 1024;
23
23
  const QUOTED = '("(?:[^"\\\\]|\\\\.)*")';
24
- const CHOICE_LINE = new RegExp(
25
- `· group: (?:${QUOTED}|\\(none\\)) → choice: ${QUOTED}(?: \\(${QUOTED}\\))?$`
26
- );
24
+ const CHOICE_LINE = new RegExp(`· group: (?:${QUOTED}|\\(none\\)) → choice: ${QUOTED}(?: \\(${QUOTED}\\))?$`);
27
25
 
28
26
  function unquote(value) {
29
27
  if (!value) return '';
@@ -53,7 +51,7 @@ function feedbackDisplay(body) {
53
51
  continue;
54
52
  }
55
53
  if (tweaks) {
56
- const change = /^ (.+?) \([^)]*\): (.*) \(was (.*)\)$/.exec(line);
54
+ const change = /^ {4}(.+?) \([^)]*\): (.*) \(was (.*)\)$/.exec(line);
57
55
  if (change) tweaks.push(`${change[1]}: ${change[2]} (was ${change[3]})`);
58
56
  else if (line.startsWith(' - tab: ')) {
59
57
  tweaks = [];
@@ -118,23 +116,46 @@ function referencedFeedbackText(part) {
118
116
  }
119
117
  }
120
118
 
121
- export function restoredUserText(content) {
122
- if (!Array.isArray(content)) {
123
- return withVisualizeFeedbackDisplay(typeof content === 'string' ? content : toolResultText(content));
124
- }
119
+ /** The display lines of a stored prompt's parts, and for each image part the
120
+ * line that draws it: the composer's metadata line right before it, else a
121
+ * bare line of its own (a bare line never stands for the next image). */
122
+ function restoredUserParts(content) {
125
123
  const texts = [];
126
- let previous = '';
124
+ const images = [];
125
+ let pendingMetadata = '';
127
126
  for (const part of content) {
128
- let text;
129
127
  if (part?.type === 'image' || part?.type === 'input_image') {
130
- text = IMAGE_METADATA_LINE.test(previous) ? '' : `[Image: ${part.mimeType || part.mediaType || 'image'}]`;
131
- } else if (isAttachmentReference(part)) {
132
- text = referencedFeedbackText(part);
133
- } else {
134
- text = toolResultText([part]);
128
+ let line = pendingMetadata;
129
+ if (!line) {
130
+ line = `[Image: ${part.mimeType || part.mediaType || 'image'}]`;
131
+ texts.push(line);
132
+ }
133
+ pendingMetadata = '';
134
+ images.push({ part, line });
135
+ continue;
135
136
  }
136
- previous = text;
137
+ const text = isAttachmentReference(part) ? referencedFeedbackText(part) : toolResultText([part]);
137
138
  if (text) texts.push(text);
139
+ pendingMetadata = IMAGE_METADATA_LINE.test(text) ? text.trimEnd().split(/\r?\n/).pop().trim() : '';
138
140
  }
139
- return withVisualizeFeedbackDisplay(texts.join('\n'));
141
+ return { texts, images };
142
+ }
143
+
144
+ export function restoredUserText(content) {
145
+ if (!Array.isArray(content)) {
146
+ return withVisualizeFeedbackDisplay(typeof content === 'string' ? content : toolResultText(content));
147
+ }
148
+ return withVisualizeFeedbackDisplay(restoredUserParts(content).texts.join('\n'));
149
+ }
150
+
151
+ /** The stored original of each image the restored bubble draws, by the
152
+ * `[Image: …]` line that draws it. Every image keeps its slot (one without a
153
+ * stored original has no `ref`) so later images do not shift onto it; empty
154
+ * when no image has a stored original. */
155
+ export function restoredUserImageRefs(content) {
156
+ if (!Array.isArray(content)) return [];
157
+ const slots = restoredUserParts(content).images.map(({ part, line }) =>
158
+ isAttachmentReference(part) ? { line, ref: part.attachmentRef } : { line }
159
+ );
160
+ return slots.some((slot) => slot.ref) ? slots : [];
140
161
  }
@@ -786,9 +786,9 @@ function guardShell(a) {
786
786
  }
787
787
  // Over-max is an unambiguous "wait as long as allowed"; clamp like the other
788
788
  // saturating integer args instead of failing the call.
789
- if (hasOwn(a, 'wait_ms') && Number.isInteger(a.wait_ms) && a.wait_ms > 120000) a.wait_ms = 120000;
789
+ if (hasOwn(a, 'wait_ms') && Number.isInteger(a.wait_ms) && a.wait_ms > 30000) a.wait_ms = 30000;
790
790
  if (hasOwn(a, 'wait_ms') && (!Number.isInteger(a.wait_ms) || a.wait_ms < 1000)) {
791
- return `Error: shell arg "wait_ms" must be an integer from 15000 to 120000, e.g. wait_ms:30000 (got ${JSON.stringify(a.wait_ms)})`;
791
+ return `Error: shell arg "wait_ms" must be an integer from 10000 to 30000, e.g. wait_ms:20000 (got ${JSON.stringify(a.wait_ms)})`;
792
792
  }
793
793
  if (!hasOwn(a, 'command')) {
794
794
  return 'Error: shell requires "command"';
@@ -1,12 +1,12 @@
1
1
  // Commands start in the foreground. Only work still running after the
2
- // 15 s coordination budget is promoted to a tracked background task.
2
+ // 10 s coordination budget is promoted to a tracked background task.
3
3
  // Short commands therefore complete in the original tool turn, while longer
4
4
  // work returns partial output plus task_id and finishes by notification.
5
- // 15 s because a command promoted moments before it ends costs a whole
6
- // follow-up request on `task wait`. Session logs (2026-09-30..10-05), the 260
7
- // promoted commands with a recorded duration: 108 had ended within 10 s, 144
8
- // within 15 s and only 152 within 20 s.
9
- export const DEFAULT_SHELL_AUTO_BACKGROUND_MS = 15_000;
5
+ // A per-call wait_ms may stretch the window for a command whose result should
6
+ // return in the same call, never past 30 s, so the conversation is never held
7
+ // open long; anything longer finishes by notification.
8
+ export const DEFAULT_SHELL_AUTO_BACKGROUND_MS = 10_000;
9
+ export const MAX_SHELL_WAIT_MS = 30_000;
10
10
 
11
11
  // JS timers (setTimeout) and PS WaitForExit(ms) are 32-bit: a delay above
12
12
  // 2^31-1 wraps to a tiny/negative value and fires immediately. Clamp the
@@ -17,17 +17,14 @@ const TIMER_MAX_MS = 2_147_483_647;
17
17
 
18
18
  // Main-agent blocking budget. A timeout is the command's total deadline, not
19
19
  // permission to hold the conversation open for that whole duration: after
20
- // 15 s a still-running command becomes a tracked background task and
20
+ // 10 s a still-running command becomes a tracked background task and
21
21
  // completion is pushed to the owner. MIXDOG_SHELL_AUTO_BACKGROUND_MS
22
22
  // overrides; an explicit 0 disables. Gated on backgroundOnTimeout so
23
23
  // disabled background tasks remain foreground.
24
- // A per-call wait_ms extends that default for the call, capped by the
25
- // foreground maximum; it never shortens it. A shorter window promotes a
26
- // command that would have returned its result in the starting call and spends
27
- // a whole follow-up request on `task wait`. Session logs (2026-09-30..10-05,
28
- // 3062 shell calls): 329 passed a wait_ms under the default (53% of one model
29
- // family's calls), 256 of those were promoted, and 108 of the 192 with a
30
- // recorded duration had finished inside the default window (10 s then).
24
+ // A per-call wait_ms extends that default for the call, capped by
25
+ // MAX_SHELL_WAIT_MS and the foreground maximum; it never shortens it. A
26
+ // shorter window promotes a command that would have returned its result in
27
+ // the starting call and spends a whole follow-up request on `task wait`.
31
28
  function autoBackgroundBudget(backgroundOnTimeout, timeout, waitMs, maxForegroundMs) {
32
29
  const raw = process.env.MIXDOG_SHELL_AUTO_BACKGROUND_MS;
33
30
  const parsed = Number(raw);
@@ -35,7 +32,7 @@ function autoBackgroundBudget(backgroundOnTimeout, timeout, waitMs, maxForegroun
35
32
  raw != null && String(raw).trim() !== '' && Number.isFinite(parsed) && parsed >= 0
36
33
  ? Math.floor(parsed)
37
34
  : DEFAULT_SHELL_AUTO_BACKGROUND_MS;
38
- if (waitMs > 0) defaultMs = Math.max(defaultMs, Math.min(waitMs, maxForegroundMs));
35
+ if (waitMs > 0) defaultMs = Math.max(defaultMs, Math.min(waitMs, MAX_SHELL_WAIT_MS, maxForegroundMs));
39
36
  if (!backgroundOnTimeout || defaultMs <= 0) return 0;
40
37
  return timeout > 0 ? Math.min(defaultMs, timeout) : defaultMs;
41
38
  }
@@ -3,13 +3,25 @@ import { buildPowerShellFilterTeePlan } from '../shell-analysis.mjs';
3
3
  import { normalizeErrorMessage } from '../path-diagnostics.mjs';
4
4
  import { planDirectExeSpawn } from '../shell-direct-exe.mjs';
5
5
  import { POWERSHELL_UTF8_PREFIX } from '../../../../../shared/shell-display.mjs';
6
+ import { renderPowerShellSkillFunction, skillScriptRuntime } from '../../../../../shared/skill-script-runtime.mjs';
6
7
  import { buildShellSpawnEnv } from './spawn-env.mjs';
7
8
  import { formatShellToolFailure } from './result-format.mjs';
8
9
 
10
+ // Every PowerShell model command defines `mixdog-skill-node` first, so the
11
+ // skill launcher runs without the .cmd's cmd.exe argument re-parsing.
12
+ // Injected whenever absent, independent of the UTF-8 prefix deduplication.
13
+ function prefixPowerShellSkillFunction(command) {
14
+ const fn = renderPowerShellSkillFunction(skillScriptRuntime());
15
+ const text = String(command || '');
16
+ return text.trimStart().startsWith(`${fn}\n`) ? text : `${fn}\n${text}`;
17
+ }
18
+
9
19
  function prefixPowerShellUtf8(command) {
10
20
  const prefix = POWERSHELL_UTF8_PREFIX;
11
21
  const text = String(command || '');
12
- return text.trimStart().startsWith(prefix) ? text : `${prefix}\n${text}`;
22
+ const trimmed = text.trimStart();
23
+ const body = trimmed.startsWith(prefix) ? trimmed.slice(prefix.length).replace(/^[ \t]*\r?\n/, '') : text;
24
+ return `${prefix}\n${prefixPowerShellSkillFunction(body)}`;
13
25
  }
14
26
 
15
27
  // How the command reaches the child: a direct exe spawn, PowerShell with the
@@ -54,6 +66,10 @@ export async function planShellInvocation({ command, resolvedSpec, cwd }) {
54
66
  plan.wrappedCommand = prefixPowerShellUtf8(plan.teePlan ? plan.teePlan.command : command);
55
67
  return plan;
56
68
  }
69
+ if (shellType === 'powershell') {
70
+ plan.wrappedCommand = prefixPowerShellSkillFunction(command);
71
+ return plan;
72
+ }
57
73
  if (process.platform !== 'win32' && (shell.includes('bash') || shell.includes('zsh'))) {
58
74
  try {
59
75
  plan.wrappedCommand = await wrapCommandWithSnapshot(shell, command);
@@ -1,4 +1,5 @@
1
1
  import { resourceAdmission } from '../../../../../shared/resource-admission.mjs';
2
+ import { withSkillLauncherPath } from '../../../../../shared/skill-script-runtime.mjs';
2
3
  import {
3
4
  applyShellEgressPolicy,
4
5
  scrubLoaderVars,
@@ -24,5 +25,8 @@ export function buildShellSpawnEnv(cwd, baseEnv = process.env) {
24
25
  scrubLoaderVars(spawnEnv);
25
26
  scrubRuntimeRootVars(spawnEnv);
26
27
  applyShellEgressPolicy(spawnEnv);
28
+ // `mixdog-skill-node` (a skill's ${MIXDOG_SKILL_NODE}) resolves in every
29
+ // model shell; only this env gets the entry, never the daemon's own.
30
+ withSkillLauncherPath(spawnEnv);
27
31
  return spawnEnv;
28
32
  }
@@ -146,7 +146,7 @@ export const BUILTIN_TOOLS = [
146
146
  openWorldHint: true,
147
147
  compressible: true,
148
148
  },
149
- description: `Run programs, builds, tests and computation. Never use shell commands or scripts for work covered by dedicated tools: cat/head/tail→read, ls→list, find→glob, filename lookup→find, grep/rg→grep, code structure→code_graph, file edits/writes (sed/awk/redirection)→edit/apply_patch, Git→git when that tool is on the surface. Tool names are not shell commands. ${_shellBackgroundDisabled ? 'Commands run in the foreground until completion.' : 'After a 15s foreground window (not a timeout; wait_ms extends it up to 120s for one call, e.g. a test suite), unfinished work continues under task_id; use task wait, not read polling. If no execution slot frees within the admission wait, the command is queued as a background task with a task_id. Dev servers/watchers: pass timeout_ms or stop them with task cancel when done.'}`,
149
+ description: `Run programs, builds, tests and computation. Never use shell commands or scripts for work covered by dedicated tools: cat/head/tail→read, ls→list, find→glob, filename lookup→find, grep/rg→grep, code structure→code_graph, file edits/writes (sed/awk/redirection)→edit/apply_patch, Git→git when that tool is on the surface. Tool names are not shell commands. ${_shellBackgroundDisabled ? 'Commands run in the foreground until completion.' : 'After a 10s foreground window (not a timeout; omit wait_ms by default, set it up to 30s only for a command you expect to finish in 10–30s, e.g. one test file), unfinished work continues under task_id; use task wait, not read polling. If no execution slot frees within the admission wait, the command is queued as a background task with a task_id. Dev servers/watchers: pass timeout_ms or stop them with task cancel when done.'}`,
150
150
  inputSchema: {
151
151
  type: 'object',
152
152
  properties: {
@@ -155,14 +155,14 @@ export const BUILTIN_TOOLS = [
155
155
  type: 'integer',
156
156
  minimum: 0,
157
157
  description:
158
- 'Hard kill deadline in ms (omit or 0 = none), separate from the 15s foreground window; set one for throwaway probes so a slow check fails fast.',
158
+ 'Hard kill deadline in ms (omit or 0 = none), separate from the 10s foreground window; set one for throwaway probes so a slow check fails fast.',
159
159
  },
160
160
  wait_ms: {
161
161
  type: 'integer',
162
- minimum: 15000,
163
- maximum: 120000,
162
+ minimum: 10000,
163
+ maximum: 30000,
164
164
  description:
165
- 'Foreground wait in ms before unfinished work continues as a background task (default 15000); raise it for a command that should return its result in this call.',
165
+ 'Foreground wait in ms before unfinished work continues as a background task (default 10000). Omit it by default. Set it only when you expect the command to finish within 10–30s (e.g. one test file or a small build step); never for work expected to take longer, which finishes by notification.',
166
166
  },
167
167
  },
168
168
  required: ['command'],
@@ -8,7 +8,7 @@ import { normalizeOutputPath, resolveAgainstCwd } from '../path-utils.mjs';
8
8
  /** Report the requested path's result; suggestions never retarget the operation. */
9
9
  export async function readFamilyPathEnoentOrError(workDir, fullPath, inputPath, err) {
10
10
  const safeMsg = normalizeErrorMessage(err instanceof Error ? err.message : String(err));
11
- const hint = buildNotFoundHint(workDir, fullPath, 'List', err?.code);
11
+ const hint = await buildNotFoundHint(workDir, fullPath, 'List', err?.code);
12
12
  const tail = finalizeReadFamilyEnoentTail(hint, inputPath, err?.code);
13
13
  // Conclusive absence is the list's ANSWER, not a tool failure (matches
14
14
  // read's `[path absent]` and git's `repo:false` policy). Genuine
@@ -78,4 +78,4 @@ export async function countTextFileLines(fullPath, size) {
78
78
  } finally {
79
79
  await handle?.close().catch(() => {});
80
80
  }
81
- }
81
+ }
@@ -97,7 +97,7 @@ const BASENAME_SCAN_SKIP_DIRS = new Set([
97
97
  // directories scanned and wall-clock. `visitEntry` decides what counts as a
98
98
  // match and which directories to queue, and returns true to stop reading the
99
99
  // current directory (its own limit break).
100
- function scanByBasename(searchRoot, { limit, maxDirs, deadlineMs }, visitEntry) {
100
+ async function scanByBasename(searchRoot, { limit, maxDirs, deadlineMs }, visitEntry) {
101
101
  const matches = [];
102
102
  const queue = [searchRoot];
103
103
  const stopAt = Date.now() + Math.max(1, deadlineMs);
@@ -112,7 +112,7 @@ function scanByBasename(searchRoot, { limit, maxDirs, deadlineMs }, visitEntry)
112
112
  scanned++;
113
113
  let entries;
114
114
  try {
115
- entries = readdirSync(dir, { withFileTypes: true });
115
+ entries = await readdir(dir, { withFileTypes: true });
116
116
  } catch {
117
117
  continue;
118
118
  }
@@ -127,7 +127,7 @@ function scanByBasename(searchRoot, { limit, maxDirs, deadlineMs }, visitEntry)
127
127
  return matches;
128
128
  }
129
129
 
130
- export function findFileByBasename(
130
+ export async function findFileByBasename(
131
131
  searchRoot,
132
132
  fullPath,
133
133
  { limit = 3, maxDirs = 6000, deadlineMs = BASENAME_SCAN_DEADLINE_MS } = {}
@@ -136,7 +136,7 @@ export function findFileByBasename(
136
136
  if (typeof searchRoot !== 'string' || !searchRoot) return [];
137
137
  const target = basename(fullPath).toLowerCase();
138
138
  if (!target) return [];
139
- return scanByBasename(searchRoot, { limit, maxDirs, deadlineMs }, (dir, ent, matches, queue) => {
139
+ return await scanByBasename(searchRoot, { limit, maxDirs, deadlineMs }, (dir, ent, matches, queue) => {
140
140
  const name = ent.name;
141
141
  if (ent.isDirectory()) {
142
142
  if (name.startsWith('.') || BASENAME_SCAN_SKIP_DIRS.has(name)) return false;
@@ -205,7 +205,7 @@ export function findBySuffixStrip(searchRoot, fullPath, { maxIterations = 12 } =
205
205
 
206
206
  // Same as findFileByBasename but for directories sharing the missing path's
207
207
  // final segment name (e.g. guessed `src/shared` → the real `lib/shared`).
208
- export function findDirectoryByBasename(
208
+ export async function findDirectoryByBasename(
209
209
  searchRoot,
210
210
  fullPath,
211
211
  { limit = 3, maxDirs = 6000, deadlineMs = BASENAME_SCAN_DEADLINE_MS } = {}
@@ -214,7 +214,7 @@ export function findDirectoryByBasename(
214
214
  if (typeof searchRoot !== 'string' || !searchRoot) return [];
215
215
  const target = basename(fullPath).toLowerCase();
216
216
  if (!target) return [];
217
- return scanByBasename(searchRoot, { limit, maxDirs, deadlineMs }, (dir, ent, matches, queue) => {
217
+ return await scanByBasename(searchRoot, { limit, maxDirs, deadlineMs }, (dir, ent, matches, queue) => {
218
218
  const name = ent.name;
219
219
  if (!ent.isDirectory()) return false;
220
220
  if (name.toLowerCase() === target) {