mixdog 1.4.0 → 1.4.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 (493) hide show
  1. package/package.json +3 -2
  2. package/scripts/build-shipped-history.mjs +115 -33
  3. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  4. package/scripts/gate-local.mjs +183 -63
  5. package/scripts/latest-guard.mjs +21 -9
  6. package/scripts/lib/gate-scheduler.mjs +138 -32
  7. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +91 -66
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +124 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/lib/test-failure-records.mjs +14 -1
  14. package/scripts/lib/test-failure-summary.mjs +16 -4
  15. package/scripts/lib/test-spawn-ledger.mjs +12 -3
  16. package/scripts/post-release-check.mjs +1 -6
  17. package/scripts/pptx-kit-index.mjs +17 -5
  18. package/scripts/suite-health.mjs +115 -24
  19. package/scripts/test-data-dir.mjs +10 -7
  20. package/scripts/test.mjs +9 -14
  21. package/src/agents/advisor/AGENT.md +4 -4
  22. package/src/agents/advisor/agent.json +1 -1
  23. package/src/agents/explore/AGENT.md +22 -0
  24. package/src/agents/explore/agent.json +6 -0
  25. package/src/app.mjs +4 -0
  26. package/src/cli.mjs +7 -0
  27. package/src/defaults/agents.json +7 -0
  28. package/src/defaults/shipped-history.json +23 -2
  29. package/src/defaults/skills/browser-use/SKILL.md +10 -5
  30. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  31. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  32. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  33. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  34. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  35. package/src/defaults/skills/computer-use/SKILL.md +16 -4
  36. package/src/defaults/skills/goal-management/SKILL.md +1 -1
  37. package/src/defaults/skills/setup/references/actions.md +12 -6
  38. package/src/defaults/skills/setup/references/surfaces.md +2 -2
  39. package/src/defaults/skills/setup-guide/SKILL.md +5 -2
  40. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  41. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  42. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  43. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  44. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  45. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  46. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  47. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  48. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  49. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  50. package/src/defaults/skills/visualize/SKILL.md +6 -2
  51. package/src/lib/rules-builder.cjs +35 -42
  52. package/src/output-styles/common.md +2 -2
  53. package/src/output-styles/simple.md +1 -1
  54. package/src/rules/agent/AGENT.md +5 -4
  55. package/src/rules/lead/LEAD.md +12 -7
  56. package/src/rules/shared/10-tool-workflow.md +3 -1
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/45-destructive.md +0 -2
  60. package/src/rules/shared/50-execution.md +2 -0
  61. package/src/rules/shared/60-verification.md +10 -9
  62. package/src/rules/shared/70-delivery.md +8 -9
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
  65. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
  66. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  69. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  70. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
  71. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
  72. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
  79. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
  80. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
  81. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
  82. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
  84. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  85. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  86. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  90. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
  91. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
  92. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  93. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  94. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  95. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  97. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
  99. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  100. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  101. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  102. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  103. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  104. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  105. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  106. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  107. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
  108. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  109. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  110. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  111. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  112. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  113. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  114. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  115. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  116. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  117. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  128. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  129. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  130. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  131. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  132. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  133. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
  134. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
  135. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  136. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
  137. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  138. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  139. package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
  140. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  141. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  142. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  143. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
  145. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  146. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
  147. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
  148. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  149. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
  150. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
  151. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  152. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  153. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  154. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  155. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  156. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
  157. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  158. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  159. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  160. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  161. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
  162. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  163. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
  164. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
  165. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  166. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  167. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
  168. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  169. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
  170. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
  171. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
  172. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  174. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
  175. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
  176. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
  177. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
  178. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  179. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
  180. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  181. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
  182. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  183. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  184. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
  185. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
  186. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
  187. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
  188. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
  189. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
  190. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  191. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
  192. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
  193. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  194. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  195. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
  196. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  197. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
  198. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
  199. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  200. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
  201. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
  202. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
  203. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  204. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
  209. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  210. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
  211. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  212. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
  213. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  214. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  215. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  217. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
  218. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
  219. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
  221. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
  222. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  223. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  224. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  225. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  226. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  227. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  228. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  229. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  231. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
  232. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  233. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  234. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  235. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  236. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  237. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  238. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  239. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
  240. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  241. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  243. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
  244. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
  245. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  246. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
  247. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  248. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  249. package/src/runtime/channels/lib/whisper-port.mjs +29 -11
  250. package/src/runtime/channels/lib/whisper-server.mjs +10 -1
  251. package/src/runtime/computer-bridge/action-schema.mjs +2 -2
  252. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  253. package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
  254. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  255. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  256. package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
  257. package/src/runtime/connectors/gmail-app-password.mjs +3 -3
  258. package/src/runtime/explore/explorer.mjs +93 -0
  259. package/src/runtime/explore/tool-defs.mjs +35 -0
  260. package/src/runtime/explore/tool.mjs +123 -0
  261. package/src/runtime/local-provider/server-process.mjs +2 -1
  262. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  263. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  264. package/src/runtime/memory/index.mjs +4 -0
  265. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  266. package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
  267. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  268. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  269. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  270. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  271. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  272. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  273. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  274. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  275. package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
  276. package/src/runtime/office/quality/design-review.mjs +1 -5
  277. package/src/runtime/office/quality/document-brief.mjs +1 -5
  278. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  279. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  280. package/src/runtime/shared/agent-route-config.mjs +17 -2
  281. package/src/runtime/shared/atomic-file.mjs +103 -2
  282. package/src/runtime/shared/background-tasks.mjs +15 -6
  283. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  284. package/src/runtime/shared/connector-accounts.mjs +5 -5
  285. package/src/runtime/shared/connector-catalog.d.mts +11 -4
  286. package/src/runtime/shared/connector-catalog.mjs +60 -52
  287. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  288. package/src/runtime/shared/defaults-separation.mjs +1 -4
  289. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  290. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  291. package/src/runtime/shared/file-has-data.mjs +26 -2
  292. package/src/runtime/shared/file-lock.mjs +13 -15
  293. package/src/runtime/shared/git-launch.d.mts +9 -0
  294. package/src/runtime/shared/git-launch.mjs +213 -0
  295. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  296. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  297. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  298. package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
  299. package/src/runtime/shared/llm/cost.mjs +11 -2
  300. package/src/runtime/shared/llm/http-agent.mjs +313 -29
  301. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  302. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  303. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  304. package/src/runtime/shared/llm/system-proxy.mjs +452 -0
  305. package/src/runtime/shared/loopback-listener.mjs +25 -2
  306. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  307. package/src/runtime/shared/model-route-chain.mjs +22 -4
  308. package/src/runtime/shared/open-url.mjs +10 -0
  309. package/src/runtime/shared/provider-accounts.mjs +52 -2
  310. package/src/runtime/shared/session-activity-signal.mjs +14 -0
  311. package/src/runtime/shared/session-scratch.mjs +37 -0
  312. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  313. package/src/runtime/shared/staged-update.mjs +47 -2
  314. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  315. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  316. package/src/runtime/shared/tool-result-summary.mjs +1 -1
  317. package/src/runtime/shared/tool-surface.mjs +113 -36
  318. package/src/runtime/shared/tool-work-units.mjs +6 -0
  319. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  320. package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
  321. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  322. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  323. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  324. package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
  325. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  326. package/src/runtime/shared/worktrees/git.mjs +72 -0
  327. package/src/runtime/shared/worktrees/manager.mjs +285 -168
  328. package/src/runtime/shared/worktrees/test-support.mjs +6 -10
  329. package/src/runtime/tidy/install.mjs +95 -15
  330. package/src/runtime/tidy/languages.mjs +17 -15
  331. package/src/runtime/tidy/process.mjs +7 -4
  332. package/src/runtime/tidy/resolve.mjs +19 -16
  333. package/src/runtime/tidy/runners/biome.mjs +3 -3
  334. package/src/runtime/tidy/tool.mjs +1 -1
  335. package/src/runtime/tidy/worktree.mjs +10 -6
  336. package/src/runtime/visualize-bridge/client.mjs +6 -1
  337. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  338. package/src/runtime/web-search/index.mjs +1 -1
  339. package/src/session-runtime/agent-home-delivery.mjs +41 -0
  340. package/src/session-runtime/agent-task-sessions.mjs +458 -312
  341. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  342. package/src/session-runtime/boot/tools.mjs +7 -1
  343. package/src/session-runtime/bot-status.mjs +107 -101
  344. package/src/session-runtime/bot-target.mjs +38 -0
  345. package/src/session-runtime/channel-config-api.mjs +6 -1
  346. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  347. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  348. package/src/session-runtime/conversation-import/discovery.mjs +401 -36
  349. package/src/session-runtime/conversation-import/service.mjs +35 -8
  350. package/src/session-runtime/handoff-attachments.mjs +82 -31
  351. package/src/session-runtime/held-requests.mjs +3 -1
  352. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
  353. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
  354. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
  355. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  356. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  357. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
  358. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  359. package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
  360. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
  361. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  362. package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
  363. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  364. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  365. package/src/session-runtime/model-route/set-route.mjs +11 -2
  366. package/src/session-runtime/provider-auth/login.mjs +2 -2
  367. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  368. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  369. package/src/session-runtime/provider-models.mjs +4 -2
  370. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  371. package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
  372. package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
  373. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  374. package/src/session-runtime/resource-recall-api.mjs +6 -1
  375. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  376. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  377. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  378. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  379. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  380. package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
  381. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  382. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
  383. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
  384. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  385. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  386. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  387. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  388. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  389. package/src/session-runtime/services/plugin-admin.mjs +10 -6
  390. package/src/session-runtime/services/provider-admin.mjs +283 -11
  391. package/src/session-runtime/session-turn-api.mjs +2 -0
  392. package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
  393. package/src/session-runtime/settings-system-api.mjs +1 -1
  394. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  395. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  396. package/src/session-runtime/setup-tool/executor.mjs +6 -2
  397. package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
  398. package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
  399. package/src/session-runtime/turn/agent-ops.mjs +23 -0
  400. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
  401. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  402. package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
  403. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  404. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  405. package/src/session-runtime/workspace/session-view.mjs +149 -0
  406. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  407. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  408. package/src/session-runtime/workspace/transitions.mjs +108 -1041
  409. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  410. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  411. package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
  412. package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
  413. package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
  414. package/src/standalone/daemon-desktop-runtime.mjs +2 -0
  415. package/src/standalone/daemon-session-control.mjs +169 -138
  416. package/src/standalone/daemon.mjs +7 -0
  417. package/src/standalone/desktop-service-registry.mjs +9 -0
  418. package/src/standalone/local-session-runtime.mjs +5 -1
  419. package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
  420. package/src/standalone/session-client.mjs +5 -1
  421. package/src/standalone/session-frame-stream.mjs +83 -11
  422. package/src/standalone/session-protocol.mjs +4 -0
  423. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  424. package/src/standalone/session-service/agent-tree.mjs +45 -9
  425. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  426. package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
  427. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  428. package/src/standalone/session-service/stored-reader.mjs +127 -40
  429. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  430. package/src/tui/App.jsx +154 -164
  431. package/src/tui/app/app-view/floating-panel.jsx +10 -4
  432. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  433. package/src/tui/app/clipboard.mjs +21 -10
  434. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  435. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  436. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  437. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  438. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  439. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  440. package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
  441. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  442. package/src/tui/app/provider-setup-picker.mjs +29 -18
  443. package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
  444. package/src/tui/app/slash-commands.mjs +1 -0
  445. package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
  446. package/src/tui/app/slash-dispatch.mjs +1 -1
  447. package/src/tui/app/use-btw-panel.mjs +29 -0
  448. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  449. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  450. package/src/tui/app/use-mouse-input.mjs +11 -0
  451. package/src/tui/app/use-onboarding-start.mjs +8 -3
  452. package/src/tui/app/use-panel-transition.mjs +10 -1
  453. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  454. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  455. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  456. package/src/tui/app/use-prompt-queue-history.mjs +3 -2
  457. package/src/tui/app/use-selection-focus.mjs +11 -2
  458. package/src/tui/app/use-selection-geometry.mjs +18 -9
  459. package/src/tui/app/use-selection-paint.mjs +4 -4
  460. package/src/tui/app/use-selection-stitch.mjs +3 -3
  461. package/src/tui/app/use-slash-palette.mjs +62 -0
  462. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  463. package/src/tui/app/use-transcript-activity.mjs +47 -32
  464. package/src/tui/app/use-transcript-follow.mjs +12 -4
  465. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  466. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  467. package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
  468. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  469. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  470. package/src/tui/app/use-transcript-window.mjs +21 -11
  471. package/src/tui/app/use-tui-ready.mjs +18 -0
  472. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  473. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  474. package/src/tui/components/Picker.jsx +27 -3
  475. package/src/tui/components/QuestionPanel.jsx +13 -4
  476. package/src/tui/components/SignInUrl.jsx +68 -0
  477. package/src/tui/components/TextEntryPanel.jsx +76 -46
  478. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  479. package/src/tui/dist/index.mjs +1963 -1361
  480. package/src/tui/session/goal-turn-state.mjs +6 -2
  481. package/src/tui/session/session-api/controls.mjs +4 -0
  482. package/src/tui/session/session-api/extensions.mjs +8 -0
  483. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  484. package/src/tui/session/session-api/intake.mjs +2 -0
  485. package/src/tui/session/session-api/integrations.mjs +2 -2
  486. package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
  487. package/src/tui/session/session-api/settings.mjs +2 -2
  488. package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
  489. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  490. package/src/tui/session/transcript-spill.mjs +92 -4
  491. package/src/tui/session/transcript-store.mjs +2 -0
  492. package/src/ui/statusline-agents.mjs +1 -3
  493. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
@@ -6,13 +6,31 @@
6
6
  import { randomUUID } from 'node:crypto';
7
7
  import { publishForegroundShellRecord, retireForegroundShellRecord } from '../builtin/shell-jobs.mjs';
8
8
  import { ShellTextDecoder, TaskOutput, treeKill } from '../shell-exec-output.mjs';
9
- import { createProcessTreeTracker, killAfterSnapshot } from './shell-descendants.mjs';
9
+ import { createContainedTreeTracker, createProcessTreeTracker } from './shell-descendants.mjs';
10
10
  import { registerOwnedShellTree } from './owned-shell-trees.mjs';
11
11
 
12
+ /** The tracker of the run's process tree, created once. A killed tree the
13
+ * spawn server contains is gone on its verified-empty report alone; every
14
+ * other tree (no containment, or a root that exited on its own and left
15
+ * survivors) is observed through the process table. */
16
+ export function runTreeTracker(run) {
17
+ run.terminationTracker =
18
+ run.terminationTracker ||
19
+ (run.killed === true && run.child.contained === true
20
+ ? createContainedTreeTracker({
21
+ outcome: () => run.child.treeOutcome,
22
+ // Survivors the server kept in the job: the kill, by request id.
23
+ cancel: () => treeKill(run.child),
24
+ })
25
+ : createProcessTreeTracker({ pid: run.child.pid, rootCreationTime: run.child.creationTime }));
26
+ return run.terminationTracker;
27
+ }
28
+
12
29
  /** One pre-kill identity read of the run's tree (every kill path shares it):
13
- * resolves true once the capture is complete, false when it failed. */
30
+ * resolves true once the capture is complete, false when it failed. A
31
+ * contained kill needs none: true at once, so the kill is never delayed. */
14
32
  export function capturePreKill(run) {
15
- run.terminationTracker = run.terminationTracker || createProcessTreeTracker({ pid: run.child.pid });
33
+ if (runTreeTracker(run).contained) return true;
16
34
  const rootExited = run.child.exitCode != null || run.child.signalCode != null;
17
35
  return run.terminationTracker.capture({ rootExited }).catch(() => false);
18
36
  }
@@ -32,6 +50,7 @@ export function registerForegroundOwnedTree(run, ownerSessionId) {
32
50
  run.killCause = run.killCause || 'session-close';
33
51
  // Always a fresh read: an earlier one predates what the run started
34
52
  // since. Pending, the kill is sent at the snapshot bound regardless.
53
+ // A contained tree answers true at once: its cancel is sent at once.
35
54
  return capturePreKill(run);
36
55
  },
37
56
  };
@@ -219,18 +238,23 @@ export function keepTerminationUnconfirmedRecord(run) {
219
238
  // Record the tree's identities while the root is still alive, THEN kill: once
220
239
  // an intermediate dies its children's parent links dangle and a snapshot taken
221
240
  // afterwards can no longer find them.
222
- // The kill waits for the snapshot at most PROCESS_TABLE_READ_BOUND_MS and is
223
- // sent whether the snapshot succeeded, failed or is still pending (a late
224
- // snapshot is still absorbed; a missing one leaves the outcome unknown, so the
225
- // workspace stays held under the observation loop). The confirmation deadline
226
- // starts once the kill is actually issued.
241
+ // The kill waits until the snapshot succeeded or failed, never just for a
242
+ // while: a read still in flight takes its table after a kill sent beside it,
243
+ // finds the root gone, and the tree could never be confirmed terminated (the
244
+ // workspace then stays held until a force-release). A healthy table read takes
245
+ // seconds on a loaded host; a stuck one ends at its enumeration deadline
246
+ // (ENUMERATION_DEADLINE_MS), and the kill is sent then, the outcome unknown.
247
+ // A tree the spawn server contains is killed at once instead: its job holds
248
+ // every descendant, and the server reports when that job is empty.
249
+ // The confirmation deadline starts once the kill is actually issued.
227
250
  function snapshotThenKill(run, afterKill) {
228
- if (!run.child?.pid) {
251
+ const snapshot = run.child?.pid ? capturePreKill(run) : true;
252
+ if (snapshot === true) {
229
253
  treeKill(run.child);
230
254
  afterKill();
231
255
  return;
232
256
  }
233
- void killAfterSnapshot(capturePreKill(run), () => {
257
+ void snapshot.then(() => {
234
258
  treeKill(run.child);
235
259
  afterKill();
236
260
  });
@@ -55,8 +55,13 @@ function _disabled() {
55
55
  return process.env.MIXDOG_SHELL_WARM_STANDBY === '0';
56
56
  }
57
57
 
58
+ // Per-session scratch variables: they differ between sessions by design, so
59
+ // they stay out of the reuse signature and are set in the hand-off prelude.
60
+ const SCRATCH_ENV_KEYS = Object.freeze(['TEMP', 'TMP', 'TMPDIR']);
61
+
58
62
  function envSignature(env) {
59
63
  const entries = Object.entries(env || {})
64
+ .filter(([key]) => !SCRATCH_ENV_KEYS.includes(key))
60
65
  .map(([key, value]) => `${key}=${value}`)
61
66
  .sort()
62
67
  .join('\n');
@@ -67,8 +72,16 @@ function _slotAlive(slot) {
67
72
  return Boolean(slot?.native?.child && slot.native.child.exitCode == null && !slot.native.child.killed);
68
73
  }
69
74
 
70
- function psQuote(value) {
71
- return String(value).replace(/'/g, "''");
75
+ // A PowerShell expression yielding `value` for any text. PowerShell quoting has
76
+ // no safe form for typographic apostrophes and the like, so the value travels
77
+ // as UTF-8 Base64 and is decoded inside the expression.
78
+ function psStringExpr(value) {
79
+ return `[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${Buffer.from(String(value), 'utf8').toString('base64')}'))`;
80
+ }
81
+
82
+ /** The parked standby slot, for tests. */
83
+ export function _parkedShellStandbyForTest() {
84
+ return _slot;
72
85
  }
73
86
 
74
87
  /** Pre-spawn the next standby (fire-and-forget; a live one is kept). */
@@ -89,6 +102,8 @@ function ensureWarmShellStandby({ shell, env }) {
89
102
  outputLimit: SHELL_OUTPUT_DISK_CAP,
90
103
  rawOutput: true,
91
104
  stdinPipe: true,
105
+ // The command it is fed runs contained, like a fresh spawn's.
106
+ contain: true,
92
107
  shellType: 'powershell',
93
108
  command: '(warm shell standby)',
94
109
  },
@@ -164,9 +179,18 @@ export function takeWarmShellStandby({ shell, env }) {
164
179
  // cwd prelude: the standby was spawned in the daemon cwd. Set-Location
165
180
  // fixes $PWD and native-child working dirs; Environment.CurrentDirectory
166
181
  // fixes .NET relative-path APIs.
167
- const prelude = workDir
168
- ? `Set-Location -LiteralPath '${psQuote(workDir)}'; [System.Environment]::CurrentDirectory = '${psQuote(workDir)}'; `
182
+ const cwdPrelude = workDir
183
+ ? `$__mixdogCwd = ${psStringExpr(workDir)}; Set-Location -LiteralPath $__mixdogCwd; [System.Environment]::CurrentDirectory = $__mixdogCwd; `
169
184
  : '';
185
+ // Scratch prelude: the standby was spawned for whichever session parked
186
+ // it. Set (or clear, when the request has none) the requested values
187
+ // before the command runs, so no other session's scratch path survives.
188
+ const scratchPrelude = SCRATCH_ENV_KEYS.map((key) =>
189
+ typeof env?.[key] === 'string'
190
+ ? `$env:${key} = ${psStringExpr(env[key])}; `
191
+ : `Remove-Item -LiteralPath 'Env:${key}' -ErrorAction SilentlyContinue; `
192
+ ).join('');
193
+ const prelude = scratchPrelude + cwdPrelude;
170
194
  // Single atomic write+EOF: a separate close message can race ahead
171
195
  // of the server's async write thread and feed an empty script.
172
196
  slot.native.child.writeStdin(prelude + String(commandText ?? ''), { close: true });
@@ -0,0 +1,26 @@
1
+ // Test support: wait for a real condition on a wall-clock budget. A fixed
2
+ // number of event-loop turns is load-dependent (async record writes and
3
+ // process-table reads take more turns on a busy machine); elapsed time is not.
4
+ // Polls on a short real timer (never a busy loop). The real setTimeout is
5
+ // captured at load, before any test enables mock timers, so a mocked clock
6
+ // cannot freeze the wait.
7
+ import assert from 'node:assert/strict';
8
+
9
+ const realSetTimeout = setTimeout;
10
+ const POLL_MS = 5;
11
+ const tick = () => new Promise((resolve) => realSetTimeout(resolve, POLL_MS));
12
+
13
+ /** Resolves with the first truthy `read()` (sync or async); fails with `what`
14
+ * once `timeoutMs` has passed without one. */
15
+ export async function waitUntil(
16
+ read,
17
+ { timeoutMs = 10_000, what = String(read).replace(/\s+/g, ' ').slice(0, 160) } = {}
18
+ ) {
19
+ const deadline = Date.now() + timeoutMs;
20
+ for (;;) {
21
+ const value = await read();
22
+ if (value) return value;
23
+ if (Date.now() >= deadline) assert.fail(`condition not reached within ${timeoutMs}ms: ${what}`);
24
+ await tick();
25
+ }
26
+ }
@@ -432,7 +432,7 @@ function attachChildExit(run, releasePromotedCapture) {
432
432
  // child termination regardless — give 'close' a 3 s grace then
433
433
  // settle anyway. The grace outlives the spawn server's own 2 s drain
434
434
  // deadline, so the real exit status normally still arrives first.
435
- child.once('exit', (code, signal) => {
435
+ const onExit = (code, signal) => {
436
436
  if (!run.rootExitAtMs) run.rootExitAtMs = Date.now();
437
437
  const grace = setTimeout(() => {
438
438
  if (run.settled || run.promotionClose) return;
@@ -449,7 +449,12 @@ function attachChildExit(run, releasePromotedCapture) {
449
449
  run.settle(code == null ? 1 : code, signal);
450
450
  }, 3000);
451
451
  if (grace.unref) grace.unref();
452
- });
452
+ };
453
+ // The spawn awaits the command's workspace lease before these listeners
454
+ // exist; a root that exited meanwhile ('close' is replayed, 'exit' is not)
455
+ // starts its grace now.
456
+ if (child.exitCode != null || child.signalCode != null) onExit(child.exitCode, child.signalCode);
457
+ else child.once('exit', onExit);
453
458
  }
454
459
 
455
460
  // Live-progress heartbeat: every 2 s while the foreground command runs, emit
@@ -1,30 +1,30 @@
1
1
  {
2
- "version": "0.1.11",
2
+ "version": "0.1.12",
3
3
  "_comment": "Synced from immutable spawn-v release assets.",
4
4
  "assets": {
5
5
  "darwin-arm64": {
6
- "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-darwin-arm64",
7
- "sha256": "6f1a7e6597dcc8785d12c5a13c42388110d9f4a2e5378ca2773172adbf50de60"
6
+ "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.12/mixdog-spawn-darwin-arm64",
7
+ "sha256": "bc2307b1c089e07f829a8a1daf4dfdfc128e3221d8f70609ffbdcc3f8b596806"
8
8
  },
9
9
  "darwin-x64": {
10
- "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-darwin-x64",
11
- "sha256": "ff755eb9848cb3ce90f3df24136bb84a52f9ff6c67002c4d764beb6d7906e6b2"
10
+ "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.12/mixdog-spawn-darwin-x64",
11
+ "sha256": "4b1d221a29128046c417cfae5617e2898e1b7bc564dca686b2608b6cb14bf3af"
12
12
  },
13
13
  "linux-arm64": {
14
- "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-linux-arm64",
15
- "sha256": "3bc0fccde46537046d498a2b953aa92ef4afacc95c96c563ce1d6fb92d74e593"
14
+ "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.12/mixdog-spawn-linux-arm64",
15
+ "sha256": "2f577f54693726db0d285a16c3af2ad25b73fd705fd2fd4ac5c18ce795f657a9"
16
16
  },
17
17
  "linux-x64": {
18
- "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-linux-x64",
19
- "sha256": "16dc4e3bf6636335c1325c88bbb5245529731525953466e761d363897b59aac7"
18
+ "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.12/mixdog-spawn-linux-x64",
19
+ "sha256": "83b52edfe2b810d5cf6544b03ab263eedcf7b2ef3c73107a45a33f6f7871e59e"
20
20
  },
21
21
  "win32-arm64": {
22
- "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-win32-arm64.exe",
23
- "sha256": "c2fb5499d3d44405e27c79f8db65694299d61ddf029f466df68549fc2f2c5f5c"
22
+ "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.12/mixdog-spawn-win32-arm64.exe",
23
+ "sha256": "33872113fc0ca3cd2a2f6cf36c33430431388a5e36f254c8a0c6a44932057009"
24
24
  },
25
25
  "win32-x64": {
26
- "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-win32-x64.exe",
27
- "sha256": "50531a9f033dc22eff3ec5b2a9d10441ffdfac0e50d9acf9047e4f302e5d70d9"
26
+ "url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.12/mixdog-spawn-win32-x64.exe",
27
+ "sha256": "0070823fa03a50819077d60a407f4f8e26becafe3541ecdfabe522fc5e05a8cb"
28
28
  }
29
29
  }
30
30
  }
@@ -46,7 +46,10 @@ function verifySignature(secret, rawBody, signatureValue, parser) {
46
46
  if (!vMatch || !tMatch) return false;
47
47
  const ts = Number(tMatch[1]);
48
48
  if (!Number.isFinite(ts) || Math.abs(Date.now() - ts * 1000) > STRIPE_TOLERANCE_MS) return false;
49
- const expected = crypto.createHmac('sha256', secret).update(Buffer.concat([Buffer.from(`${tMatch[1]}.`), Buffer.from(rawBody)])).digest('hex');
49
+ const expected = crypto
50
+ .createHmac('sha256', secret)
51
+ .update(Buffer.concat([Buffer.from(`${tMatch[1]}.`), Buffer.from(rawBody)]))
52
+ .digest('hex');
50
53
  return hexDigestsEqual(vMatch[1], expected);
51
54
  }
52
55
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
@@ -1,6 +1,7 @@
1
1
  import net from 'node:net';
2
2
  import path from 'node:path';
3
3
  import { execFile } from 'node:child_process';
4
+ import { FETCH_BLOCKED_PORTS, FETCH_SAFE_ATTEMPTS } from '../../shared/fetch-safe-listen.mjs';
4
5
 
5
6
  // whisper.cpp cannot bind port 0 itself. Ask the OS for an available port,
6
7
  // release the reservation immediately before spawn, then verify the listener's
@@ -15,9 +16,17 @@ export function selectWhisperPort(host, preferred) {
15
16
  server.close((error) => (error ? reject(error) : resolve(selected)));
16
17
  });
17
18
  });
19
+ // The server is reached with fetch, which refuses a "bad port" the OS may assign.
20
+ const reserveFetchSafe = async () => {
21
+ for (let attempt = 0; attempt <= FETCH_SAFE_ATTEMPTS; attempt += 1) {
22
+ const port = await reserve(0);
23
+ if (!FETCH_BLOCKED_PORTS.has(port)) return port;
24
+ }
25
+ throw new Error('no fetch-safe loopback port was assigned');
26
+ };
18
27
  return reserve(preferred).catch((error) => {
19
28
  if (error.code !== 'EADDRINUSE' && error.code !== 'EACCES') throw error;
20
- return reserve(0);
29
+ return reserveFetchSafe();
21
30
  });
22
31
  }
23
32
 
@@ -39,22 +48,31 @@ function runOwnershipQuery(command, args) {
39
48
  });
40
49
  }
41
50
 
51
+ // Get-NetTCPConnection prints one OwningProcess number per line: no localized words.
52
+ export function listenerPidsInclude(stdout, pid) {
53
+ return stdout.split(/\r?\n/).some((line) => line.trim() === String(pid));
54
+ }
55
+
42
56
  export async function whisperListenerOwned(host, port, pid) {
43
57
  if (!Number.isInteger(pid) || pid <= 0 || !Number.isInteger(port)) return false;
44
58
  try {
45
59
  if (process.platform === 'win32') {
46
60
  const root = process.env.SystemRoot || 'C:\\Windows';
47
- const stdout = await runOwnershipQuery(path.join(root, 'System32', 'netstat.exe'), ['-ano', '-p', 'tcp']);
61
+ // netstat omits listeners when the TCP table is large; the CIM-backed cmdlet does not.
62
+ // The State filter is skipped (it can report an unknown state for live listeners);
63
+ // a listening row is the one with no remote endpoint (RemotePort 0).
64
+ if (!/^[0-9a-fA-F:.]+$/.test(host)) return false;
65
+ const stdout = await runOwnershipQuery(
66
+ path.join(root, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe'),
67
+ [
68
+ '-NoProfile',
69
+ '-NonInteractive',
70
+ '-Command',
71
+ `(Get-NetTCPConnection -LocalAddress '${host}' -LocalPort ${port} -ErrorAction SilentlyContinue | Where-Object RemotePort -eq 0).OwningProcess`,
72
+ ]
73
+ );
48
74
  if (stdout === null) return false;
49
- return stdout.split(/\r?\n/).some((line) => {
50
- const fields = line.trim().split(/\s+/);
51
- return (
52
- fields[0] === 'TCP' &&
53
- fields[1] === `${host}:${port}` &&
54
- fields[3] === 'LISTENING' &&
55
- fields[4] === String(pid)
56
- );
57
- });
75
+ return listenerPidsInclude(stdout, pid);
58
76
  }
59
77
  if (process.platform === 'linux') {
60
78
  const stdout = await runOwnershipQuery('ss', ['-H', '-ltnp', `sport = :${port}`]);
@@ -80,6 +80,9 @@ const mgr = {
80
80
  child: null, // ChildProcess handle (non-detached)
81
81
  port: null, // selected port; must belong to the current child
82
82
  host: null,
83
+ // Ownership proven for this child+port. A live child keeps its bound port, so
84
+ // no other process can take it; cleared whenever the child goes away.
85
+ proof: null, // { child, port }
83
86
  runtimeKey: null, // exact contract fingerprint
84
87
  contract: null, // { serverCmd, modelPath, threadCount, host }
85
88
  startPromise: null, // in-flight ensureReady() start
@@ -330,6 +333,7 @@ async function teardown(reason) {
330
333
  }
331
334
  }
332
335
  mgr.child = null;
336
+ mgr.proof = null;
333
337
  mgr.port = null;
334
338
  mgr.host = null;
335
339
  mgr.runtimeKey = null;
@@ -357,6 +361,7 @@ function wireChildExit() {
357
361
  detachChildHandlers();
358
362
  clearPidMeta();
359
363
  mgr.child = null;
364
+ mgr.proof = null;
360
365
  mgr.port = null;
361
366
  mgr.runtimeKey = null;
362
367
  mgr.contract = null;
@@ -435,6 +440,7 @@ async function startServer(contract) {
435
440
  mgr.state === STATE.STARTING
436
441
  ) {
437
442
  mgr.port = port;
443
+ mgr.proof = { child, port };
438
444
  mgr.state = STATE.READY;
439
445
  return;
440
446
  }
@@ -509,7 +515,10 @@ export async function transcribe(wavPath, { language } = {}) {
509
515
  try {
510
516
  const [data, owned] = await Promise.all([
511
517
  fs.promises.readFile(wavPath),
512
- whisperListenerOwned(host, port, child.pid),
518
+ // Proven at readiness for this live child; re-prove only without that proof.
519
+ mgr.proof?.child === child && mgr.proof.port === port && child.exitCode === null
520
+ ? true
521
+ : whisperListenerOwned(host, port, child.pid),
513
522
  ]);
514
523
  // Re-check after the awaits: a replacement listener (or child) must never
515
524
  // receive audio. Nothing awaits between this check and the request.
@@ -362,13 +362,13 @@ export const COMPUTER_ACTION_CONTRACTS = [
362
362
  type: 'string',
363
363
  minLength: 1,
364
364
  description:
365
- "Fallback sign-in in the user's own browser; prefer its existing session/SSO or Browser Use's saved sign-in. Saved login (username or masked label; a miss lists the site's labels) written after host checks into the focused field of a Chrome/Edge HTTPS page. The site receives it. A password is kept from you and its browser's pixels are withheld this turn, but a page that redisplays it can expose it, and other programs of the same Windows user are outside this protection; a username is not hidden. On refusal hand the secret to the user (ask_user secret, surface computer).",
365
+ "Fallback sign-in in the user's own browser; prefer its existing session/SSO or Browser Use's saved sign-in. Saved login (username or masked label; a miss lists the site's labels) written after host checks into the focused field of a Chrome/Edge HTTPS page. The site receives it. A password is kept from you and its browser's pixels are withheld this turn, but a page that redisplays it can expose it, and other programs of the same Windows user are outside this protection; a username is not hidden. On refusal hand the secret to the user (handoff_user secret, surface computer).",
366
366
  },
367
367
  field: {
368
368
  type: 'string',
369
369
  enum: SAVED_LOGIN_FIELDS,
370
370
  description:
371
- "username (text field) or password (password field). One-time codes, passkeys, security keys and app approvals are the user's step: ask_user takeover.",
371
+ "username (text field) or password (password field). One-time codes, passkeys, security keys and app approvals are the user's step: handoff_user takeover.",
372
372
  },
373
373
  },
374
374
  ['savedAccount', 'field']
@@ -74,13 +74,13 @@ export const COMPUTER_CORE_ACTION_SCHEMA = {
74
74
  text: {
75
75
  type: 'string',
76
76
  maxLength: 30_000,
77
- description: `Literal text; foreground cap ${MAX_COMPUTER_FOREGROUND_TEXT_CHARS} UTF-16 code units per action. Never a password or one-time code, even one shown on screen: saved_login or ask_user.`,
77
+ description: `Literal text; foreground cap ${MAX_COMPUTER_FOREGROUND_TEXT_CHARS} UTF-16 code units per action. Never a password or one-time code, even one shown on screen: saved_login or handoff_user.`,
78
78
  },
79
79
  value: {
80
80
  type: 'string',
81
81
  maxLength: 30_000,
82
82
  description:
83
- 'set_value replacement for an element that advertises set_value; writes the control directly, without focus or keystrokes. Never a password or one-time code, even one shown on screen: saved_login or ask_user.',
83
+ 'set_value replacement for an element that advertises set_value; writes the control directly, without focus or keystrokes. Never a password or one-time code, even one shown on screen: saved_login or handoff_user.',
84
84
  },
85
85
  keys: {
86
86
  type: 'string',
@@ -31,8 +31,9 @@ const CLEANUP_CODES = new Set([
31
31
  const PIXEL_CODES = new Set(['pixel_unavailable', 'observation_unavailable']);
32
32
  // Saved-login refusals made before anything was written (host/saved-login.ts).
33
33
  const SAVED_LOGIN_REFUSAL_CODES = new Set(['saved_login_refused', 'saved_login_changed', 'saved_login_unavailable']);
34
- const SECRET_HANDOFF = 'hand the secret to the user with ask_user (kind "secret", surface "computer")';
35
- const STEP_HANDOFF = 'hand the step to the user with ask_user (kind "takeover", surface "computer", need "sign_in")';
34
+ const SECRET_HANDOFF = 'hand the secret to the user with handoff_user (kind "secret", surface "computer")';
35
+ const STEP_HANDOFF =
36
+ 'hand the step to the user with handoff_user (kind "takeover", surface "computer", need "sign_in")';
36
37
  // Reads send no input, so their timeout is a provider budget, not an uncertain
37
38
  // mutation: the caller needs another read route, not a cleanup investigation.
38
39
  const READ_ONLY_ACTIONS = new Set(['capture', 'list', 'diagnose', 'verify']);
@@ -157,14 +158,14 @@ function recoveryForCode(code, args) {
157
158
  if (SAVED_LOGIN_REFUSAL_CODES.has(code)) {
158
159
  return {
159
160
  code,
160
- next: 'ask_user',
161
+ next: 'handoff_user',
161
162
  guidance: `Nothing was written. If the refusal lists stored masked labels and the user's account is one of them, use that label; otherwise ${SECRET_HANDOFF}. Never type the secret yourself or try another window or field to get past the check.`,
162
163
  };
163
164
  }
164
165
  if (code === 'saved_login_unconfirmed') {
165
166
  return {
166
167
  code,
167
- next: 'ask_user',
168
+ next: 'handoff_user',
168
169
  guidance: `The saved value may have been written. Do not call saved_login again for this field and do not type it yourself; ${STEP_HANDOFF} to check the field and finish signing in.`,
169
170
  };
170
171
  }
@@ -14,15 +14,34 @@
14
14
  // pointer/keyboard the input device (uinput on Wayland, XTest on X11).
15
15
 
16
16
  const WINDOW_ACTIONS = new Set([
17
- 'list_windows', 'window_snapshot', 'related_windows', 'window_bounds', 'window_capture',
18
- 'window_integrity', 'validate_background_input', 'list_apps', 'verify', 'focus_window',
19
- 'move_window', 'window_state', 'close_window', 'terminate_process',
17
+ 'list_windows',
18
+ 'window_snapshot',
19
+ 'related_windows',
20
+ 'window_bounds',
21
+ 'window_capture',
22
+ 'window_integrity',
23
+ 'validate_background_input',
24
+ 'list_apps',
25
+ 'verify',
26
+ 'focus_window',
27
+ 'move_window',
28
+ 'window_state',
29
+ 'close_window',
30
+ 'terminate_process',
20
31
  ]);
21
32
  const ACCESSIBILITY_ACTIONS = new Set(['snapshot', 'find', 'window_predicates', 'accessibility_probe']);
22
33
  const SEMANTIC_ACTIONS = new Set(['invoke', 'set_value', 'toggle', 'invoke_menu']);
23
34
  const POINTER_ACTIONS = new Set([
24
- 'click', 'double_click', 'right_click', 'middle_click', 'triple_click',
25
- 'mouse_down', 'mouse_up', 'mouse_move', 'drag', 'scroll',
35
+ 'click',
36
+ 'double_click',
37
+ 'right_click',
38
+ 'middle_click',
39
+ 'triple_click',
40
+ 'mouse_down',
41
+ 'mouse_up',
42
+ 'mouse_move',
43
+ 'drag',
44
+ 'scroll',
26
45
  ]);
27
46
  const KEYBOARD_ACTIONS = new Set(['type', 'key', 'key_down', 'key_up']);
28
47
 
@@ -35,7 +35,10 @@ export interface LinuxComputerRefusal {
35
35
  export const MIN_WINDOW_HELPER_VERSION: number;
36
36
  export const CAPABILITY_UNAVAILABLE_CODE: 'computer_capability_unavailable';
37
37
  export function detectSession(env: Record<string, string | undefined>): 'wayland' | 'x11';
38
- export function detectDesktop(env: Record<string, string | undefined>, session: 'wayland' | 'x11'): LinuxComputerReadiness['desktop'];
38
+ export function detectDesktop(
39
+ env: Record<string, string | undefined>,
40
+ session: 'wayland' | 'x11'
41
+ ): LinuxComputerReadiness['desktop'];
39
42
  export function checkLinuxComputerReadiness(options?: Record<string, unknown>): Promise<LinuxComputerReadiness>;
40
43
  export function getLinuxComputerReadiness(options?: Record<string, unknown>): Promise<LinuxComputerReadiness>;
41
44
  export function missingCapabilities(
@@ -47,4 +50,6 @@ export function resetLinuxComputerPreflightCache(): void;
47
50
  export const GNOME_EXTENSION_UUID: 'mixdog-windows@mixdog.io';
48
51
  export function gnomeExtensionDirs(env?: Record<string, string | undefined>): string[];
49
52
  export const CAPTURE_FALLBACK_NOTE: string;
50
- export function linuxCaptureFallback(options?: Record<string, unknown>): Promise<{ command: Record<string, unknown>; note: string } | null>;
53
+ export function linuxCaptureFallback(
54
+ options?: Record<string, unknown>
55
+ ): Promise<{ command: Record<string, unknown>; note: string } | null>;