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
@@ -11,9 +11,15 @@
11
11
  export const POWERSHELL_UTF8_PREFIX =
12
12
  '[Console]::OutputEncoding=[System.Text.Encoding]::UTF8; $OutputEncoding=New-Object System.Text.UTF8Encoding $false;';
13
13
 
14
+ // The `mixdog-skill-node` definition PowerShell commands carry next
15
+ // (renderPowerShellSkillFunction) is the same kind of execution detail.
16
+ const SKILL_FUNCTION_LINE = /^[ \t]*function mixdog-skill-node \{[^\r\n]*\r?\n/;
17
+
14
18
  export function displayShellCommand(value) {
15
19
  const text = String(value ?? '');
16
- const trimmed = text.trimStart();
17
- if (!trimmed.startsWith(POWERSHELL_UTF8_PREFIX)) return text;
18
- return trimmed.slice(POWERSHELL_UTF8_PREFIX.length).replace(/^[ \t]*\r?\n/, '');
20
+ let rest = text.trimStart();
21
+ const prefixed = rest.startsWith(POWERSHELL_UTF8_PREFIX);
22
+ if (prefixed) rest = rest.slice(POWERSHELL_UTF8_PREFIX.length).replace(/^[ \t]*\r?\n/, '');
23
+ const withoutFunction = rest.replace(SKILL_FUNCTION_LINE, '');
24
+ return prefixed || withoutFunction !== rest ? withoutFunction : text;
19
25
  }
@@ -0,0 +1,10 @@
1
+ export interface SkillMention {
2
+ name: string;
3
+ start: number;
4
+ end: number;
5
+ }
6
+ export function isReservedMentionName(name: unknown): boolean;
7
+ export function isInMarkdownCode(text: unknown, offset: number): boolean;
8
+ export function skillMentionCandidates(text: unknown): SkillMention[];
9
+ export function skillMentions(text: unknown, isSkill: (name: string) => boolean): SkillMention[];
10
+ export function mentionedSkillNames(text: unknown, isSkill: (name: string) => boolean): string[];
@@ -0,0 +1,133 @@
1
+ // Inline `$name` skill mentions: a skill can be named anywhere in a prompt.
2
+ // A candidate is `$` at the start of the text or after whitespace or an
3
+ // opening bracket/quote, followed by a skill-name token (the same
4
+ // lowercase-letters, digits and hyphens rule, 64 characters at most, that
5
+ // skill-document.mjs enforces). It selects a skill only when the token is
6
+ // exactly a known skill name, so `$HOME`, `$300` and unknown names stay prose.
7
+ // The token ends where no ASCII identifier character follows (`$pptx_env`,
8
+ // `$pptxUPPER` are not `pptx`); any other character, Korean particles
9
+ // included (`$pptx로`), ends it.
10
+ const MENTION = /(^|[\s([{"'`])\$([a-z0-9][a-z0-9-]{0,63})(?![A-Za-z0-9_-])/g;
11
+
12
+ // Common environment-variable names (compared case-insensitively) and
13
+ // numeric-only tokens are never inline mentions, even when a skill has that
14
+ // name: `$path` or `$300` in prose means the variable or the amount. Choosing
15
+ // such a skill explicitly (the `Skill:` header chip) still works.
16
+ const RESERVED_NAMES = new Set([
17
+ 'path',
18
+ 'home',
19
+ 'user',
20
+ 'shell',
21
+ 'pwd',
22
+ 'tmpdir',
23
+ 'temp',
24
+ 'tmp',
25
+ 'lang',
26
+ 'term',
27
+ 'xdg_config_home',
28
+ 'userprofile',
29
+ 'appdata',
30
+ 'localappdata',
31
+ 'programfiles',
32
+ 'systemroot',
33
+ 'windir',
34
+ 'comspec',
35
+ ]);
36
+
37
+ /** True when `name` can never be an inline mention (env var or number). */
38
+ export function isReservedMentionName(name) {
39
+ const value = String(name ?? '');
40
+ return /^[0-9]+$/.test(value) || RESERVED_NAMES.has(value.toLowerCase());
41
+ }
42
+
43
+ // Markdown code is never a mention: fenced blocks (``` or ~~~, 3+ chars,
44
+ // optional info string, closed by a fence of the same char at least as long,
45
+ // else running to the end) and inline code spans (a backtick run closed by
46
+ // the next run of exactly the same length; an unmatched run is literal).
47
+ // Deliberate Mixdog difference: Codex (codex-rs/skills/src/mentions.rs) scans
48
+ // raw bytes with no code handling. Offsets stay those of the original text,
49
+ // so desktop highlighting lines up (and never lands inside code).
50
+ const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
51
+ const FENCE_CLOSE = /^ {0,3}(`{3,}|~{3,})[ \t]*$/;
52
+
53
+ function inlineCodeRanges(source, from, to, ranges) {
54
+ const runs = [];
55
+ const re = /`+/g;
56
+ re.lastIndex = from;
57
+ for (let match = re.exec(source); match && match.index < to; match = re.exec(source)) {
58
+ runs.push({ start: match.index, end: Math.min(to, match.index + match[0].length) });
59
+ }
60
+ for (let index = 0; index < runs.length; index += 1) {
61
+ const length = runs[index].end - runs[index].start;
62
+ const close = runs.findIndex((run, at) => at > index && run.end - run.start === length);
63
+ if (close < 0) continue;
64
+ ranges.push([runs[index].start, runs[close].end]);
65
+ index = close;
66
+ }
67
+ }
68
+
69
+ /** [start, end) offsets of Markdown code (fenced blocks and inline spans). */
70
+ function codeRanges(source) {
71
+ const ranges = [];
72
+ let open = null;
73
+ let proseStart = 0;
74
+ for (let at = 0; at <= source.length; ) {
75
+ const newline = source.indexOf('\n', at);
76
+ const end = newline < 0 ? source.length : newline;
77
+ const next = newline < 0 ? source.length + 1 : newline + 1;
78
+ const line = source.slice(at, end).replace(/\r$/, '');
79
+ if (!open) {
80
+ const fence = FENCE_OPEN.exec(line);
81
+ if (fence && !(fence[1][0] === '`' && fence[2].includes('`'))) {
82
+ inlineCodeRanges(source, proseStart, at, ranges);
83
+ open = { char: fence[1][0], length: fence[1].length, start: at };
84
+ }
85
+ } else {
86
+ const fence = FENCE_CLOSE.exec(line);
87
+ if (fence && fence[1][0] === open.char && fence[1].length >= open.length) {
88
+ ranges.push([open.start, Math.min(next, source.length)]);
89
+ proseStart = Math.min(next, source.length);
90
+ open = null;
91
+ }
92
+ }
93
+ at = next;
94
+ }
95
+ if (open) ranges.push([open.start, source.length]);
96
+ else inlineCodeRanges(source, proseStart, source.length, ranges);
97
+ return ranges;
98
+ }
99
+
100
+ /** True when `offset` in `text` lies inside Markdown code (a fenced block or
101
+ * an inline code span) by the same rules mention recognition uses, so a
102
+ * composer can tell whether a `$` being typed can become a mention. */
103
+ export function isInMarkdownCode(text, offset) {
104
+ const source = typeof text === 'string' ? text : '';
105
+ if (!Number.isInteger(offset) || (!source.includes('`') && !source.includes('~~~'))) return false;
106
+ return codeRanges(source).some(([from, to]) => offset >= from && offset < to);
107
+ }
108
+
109
+ /** Every syntactically valid `$name` in `text` outside Markdown code, in
110
+ * order: `start` is the `$`. */
111
+ export function skillMentionCandidates(text) {
112
+ const source = typeof text === 'string' ? text : '';
113
+ const found = [];
114
+ let code = null;
115
+ for (const match of source.matchAll(MENTION)) {
116
+ if (isReservedMentionName(match[2])) continue;
117
+ const start = match.index + match[1].length;
118
+ code ??= source.includes('`') || source.includes('~~~') ? codeRanges(source) : [];
119
+ if (code.some(([from, to]) => start >= from && start < to)) continue;
120
+ found.push({ name: match[2], start, end: start + 1 + match[2].length });
121
+ }
122
+ return found;
123
+ }
124
+
125
+ /** Candidates whose name `isSkill(name)` accepts (all occurrences, in order). */
126
+ export function skillMentions(text, isSkill) {
127
+ return skillMentionCandidates(text).filter((mention) => isSkill(mention.name));
128
+ }
129
+
130
+ /** Distinct mentioned skill names in first-mention order. */
131
+ export function mentionedSkillNames(text, isSkill) {
132
+ return [...new Set(skillMentions(text, isSkill).map((mention) => mention.name))];
133
+ }
@@ -0,0 +1,264 @@
1
+ // The interpreter a built-in skill's bundled scripts run on.
2
+ //
3
+ // `${MIXDOG_SKILL_DIR}` is a real directory every process can read, but the
4
+ // pptx scripts import the runtime by relative path (../../../../runtime/...)
5
+ // and its native dependencies (sharp, @napi-rs/canvas, pdf.js). A packaged
6
+ // desktop keeps those only inside runtime.asar, which plain Node cannot open,
7
+ // so `node "<dir>/scripts/x.mjs"` works from an npm install and fails there.
8
+ //
9
+ // So the daemon that runs the model's shells hands them its OWN runtime: a
10
+ // per-installation directory, first on every model shell's PATH, holds
11
+ // `mixdog-skill-node` launchers that run this process's executable (Electron
12
+ // in node mode, or node) on src/skill-script-entry.mjs, which maps the script
13
+ // back into the archive before importing it. Each daemon builds its own shell
14
+ // env, so an SSH-remote or mobile session gets its execution host's runtime.
15
+ // Launchers carry two paths and nothing else: no credentials, no daemon
16
+ // identity.
17
+ import { createHash } from 'node:crypto';
18
+ import { existsSync, mkdirSync, readFileSync, realpathSync } from 'node:fs';
19
+ import path from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+ import { writeFileAtomicSync } from './atomic-file.mjs';
22
+ import { resolvePluginData } from './plugin-paths.mjs';
23
+
24
+ /** This module's package root (src/runtime/shared → the package). */
25
+ export const SKILL_SCRIPT_PACKAGE_ROOT = path.resolve(fileURLToPath(new URL('.', import.meta.url)), '..', '..', '..');
26
+
27
+ function pathApi(platform) {
28
+ return platform === 'win32' ? path.win32 : path.posix;
29
+ }
30
+
31
+ /** The `…/runtime.asar` prefix of a location inside the runtime archive, or null. */
32
+ export function archiveRootOf(location, platform = process.platform) {
33
+ const sep = platform === 'win32' ? '[\\\\/]' : '/';
34
+ const match = new RegExp(`^(.*?${sep}runtime\\.asar)(?=${sep}|$)`).exec(String(location || ''));
35
+ return match ? pathApi(platform).normalize(match[1]) : null;
36
+ }
37
+
38
+ /**
39
+ * The path a script must be imported from. A built-in skill's directory is
40
+ * handed out under `runtime.asar.unpacked` (skillExecutionDir), but its
41
+ * relative imports only resolve from the archive, so a script under the
42
+ * sidecar of the archive that holds this package maps back into it. Source
43
+ * trees and npm installs keep the real path (symlinks resolved, as the ESM
44
+ * loader resolves them for import.meta.url).
45
+ */
46
+ export function canonicalSkillScriptPath(
47
+ target,
48
+ {
49
+ packageRoot = SKILL_SCRIPT_PACKAGE_ROOT,
50
+ platform = process.platform,
51
+ cwd = process.cwd(),
52
+ realpath = realpathSync,
53
+ } = {}
54
+ ) {
55
+ const api = pathApi(platform);
56
+ let location = api.resolve(cwd, String(target));
57
+ try {
58
+ location = realpath(location);
59
+ } catch {
60
+ // A missing script fails at import with its own path in the message.
61
+ }
62
+ const archive = archiveRootOf(packageRoot, platform);
63
+ if (!archive) return location;
64
+ const sidecar = `${archive}.unpacked${api.sep}`;
65
+ const fold = (value) => (platform === 'win32' ? value.replaceAll('/', '\\').toLowerCase() : value);
66
+ if (!fold(location).startsWith(fold(sidecar))) return location;
67
+ return `${archive}${api.sep}${location.slice(sidecar.length)}`;
68
+ }
69
+
70
+ /** The runtime this process would hand a skill script to. */
71
+ export function skillScriptRuntime({
72
+ execPath = process.execPath,
73
+ versions = process.versions,
74
+ packageRoot = SKILL_SCRIPT_PACKAGE_ROOT,
75
+ platform = process.platform,
76
+ } = {}) {
77
+ return {
78
+ platform,
79
+ interpreter: execPath,
80
+ // Electron's own version marker, not ELECTRON_RUN_AS_NODE: model shells
81
+ // scrub that variable, and a daemon may have inherited it without being
82
+ // Electron at all.
83
+ electron: Boolean(versions?.electron),
84
+ packageRoot,
85
+ entry: pathApi(platform).join(packageRoot, 'src', 'skill-script-entry.mjs'),
86
+ };
87
+ }
88
+
89
+ function batchQuote(value) {
90
+ return `"${String(value).replaceAll('%', '%%')}"`;
91
+ }
92
+
93
+ function posixQuote(value) {
94
+ return `'${String(value).replaceAll("'", "'\\''")}'`;
95
+ }
96
+
97
+ /**
98
+ * The command `${MIXDOG_SKILL_NODE}` renders to. It is the same word in every
99
+ * shell: model shells find it on PATH (withSkillLauncherPath), as the
100
+ * extensionless sh launcher (bash, sh, zsh, Git Bash) or as the .cmd beside
101
+ * it (cmd through PATHEXT on Windows). PowerShell model commands define a
102
+ * function of the same name first (renderPowerShellSkillFunction), which
103
+ * takes precedence over both.
104
+ */
105
+ export const SKILL_LAUNCHER_COMMAND = 'mixdog-skill-node';
106
+
107
+ /**
108
+ * sh launcher text. Electron node mode is set only inside the launcher, for
109
+ * the one child it execs; every argument and the exit code pass through.
110
+ */
111
+ export function renderPosixSkillLauncher({ interpreter, entry, electron }) {
112
+ return `${[
113
+ '#!/bin/sh',
114
+ '# Mixdog skill-script launcher, generated for one installation. Do not edit.',
115
+ ...(electron ? ['ELECTRON_RUN_AS_NODE=1', 'export ELECTRON_RUN_AS_NODE'] : []),
116
+ `exec ${posixQuote(interpreter)} ${posixQuote(entry)} "$@"`,
117
+ ].join('\n')}\n`;
118
+ }
119
+
120
+ /** .cmd launcher text, same contract as the sh launcher. */
121
+ export function renderWindowsSkillLauncher({ interpreter, entry, electron }) {
122
+ // cmd decodes a batch file in the console code page line by line, so a
123
+ // non-ASCII path needs UTF-8 for the lines after chcp; the caller's code
124
+ // page is restored before exit.
125
+ const unicode = /\P{ASCII}/u.test(`${interpreter}${entry}`);
126
+ return `${[
127
+ '@echo off',
128
+ 'rem Mixdog skill-script launcher, generated for one installation. Do not edit.',
129
+ 'setlocal EnableExtensions DisableDelayedExpansion',
130
+ ...(unicode
131
+ ? ['for /f "tokens=2 delims=:." %%C in (\'chcp\') do set "MIXDOG_SKILL_CP=%%C"', 'chcp 65001 >nul']
132
+ : []),
133
+ ...(electron ? ['set "ELECTRON_RUN_AS_NODE=1"'] : []),
134
+ `${batchQuote(interpreter)} ${batchQuote(entry)} %*`,
135
+ 'set "MIXDOG_SKILL_EXIT=%ERRORLEVEL%"',
136
+ ...(unicode ? ['if defined MIXDOG_SKILL_CP chcp %MIXDOG_SKILL_CP% >nul'] : []),
137
+ 'exit /b %MIXDOG_SKILL_EXIT%',
138
+ ].join('\r\n')}\r\n`;
139
+ }
140
+
141
+ /** Environment variable carrying a PowerShell caller's arguments to the entry. */
142
+ export const SKILL_ARGV_ENV = 'MIXDOG_SKILL_ARGV';
143
+ const SKILL_ARGV_TAG = 'mixdog1';
144
+
145
+ function psQuote(value) {
146
+ // PowerShell also treats the typographic single quotes as quote characters.
147
+ return `'${String(value).replace(/['\u2018\u2019\u201a\u201b]/g, '$&$&')}'`;
148
+ }
149
+
150
+ /**
151
+ * One-line PowerShell definition of `mixdog-skill-node`, prepended to every
152
+ * PowerShell model command. Through PATH, PowerShell would reach the .cmd via
153
+ * `cmd.exe /c` with arguments it does not quote, so `'a&b'` ran `b`. The
154
+ * function runs this daemon's executable on the entry as a plain native
155
+ * command, so PowerShell's own native-command handling provides streaming,
156
+ * ordering, backpressure, line endings, `2>&1`/`2>$null`/`2>file`,
157
+ * `$LASTEXITCODE`, Ctrl-C and early stop. The caller's arguments never reach
158
+ * that command line: they travel in SKILL_ARGV_ENV (UTF-8 base64), because
159
+ * Windows PowerShell 5.1 drops empty native arguments and does not escape
160
+ * embedded double quotes. A failing script ends the command with its exit
161
+ * code (`exit`), because a PowerShell function cannot fail `$?` or the
162
+ * -Command exit code.
163
+ *
164
+ * SKILL_ARGV_ENV and (Electron daemons only) ELECTRON_RUN_AS_NODE are set on
165
+ * $env just for the call and restored in `finally`; the bootstrap deletes
166
+ * both before importing the script. Accepted tradeoff: while the call runs,
167
+ * a process a concurrent downstream pipeline stage starts can see them.
168
+ */
169
+ export function renderPowerShellSkillFunction({ interpreter, entry, electron }) {
170
+ const names = [SKILL_ARGV_ENV, ...(electron ? ['ELECTRON_RUN_AS_NODE'] : [])];
171
+ const values = ['$__mxa', ...(electron ? ["'1'"] : [])];
172
+ const body = [
173
+ `$__mxa = '${SKILL_ARGV_TAG}'`,
174
+ "foreach ($__mxv in $args) { foreach ($__mxe in @($__mxv)) { if ($null -ne $__mxe) { $__mxa += ',' + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes([string]$__mxe)) } } }",
175
+ names.map((name, i) => `$__mxo${i} = $env:${name}`).join('; '),
176
+ [
177
+ 'try {',
178
+ ...names.map((name, i) => `$env:${name} = ${values[i]};`),
179
+ `& ${psQuote(interpreter)} ${psQuote(entry)}`,
180
+ '} finally {',
181
+ names.map((name, i) => `$env:${name} = $__mxo${i}`).join('; '),
182
+ '}',
183
+ ].join(' '),
184
+ 'if ($LASTEXITCODE) { exit $LASTEXITCODE }',
185
+ ];
186
+ return `function ${SKILL_LAUNCHER_COMMAND} { ${body.join('; ')} }`;
187
+ }
188
+
189
+ /** The arguments a PowerShell caller sent through SKILL_ARGV_ENV, or null. */
190
+ export function decodeSkillArgv(value) {
191
+ const text = typeof value === 'string' ? value : '';
192
+ if (!text.startsWith(SKILL_ARGV_TAG)) return null;
193
+ const rest = text.slice(SKILL_ARGV_TAG.length);
194
+ if (!rest) return [];
195
+ return rest
196
+ .slice(1)
197
+ .split(',')
198
+ .map((item) => Buffer.from(item, 'base64').toString('utf8'));
199
+ }
200
+
201
+ /** Launcher files of `runtime`: the sh script everywhere, plus the .cmd on Windows. */
202
+ export function skillLauncherFiles(runtime) {
203
+ return [
204
+ { name: SKILL_LAUNCHER_COMMAND, content: renderPosixSkillLauncher(runtime) },
205
+ ...(runtime.platform === 'win32'
206
+ ? [{ name: `${SKILL_LAUNCHER_COMMAND}.cmd`, content: renderWindowsSkillLauncher(runtime) }]
207
+ : []),
208
+ ];
209
+ }
210
+
211
+ /** Private per-installation launcher directory under the data dir. */
212
+ export function skillLauncherDir(runtime, dataDir = resolvePluginData()) {
213
+ const digest = createHash('sha256')
214
+ .update(JSON.stringify([runtime.platform, runtime.interpreter, runtime.entry, runtime.electron]))
215
+ .digest('hex')
216
+ .slice(0, 16);
217
+ return pathApi(runtime.platform).join(dataDir, 'skill-launchers', digest);
218
+ }
219
+
220
+ const ensuredDirs = new Set();
221
+
222
+ /**
223
+ * Write (atomically) or refresh the launchers for `runtime`; returns their
224
+ * directory. A directory already verified by this process is only checked for
225
+ * presence, so the per-command shell env build stays a couple of stats.
226
+ */
227
+ export function ensureSkillLauncherDir(runtime = skillScriptRuntime(), dataDir = resolvePluginData()) {
228
+ const dir = skillLauncherDir(runtime, dataDir);
229
+ const api = pathApi(runtime.platform);
230
+ const files = skillLauncherFiles(runtime);
231
+ if (ensuredDirs.has(dir) && files.every(({ name }) => existsSync(api.join(dir, name)))) return dir;
232
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
233
+ for (const { name, content } of files) {
234
+ const file = api.join(dir, name);
235
+ let current = null;
236
+ try {
237
+ current = readFileSync(file, 'utf8');
238
+ } catch {
239
+ // Not written yet.
240
+ }
241
+ if (current !== content) writeFileAtomicSync(file, content, { mode: 0o700 });
242
+ }
243
+ ensuredDirs.add(dir);
244
+ return dir;
245
+ }
246
+
247
+ /**
248
+ * `env` with this installation's launcher directory first on PATH. Only model
249
+ * shell environments call this; the daemon's own env, hooks and internal
250
+ * workers keep their PATH. The directory holds nothing but the launchers, so
251
+ * no existing command is shadowed.
252
+ */
253
+ export function withSkillLauncherPath(env, { runtime = skillScriptRuntime(), dataDir = resolvePluginData() } = {}) {
254
+ const dir = ensureSkillLauncherDir(runtime, dataDir);
255
+ const delimiter = runtime.platform === 'win32' ? ';' : ':';
256
+ // Windows env keys are case-insensitive and usually spelled `Path`.
257
+ const key =
258
+ (runtime.platform === 'win32' ? Object.keys(env).find((name) => name.toUpperCase() === 'PATH') : null) || 'PATH';
259
+ const entries = String(env[key] || '')
260
+ .split(delimiter)
261
+ .filter((entry) => entry && entry !== dir);
262
+ env[key] = [dir, ...entries].join(delimiter);
263
+ return env;
264
+ }
@@ -6,7 +6,7 @@
6
6
  * the shared runtime formatter so L2 matches TUI/desktop cards.
7
7
  */
8
8
  import { colorEnabled, rgb, rgbSgr } from './ansi.mjs';
9
- import { displayModelName, shortenModelName } from '../model-display.mjs';
9
+ import { displayModelName, effortDisplayLabel, shortenModelName } from '../model-display.mjs';
10
10
  import { getModelMetadataSync } from '../llm/model-catalog.mjs';
11
11
  import { contextMeasurementLabel } from '../context-measurement.mjs';
12
12
  import { formatElapsed } from '../time-format.mjs';
@@ -44,14 +44,14 @@ export function modelContextWindow(provider, model, explicitContextWindow = 0) {
44
44
  return FALLBACK_CONTEXT_WINDOW;
45
45
  }
46
46
 
47
- export function formatModelSegment({ provider, model, effort, fast, cols }) {
47
+ export function formatModelSegment({ provider, model, effort, fast, ultra, cols }) {
48
48
  const raw = String(model || '').trim();
49
49
  const meta = getModelMetadataSync(raw, provider) || {};
50
50
  const displayHint = String(meta.displayName || meta.display || meta.name || '').trim();
51
51
  const modelName = shortenModelName(displayModelName(raw, provider, displayHint), cols);
52
52
  const bits = [`${B}${modelName}${R}`];
53
- if (effort) bits.push(`${B}${String(effort).toUpperCase()}${R}`);
54
- if (fast === true) bits.push(`${B}FAST${R}`);
53
+ if (effort) bits.push(`${B}${effortDisplayLabel(effort)}${R}`);
54
+ if (fast === true) bits.push(`${B}${ultra === true ? 'Ultrafast' : 'Fast'}${R}`);
55
55
  return bits.join(` ${D}·${R} `);
56
56
  }
57
57
 
@@ -30,13 +30,13 @@ export function taskCompletionSummary({ surface = 'tool', id, tag, status, error
30
30
  return `${subject} ${outcome}${status === 'failed' && error ? `: ${error}` : ''}${detail ? ` (${detail})` : ''}`;
31
31
  }
32
32
 
33
- export function renderTaskCompletionEnvelope({ surface = 'tool', id, tag, status, result = '', error } = {}) {
33
+ export function renderTaskCompletionEnvelope({ surface = 'tool', id, tag, status, result = '', error, detail } = {}) {
34
34
  return [
35
35
  '<task-notification>',
36
36
  field('task-id', id),
37
37
  tag ? field('tag', tag) : null,
38
38
  field('status', status),
39
- field('summary', taskCompletionSummary({ surface, id, tag, status })),
39
+ field('summary', taskCompletionSummary({ surface, id, tag, status, detail })),
40
40
  result ? `<result>\n${result}\n</result>` : null,
41
41
  status === 'failed' && error ? field('error', error) : null,
42
42
  '</task-notification>',
@@ -22,8 +22,39 @@ function rawToolName(name) {
22
22
  return String(name || 'tool').replace(/^functions\./, '');
23
23
  }
24
24
 
25
- export function parseMcpToolName(name) {
26
- const text = rawToolName(name);
25
+ // Tool names shortened to fit provider limits -> their real server and tool,
26
+ // recorded when the name is built so name-only callers in this process
27
+ // resolve them. Bounded; the oldest entries go first.
28
+ const MCP_TOOL_IDENTITY_MAX = 4096;
29
+ const mcpToolIdentities = new Map();
30
+
31
+ export function rememberMcpToolIdentity(name, server, tool) {
32
+ const key = String(name || '');
33
+ if (!key) return;
34
+ mcpToolIdentities.delete(key);
35
+ mcpToolIdentities.set(key, { server: String(server || ''), tool: String(tool || '') });
36
+ if (mcpToolIdentities.size > MCP_TOOL_IDENTITY_MAX) mcpToolIdentities.delete(mcpToolIdentities.keys().next().value);
37
+ }
38
+
39
+ /** Server and tool of a shortened MCP tool name, when this process built it. */
40
+ export function knownMcpToolIdentity(name) {
41
+ const known = mcpToolIdentities.get(rawToolName(name));
42
+ return known ? { ...known } : null;
43
+ }
44
+
45
+ /** `{ server, tool }` of an MCP tool, or null. Takes a tool definition (its
46
+ * `mcpServerName`/`mcpToolName` metadata wins) or a name (a recorded
47
+ * shortened name first, else the `mcp__<server>__<tool>` form). */
48
+ export function parseMcpToolName(nameOrTool) {
49
+ if (nameOrTool && typeof nameOrTool === 'object') {
50
+ const server = String(nameOrTool.mcpServerName || '').trim();
51
+ const parsed = parseMcpToolName(nameOrTool.name);
52
+ if (!server) return parsed;
53
+ return { server, tool: String(nameOrTool.mcpToolName || '') || parsed?.tool || '' };
54
+ }
55
+ const text = rawToolName(nameOrTool);
56
+ const known = mcpToolIdentities.get(text);
57
+ if (known) return { ...known };
27
58
  const match = /^mcp__(.+?)__(.+)$/.exec(text);
28
59
  if (!match) return null;
29
60
  return { server: match[1], tool: match[2] };
@@ -169,6 +200,8 @@ export function toolSearchDisplayLabel(args = {}) {
169
200
  export function displayToolSearchTarget(value) {
170
201
  const text = String(value || '').trim();
171
202
  if (/^skill:/i.test(text)) return text.slice('skill:'.length);
203
+ const known = knownMcpToolIdentity(text);
204
+ if (known) return `${known.server}.${known.tool}`;
172
205
  const mcp = /^mcp__(.*?)__(.+)$/.exec(text);
173
206
  if (mcp) return `${mcp[1]}.${mcp[2]}`;
174
207
  return stripToolPrefix(text);