mixdog 1.2.5 → 1.3.0

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/LICENSES/simple-icons-CC0-1.0.txt +30 -0
  2. package/NOTICE.md +19 -0
  3. package/package.json +4 -1
  4. package/scripts/check-model-recommendations.mjs +89 -0
  5. package/scripts/gate-local.mjs +7 -0
  6. package/scripts/lib/gate-scheduler.mjs +2 -2
  7. package/scripts/lib/isolated-test-env.mjs +16 -0
  8. package/scripts/lib/run-node-tests.mjs +5 -14
  9. package/scripts/provider-pingpong-live.mjs +9 -9
  10. package/src/agents/advisor/AGENT.md +4 -4
  11. package/src/agents/advisor/agent.json +1 -1
  12. package/src/agents/reviewer/AGENT.md +5 -4
  13. package/src/agents/reviewer/agent.json +1 -1
  14. package/src/defaults/shipped-history.json +17 -0
  15. package/src/defaults/skills/browser-use/SKILL.md +7 -1
  16. package/src/defaults/skills/computer-use/SKILL.md +3 -1
  17. package/src/defaults/skills/memory-management/SKILL.md +4 -1
  18. package/src/defaults/skills/setup/references/actions.md +11 -4
  19. package/src/defaults/skills/setup-guide/SKILL.md +175 -0
  20. package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
  21. package/src/defaults/skills/visualize/SKILL.md +3 -2
  22. package/src/lib/rules-builder.cjs +56 -7
  23. package/src/output-styles/common.md +22 -6
  24. package/src/output-styles/detailed.md +7 -5
  25. package/src/output-styles/minimal.md +7 -3
  26. package/src/output-styles/simple.md +2 -3
  27. package/src/rules/agent/AGENT.md +7 -1
  28. package/src/rules/agent-mode/AGENT_MODE.md +24 -0
  29. package/src/rules/agent-mode/MIXY.md +21 -0
  30. package/src/rules/agent-mode/ROUTINE.md +6 -0
  31. package/src/rules/lead/LEAD.md +9 -4
  32. package/src/rules/shared/10-tool-workflow.md +2 -1
  33. package/src/rules/shared/60-verification.md +4 -5
  34. package/src/rules/shared/70-delivery.md +3 -0
  35. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
  36. package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
  37. package/src/runtime/agent/orchestrator/config.mjs +6 -0
  38. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
  39. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +182 -13
  40. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +5 -3
  41. package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
  42. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +215 -0
  43. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +58 -64
  44. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
  45. package/src/runtime/agent/orchestrator/mcp/client.mjs +122 -15
  46. package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
  47. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
  48. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
  49. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
  50. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
  51. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
  52. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
  53. package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
  54. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
  55. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  56. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +41 -19
  57. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
  58. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
  59. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
  60. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
  61. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
  62. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
  63. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +11 -5
  64. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
  65. package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
  66. package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
  69. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
  70. package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
  71. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
  72. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  74. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
  75. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  76. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
  78. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
  79. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
  80. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  81. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
  82. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  83. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
  84. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
  85. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
  86. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
  88. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
  89. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
  90. package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
  91. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
  92. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
  93. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
  94. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
  95. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
  96. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
  97. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
  98. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
  99. package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
  100. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +98 -4
  101. package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
  102. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
  103. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +15 -8
  104. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
  105. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
  106. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
  107. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -4
  108. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +4 -1
  109. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +50 -20
  110. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
  111. package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
  112. package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
  113. package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
  114. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
  115. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
  116. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
  117. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +162 -0
  118. package/src/runtime/agent/orchestrator/session/agent-room.mjs +641 -0
  119. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
  120. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
  121. package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
  122. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
  123. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
  124. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
  125. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
  126. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +165 -0
  127. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
  128. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
  129. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
  130. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
  131. package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
  132. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
  133. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
  134. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
  135. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +16 -1
  136. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +82 -33
  137. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +11 -4
  138. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
  139. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
  140. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +7 -0
  141. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
  142. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +6 -1
  143. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  144. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
  145. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
  146. package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
  147. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
  148. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
  149. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
  150. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
  151. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
  152. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
  153. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
  154. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -5
  155. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +55 -8
  156. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
  157. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
  158. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
  159. package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
  160. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
  161. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +24 -0
  162. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
  163. package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
  164. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +70 -0
  165. package/src/runtime/agent/orchestrator/session/routine-result.mjs +277 -0
  166. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
  167. package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
  168. package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
  169. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
  170. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
  171. package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
  172. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
  173. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
  174. package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
  175. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
  176. package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +325 -0
  177. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +84 -21
  178. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
  179. package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
  180. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
  181. package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
  182. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
  183. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
  184. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
  185. package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
  186. package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
  187. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
  188. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +44 -1
  189. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
  190. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
  191. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
  192. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
  193. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
  194. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
  195. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
  196. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
  197. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
  198. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
  199. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
  200. package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
  201. package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
  202. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
  203. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
  205. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
  206. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
  207. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
  208. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
  209. package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
  210. package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
  211. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
  212. package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
  213. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
  214. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
  215. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
  216. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
  217. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
  218. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
  219. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
  220. package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
  221. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +123 -32
  222. package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
  224. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
  225. package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
  226. package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
  227. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
  228. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
  229. package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
  230. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  231. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
  232. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +64 -2
  233. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +10 -2
  234. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
  235. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +8 -0
  236. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -1
  237. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
  238. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +104 -55
  239. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
  240. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
  241. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
  242. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  243. package/src/runtime/attachments/office-extract.mjs +11 -9
  244. package/src/runtime/browser-bridge/client.mjs +24 -0
  245. package/src/runtime/channels/lib/scheduler.mjs +40 -12
  246. package/src/runtime/channels/lib/schedules-db.mjs +71 -12
  247. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
  248. package/src/runtime/channels/lib/webhook.mjs +0 -1
  249. package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
  250. package/src/runtime/channels/lib/worker-main.mjs +17 -20
  251. package/src/runtime/computer-bridge/client.mjs +28 -1
  252. package/src/runtime/connectors/gmail-app-password.mjs +690 -0
  253. package/src/runtime/connectors/google-mcp.mjs +446 -0
  254. package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
  255. package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
  256. package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
  257. package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
  258. package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
  259. package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
  260. package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
  261. package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
  262. package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
  263. package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
  264. package/src/runtime/memory/lib/memory.mjs +7 -1
  265. package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
  266. package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
  267. package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
  268. package/src/runtime/memory/lib/tool-call-handler.mjs +9 -5
  269. package/src/runtime/memory/tool-defs.mjs +5 -0
  270. package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
  271. package/src/runtime/office/core/tabular.mjs +1 -1
  272. package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
  273. package/src/runtime/office/portable/docx-formatting.mjs +1 -1
  274. package/src/runtime/office/portable/docx-runs.mjs +1 -1
  275. package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
  276. package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
  277. package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
  278. package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
  279. package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
  280. package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
  281. package/src/runtime/office/portable/portable-opc.mjs +27 -13
  282. package/src/runtime/office/portable/portable-pivot.mjs +3 -3
  283. package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
  284. package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
  285. package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
  286. package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
  287. package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
  288. package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
  289. package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
  290. package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
  291. package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
  292. package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
  293. package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
  294. package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
  295. package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
  296. package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
  297. package/src/runtime/office/portable/portable-xml.mjs +1 -1
  298. package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
  299. package/src/runtime/shared/agent-avatar.d.mts +64 -0
  300. package/src/runtime/shared/agent-avatar.mjs +320 -0
  301. package/src/runtime/shared/agent-route-config.d.mts +3 -0
  302. package/src/runtime/shared/agent-route-config.mjs +16 -0
  303. package/src/runtime/shared/atomic-file.mjs +36 -14
  304. package/src/runtime/shared/background-tasks.mjs +60 -20
  305. package/src/runtime/shared/child-spawn-gate.mjs +26 -16
  306. package/src/runtime/shared/config.mjs +8 -11
  307. package/src/runtime/shared/connector-accounts.mjs +15 -0
  308. package/src/runtime/shared/connector-catalog.d.mts +52 -0
  309. package/src/runtime/shared/connector-catalog.mjs +230 -0
  310. package/src/runtime/shared/connector-triggers.d.mts +3 -0
  311. package/src/runtime/shared/connector-triggers.mjs +43 -0
  312. package/src/runtime/shared/file-lock.mjs +7 -1
  313. package/src/runtime/shared/file-permissions-worker.mjs +38 -0
  314. package/src/runtime/shared/file-permissions.d.mts +19 -4
  315. package/src/runtime/shared/file-permissions.mjs +310 -4
  316. package/src/runtime/shared/git-runner-worker.mjs +6 -78
  317. package/src/runtime/shared/google-oauth-client.mjs +24 -0
  318. package/src/runtime/shared/held-request-host.d.mts +12 -0
  319. package/src/runtime/shared/held-request-host.mjs +71 -0
  320. package/src/runtime/shared/llm/http-agent.mjs +7 -3
  321. package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
  322. package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
  323. package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
  324. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
  325. package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
  326. package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
  327. package/src/runtime/shared/memory-snapshot.mjs +5 -1
  328. package/src/runtime/shared/notify-trace.mjs +8 -1
  329. package/src/runtime/shared/plain-preview.d.mts +1 -0
  330. package/src/runtime/shared/plain-preview.mjs +28 -0
  331. package/src/runtime/shared/pristine-execution-contract.json +5 -1
  332. package/src/runtime/shared/process-runner-worker.mjs +7 -0
  333. package/src/runtime/shared/process-runner.mjs +38 -0
  334. package/src/runtime/shared/provider-accounts.mjs +2 -1
  335. package/src/runtime/shared/provider-api-key.mjs +0 -1
  336. package/src/runtime/shared/read-row-numbers.mjs +1 -1
  337. package/src/runtime/shared/resource-admission.mjs +60 -18
  338. package/src/runtime/shared/routine-limits.d.mts +11 -0
  339. package/src/runtime/shared/routine-limits.mjs +21 -0
  340. package/src/runtime/shared/routine-trigger.d.mts +10 -0
  341. package/src/runtime/shared/routine-trigger.mjs +44 -0
  342. package/src/runtime/shared/run-child.mjs +84 -0
  343. package/src/runtime/shared/schedule-model-ref.mjs +9 -10
  344. package/src/runtime/shared/session-activity-signal.mjs +23 -0
  345. package/src/runtime/shared/shell-output-summary.mjs +23 -0
  346. package/src/runtime/shared/singleton-owner.mjs +126 -42
  347. package/src/runtime/shared/slow-span.mjs +4 -12
  348. package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
  349. package/src/runtime/shared/tool-output-limit.mjs +4 -2
  350. package/src/runtime/shared/tool-output-marker.mjs +58 -0
  351. package/src/runtime/shared/transcript-metadata.mjs +10 -0
  352. package/src/runtime/shared/turn-changes.mjs +0 -8
  353. package/src/runtime/shared/usage-readout-totals.mjs +56 -0
  354. package/src/runtime/shared/user-data-guard.mjs +131 -34
  355. package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
  356. package/src/runtime/shared/worktrees/git-head.mjs +20 -2
  357. package/src/runtime/shared/worktrees/lock.mjs +3 -2
  358. package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
  359. package/src/runtime/tidy/runners/biome.mjs +3 -1
  360. package/src/runtime/tidy/shadow.mjs +2 -1
  361. package/src/runtime/web-search/index.mjs +5 -7
  362. package/src/runtime/web-search/lib/formatter.mjs +42 -6
  363. package/src/runtime/web-search/tool-defs.mjs +6 -1
  364. package/src/session-runtime/agent-home-delivery.mjs +459 -0
  365. package/src/session-runtime/agent-profile-changes.mjs +21 -0
  366. package/src/session-runtime/agent-room-delivery.mjs +92 -0
  367. package/src/session-runtime/agent-task-sessions.mjs +200 -0
  368. package/src/session-runtime/boot/apis.mjs +50 -18
  369. package/src/session-runtime/boot/facade.mjs +5 -8
  370. package/src/session-runtime/boot/infrastructure.mjs +28 -17
  371. package/src/session-runtime/boot/tools.mjs +3 -0
  372. package/src/session-runtime/channel-config-api.mjs +53 -5
  373. package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
  374. package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
  375. package/src/session-runtime/held-requests.mjs +228 -0
  376. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
  377. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
  378. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
  379. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +31 -2
  380. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  381. package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
  382. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
  383. package/src/session-runtime/lifecycle/session-switch/resume.mjs +11 -4
  384. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
  385. package/src/session-runtime/lifecycle/shared.mjs +25 -2
  386. package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
  387. package/src/session-runtime/lifecycle/teardown.mjs +5 -2
  388. package/src/session-runtime/lifecycle-api.mjs +3 -1
  389. package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
  390. package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
  391. package/src/session-runtime/mcp-oauth-login.mjs +112 -15
  392. package/src/session-runtime/model-route/set-route.mjs +14 -3
  393. package/src/session-runtime/owned-automation-run.mjs +229 -0
  394. package/src/session-runtime/provider-auth/login.mjs +10 -6
  395. package/src/session-runtime/provider-auth/setup.mjs +19 -2
  396. package/src/session-runtime/provider-catalog-cache.mjs +101 -25
  397. package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
  398. package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
  399. package/src/session-runtime/provider-models.mjs +76 -10
  400. package/src/session-runtime/provider-readiness.mjs +4 -0
  401. package/src/session-runtime/resource-api.mjs +5 -0
  402. package/src/session-runtime/resource-mcp-api.mjs +107 -13
  403. package/src/session-runtime/resource-skills-api.mjs +12 -0
  404. package/src/session-runtime/room-member-gate.mjs +48 -0
  405. package/src/session-runtime/routine-home-turn.mjs +156 -0
  406. package/src/session-runtime/routine-owner.mjs +48 -0
  407. package/src/session-runtime/schedule-session-run.mjs +30 -64
  408. package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
  409. package/src/session-runtime/services/agent-tool/helpers.mjs +10 -0
  410. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
  411. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
  412. package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
  413. package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
  414. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
  415. package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
  416. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
  417. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
  418. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
  419. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
  420. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
  421. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
  422. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
  423. package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
  424. package/src/session-runtime/services/agent-tool.mjs +20 -0
  425. package/src/session-runtime/services/channel-admin.mjs +93 -24
  426. package/src/session-runtime/services/memory-access.mjs +37 -0
  427. package/src/session-runtime/services/provider-admin.mjs +166 -59
  428. package/src/session-runtime/services/schedule-access.mjs +91 -0
  429. package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
  430. package/src/session-runtime/services/usage-dashboard.mjs +27 -69
  431. package/src/session-runtime/session-create/session-options.mjs +34 -7
  432. package/src/session-runtime/session-hooks.mjs +16 -8
  433. package/src/session-runtime/setup-tool/executor.mjs +68 -6
  434. package/src/session-runtime/setup-tool/extended-actions.mjs +72 -14
  435. package/src/session-runtime/setup-tool/settings-contract.mjs +8 -6
  436. package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
  437. package/src/session-runtime/skills-api.mjs +16 -1
  438. package/src/session-runtime/tool-policy-refresh.mjs +238 -29
  439. package/src/session-runtime/turn/session-ops.mjs +10 -3
  440. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +11 -2
  441. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +3 -0
  442. package/src/session-runtime/usage-stats-api.mjs +6 -1
  443. package/src/session-runtime/webhook-session-run.mjs +49 -67
  444. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
  445. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +556 -22
  446. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
  447. package/src/session-runtime/workflow-agents-api.mjs +4 -1
  448. package/src/standalone/channel-transport/http-routes.mjs +10 -9
  449. package/src/standalone/daemon-agent-control.mjs +1 -8
  450. package/src/standalone/daemon-desktop-runtime.mjs +20 -7
  451. package/src/standalone/daemon-owner.mjs +117 -25
  452. package/src/standalone/daemon-session-control.mjs +11 -2
  453. package/src/standalone/daemon.mjs +61 -17
  454. package/src/standalone/session-call-cache.mjs +6 -0
  455. package/src/standalone/session-protocol.mjs +28 -1
  456. package/src/standalone/session-service/retention/busy.mjs +7 -2
  457. package/src/standalone/session-service/session-calls/session-turns.mjs +9 -0
  458. package/src/standalone/session-service.mjs +19 -0
  459. package/src/standalone/session-transport/routes.mjs +7 -6
  460. package/src/tui/app/model-options.mjs +39 -2
  461. package/src/tui/app/model-picker.mjs +16 -2
  462. package/src/tui/app/provider-setup-picker.mjs +1 -2
  463. package/src/tui/app/slash-commands.mjs +20 -0
  464. package/src/tui/dist/index.mjs +487 -128
  465. package/src/tui/session/context-state.mjs +6 -1
  466. package/src/tui/session/notice-surface.mjs +35 -4
  467. package/src/tui/session/notice-text.mjs +0 -1
  468. package/src/tui/session/queue-helpers.mjs +2 -1
  469. package/src/tui/session/session-api/extensions.mjs +4 -0
  470. package/src/tui/session/session-api/intake/submission.mjs +12 -13
  471. package/src/tui/session/session-api/integrations.mjs +9 -5
  472. package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
  473. package/src/tui/session/session-api/lifecycle.mjs +17 -1
  474. package/src/tui/session/session-api/routes.mjs +48 -3
  475. package/src/tui/session/session-flow/drain.mjs +20 -3
  476. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
  477. package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
  478. package/src/tui/session/session-flow/steering.mjs +104 -24
  479. package/src/tui/session/session-flow.mjs +2 -0
  480. package/src/tui/session/tool-approval.mjs +26 -5
  481. package/src/tui/session/transcript-intake.mjs +6 -2
  482. package/src/tui/session/transcript-spill.mjs +5 -1
  483. package/src/tui/session/tui-steering-persist.mjs +65 -42
  484. package/src/tui/session/turn-live-call.mjs +56 -0
  485. package/src/tui/session/turn-stream.mjs +33 -0
  486. package/src/tui/session/turn.mjs +50 -7
  487. package/src/ui/statusline.mjs +1 -6
  488. package/src/ui/streaming-markdown-heal.mjs +24 -7
  489. package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
  490. package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
  491. package/src/workflows/default/WORKFLOW.md +9 -13
  492. package/src/session-runtime/automation-agents.mjs +0 -94
  493. package/src/session-runtime/automation-workflow.mjs +0 -59
@@ -292,20 +292,27 @@ function mergeLegacyDays(db, { days, hourly, hourlyDay, fromDay, toDay }) {
292
292
  * Compaction requests run under their own provider session id but are
293
293
  * recorded under the source session, so this is the whole conversation
294
294
  * across compactions. The same route choice as a rollup applies: a gateway
295
- * summary never doubles a detail record.
295
+ * summary never doubles a detail record. `ownerIds` adds every session
296
+ * recorded as run for one of them (a Lead's agents, theirs in turn).
296
297
  */
297
- export function readSessionUsage(db, sessionIds) {
298
+ export function readSessionUsage(db, sessionIds, ownerIds = []) {
298
299
  const total = empty();
299
300
  const rows = db
300
301
  .prepare(`
301
- WITH mine AS (
302
+ WITH RECURSIVE owned(id) AS (
303
+ SELECT o.session FROM usage_session_owners o JOIN usage_sessions s ON s.id=o.owner
304
+ WHERE s.value IN (SELECT value FROM json_each(?))
305
+ UNION
306
+ SELECT o.session FROM usage_session_owners o JOIN owned ON o.owner=owned.id
307
+ ), mine AS (
302
308
  SELECT day,route,COUNT(*) AS turns,SUM(input) AS input,SUM(output) AS output,
303
309
  SUM(cache_read) AS cache_read,SUM(cache_write) AS cache_write,
304
310
  SUM(cost_usd) AS cost_usd,SUM(duration_ms) AS duration_ms,
305
311
  SUM(CASE WHEN duration_ms>0 AND output>0 THEN output ELSE 0 END) AS speed_output,
306
312
  SUM(CASE WHEN duration_ms>0 AND output>0 THEN duration_ms ELSE 0 END) AS speed_ms
307
313
  FROM usage_events WHERE session IN (
308
- SELECT id FROM usage_sessions WHERE value IN (SELECT value FROM json_each(?)))
314
+ SELECT id FROM usage_sessions WHERE value IN (SELECT value FROM json_each(?))
315
+ UNION SELECT id FROM owned)
309
316
  GROUP BY day,route
310
317
  ), attributed AS (
311
318
  SELECT printf('%04d-%02d-%02d',m.day/10000,(m.day/100)%100,m.day%100) AS day,
@@ -320,7 +327,7 @@ export function readSessionUsage(db, sessionIds) {
320
327
  )
321
328
  SELECT a.* FROM attributed a JOIN (${best}) b USING(day,provider,model,rank)
322
329
  `)
323
- .all(JSON.stringify(sessionIds), '0000-01-01', '9999-12-31');
330
+ .all(JSON.stringify(ownerIds), JSON.stringify(sessionIds), '0000-01-01', '9999-12-31');
324
331
  let speedOutput = 0;
325
332
  let speedMs = 0;
326
333
  for (const row of rows) {
@@ -60,7 +60,7 @@ function recordBatch(ledger, rows) {
60
60
  const operations = {
61
61
  rollup: ({ path, options }) => read(path, (db) => rollupUsage(db, options)),
62
62
  rollupDelta: ({ path, options, known, now }) => read(path, (db) => rollupDelta(db, options, known, now)),
63
- sessionUsage: ({ path, sessionIds }) => read(path, (db) => readSessionUsage(db, sessionIds)),
63
+ sessionUsage: ({ path, sessionIds, ownerIds }) => read(path, (db) => readSessionUsage(db, sessionIds, ownerIds)),
64
64
  record: ({ path, rows }) => write(path, (ledger) => recordBatch(ledger, rows)),
65
65
  recordQuota: ({ path, samples }) => write(path, (ledger) => ledger.recordQuota(samples)),
66
66
  quotaHistory: ({ path, options }) => read(path, (db) => readQuotaHistory(db, options)),
@@ -78,6 +78,13 @@ const COMPACT_SCHEMA = `
78
78
  -- One session's lifetime totals (the /context footer) read that session's
79
79
  -- records only instead of scanning every record ever written.
80
80
  CREATE INDEX IF NOT EXISTS usage_events_session ON usage_events(session);
81
+ -- The session each session ran for (an agent's Lead), so a Lead's agents
82
+ -- stay countable after their own session records are gone.
83
+ CREATE TABLE IF NOT EXISTS usage_session_owners (
84
+ session INTEGER PRIMARY KEY REFERENCES usage_sessions(id),
85
+ owner INTEGER NOT NULL REFERENCES usage_sessions(id)
86
+ );
87
+ CREATE INDEX IF NOT EXISTS usage_session_owners_owner ON usage_session_owners(owner);
81
88
  `;
82
89
 
83
90
  // Preserve the old read surface. Only storage changes: every field, including
@@ -109,6 +116,7 @@ function compactEventWriter(db) {
109
116
  const insertSession = db.prepare('INSERT OR IGNORE INTO usage_sessions(value) VALUES (?)');
110
117
  const findSession = db.prepare('SELECT id FROM usage_sessions WHERE value=?');
111
118
  const insert = db.prepare('INSERT INTO usage_events VALUES (?,?,?,?,?,?,?,?,?,?,?)');
119
+ const insertOwner = db.prepare('INSERT OR IGNORE INTO usage_session_owners VALUES (?,?)');
112
120
  return (row) => {
113
121
  for (const key of ['id', 'provider', 'model', 'kind', 'source_type', 'cost_source', 'origin', 'session_id']) {
114
122
  if (row[key] == null) throw new Error(`Usage requires ${key}`);
@@ -133,6 +141,11 @@ function compactEventWriter(db) {
133
141
  const route = findRoute.get(signature).id;
134
142
  insertSession.run(String(row.session_id));
135
143
  const session = findSession.get(String(row.session_id)).id;
144
+ const owner = row.owner_session_id ? String(row.owner_session_id) : '';
145
+ if (owner && owner !== String(row.session_id)) {
146
+ insertSession.run(owner);
147
+ insertOwner.run(session, findSession.get(owner).id);
148
+ }
136
149
  insert.run(
137
150
  id,
138
151
  row.ts,
@@ -201,7 +214,6 @@ function migrateUsageLedger(db, path) {
201
214
 
202
215
  export function usageRouteKind(provider) {
203
216
  if (provider === 'mixdog-local') return 'local';
204
- if (provider === 'opencode-go') return 'quota-api';
205
217
  return provider.endsWith('-oauth') ? 'oauth' : 'api';
206
218
  }
207
219
 
@@ -273,6 +285,7 @@ export function makeUsageRecord(args) {
273
285
  model,
274
286
  kind,
275
287
  sessionId: ['no-session', '(none)'].includes(args.sessionId) ? '' : text(args.sessionId),
288
+ ...(args.ownerSessionId ? { ownerSessionId: text(args.ownerSessionId) } : {}),
276
289
  sourceType: text(args.sourceType),
277
290
  input: priced.input,
278
291
  output: num(args.outputTokens),
@@ -453,6 +466,7 @@ export class UsageLedger {
453
466
  !this.insert({
454
467
  ...row,
455
468
  session_id: row.sessionId,
469
+ owner_session_id: row.ownerSessionId,
456
470
  source_type: row.sourceType,
457
471
  cache_read: row.cacheRead,
458
472
  cache_write: row.cacheWrite,
@@ -558,10 +572,11 @@ export class UsageLedger {
558
572
  return this.workerRequest('quotaWindows', { options });
559
573
  }
560
574
 
561
- /** Every request one session made under any of its ids, compactions included, read on the ledger worker. */
562
- sessionUsageAsync(sessionIds) {
563
- if (this.path === ':memory:') return Promise.resolve().then(() => readSessionUsage(this.db, sessionIds));
564
- return this.workerRequest('sessionUsage', { sessionIds });
575
+ /** Every request one session made under any of its ids, compactions included, read on the ledger worker.
576
+ * `ownerIds` adds every session recorded as run for them, transitively. */
577
+ sessionUsageAsync(sessionIds, ownerIds = []) {
578
+ if (this.path === ':memory:') return Promise.resolve().then(() => readSessionUsage(this.db, sessionIds, ownerIds));
579
+ return this.workerRequest('sessionUsage', { sessionIds, ownerIds });
565
580
  }
566
581
 
567
582
  preserveLegacyDays(days) {
@@ -22,8 +22,12 @@ const PERIODIC_ATTRIBUTION_FREE_BYTES = 2 * 1024 * 1024 * 1024;
22
22
  let periodicTimer = null;
23
23
  let lastPressureSnapshotAt = 0;
24
24
 
25
+ // Opt-in diagnostics (MIXDOG_MEMORY_SNAPSHOT=1): every sample starts a
26
+ // PowerShell process on Windows (two for a full snapshot, requested exactly
27
+ // when the host is under memory pressure), from every process that loads
28
+ // this module. A normal install never pays for that.
25
29
  function enabled() {
26
- return process.env.MIXDOG_MEMORY_SNAPSHOT !== '0';
30
+ return process.env.MIXDOG_MEMORY_SNAPSHOT === '1';
27
31
  }
28
32
 
29
33
  function snapshotPaths() {
@@ -1,4 +1,6 @@
1
- // Lightweight always-on completion-notification trace. The display path for
1
+ // Opt-in (MIXDOG_NOTIFY_TRACE=1) completion-notification trace: off by
2
+ // default, so a normal install writes no line per delivery decision (it kept
3
+ // a multi-MB log growing in every data dir). The display path for
2
4
  // background completions is event-time only and has repeatedly failed silently
3
5
  // in the field (2026-08-17: bench shell output never rendered while the model
4
6
  // queue twin worked every time). One append-only line per decision point keeps
@@ -36,7 +38,12 @@ function tracePath() {
36
38
  return join(traceDir, 'notify-trace.log');
37
39
  }
38
40
 
41
+ function notifyTraceEnabled() {
42
+ return process.env.MIXDOG_NOTIFY_TRACE === '1';
43
+ }
44
+
39
45
  export function notifyTrace(stage, fields = {}) {
46
+ if (!notifyTraceEnabled()) return;
40
47
  try {
41
48
  const parts = [`[${new Date().toISOString()}]`, `pid=${process.pid}`, stage];
42
49
  for (const [key, value] of Object.entries(fields)) {
@@ -0,0 +1 @@
1
+ export function plainPreviewText(text: unknown): string;
@@ -0,0 +1,28 @@
1
+ // A messenger preview line reads as plain text, as KakaoTalk shows it: the
2
+ // markdown a reply was written in (bold, headings, list markers, quotes,
3
+ // code fences and spans, links, images) is dropped, its words kept.
4
+
5
+ /** `text` without markdown syntax, whitespace folded to single spaces. */
6
+ export function plainPreviewText(text) {
7
+ // HTML comments never show in markdown (a greeting's suggestions ride one).
8
+ return String(text ?? '')
9
+ .replace(/<!--[\s\S]*?(?:-->|$)/g, ' ')
10
+ .replace(/^[ \t]*(`{3,}|~{3,})[^\n]*$/gm, ' ')
11
+ .replace(/!\[([^\]]*)\]\([^)]*\)/g, '$1')
12
+ .replace(/\[([^\]]+)\]\([^)]*\)/g, '$1')
13
+ .replace(/^[ \t]{0,3}#{1,6}[ \t]+/gm, '')
14
+ .replace(/^[ \t]*>[ \t]?/gm, '')
15
+ .replace(/^[ \t]*(?:[-*+]|\d+[.)])[ \t]+(?:\[[ xX]\][ \t]+)?/gm, '')
16
+ .replace(/^[ \t]*(?:[-*_][ \t]*){3,}$/gm, ' ')
17
+ .replace(/(\*\*|__)(?=\S)([\s\S]*?\S)\1/g, '$2')
18
+ .replace(/(^|[^\w*])\*(?=\S)([^*\n]*?\S)\*(?!\w)/g, '$1$2')
19
+ .replace(/(^|[^\w_])_(?=\S)([^_\n]*?\S)_(?!\w)/g, '$1$2')
20
+ .replace(/~~(?=\S)([\s\S]*?\S)~~/g, '$1')
21
+ .replace(/`+([^`\n]*)`+/g, '$1')
22
+ .replace(/\s+/g, ' ')
23
+ .trim()
24
+ .slice(0, PREVIEW_CAP);
25
+ }
26
+
27
+ /** A safety cap only: the row clamps the shown text to two lines. */
28
+ const PREVIEW_CAP = 200;
@@ -88,6 +88,11 @@
88
88
  "credentialFile": "antigravity-oauth.json",
89
89
  "credentialPathEnv": "ANTIGRAVITY_OAUTH_CREDENTIALS_PATH",
90
90
  "modelCatalogFile": "antigravity-oauth-models.json"
91
+ },
92
+ "opencode-go-oauth": {
93
+ "credentialFile": "opencode-go-oauth.json",
94
+ "credentialPathEnv": "OPENCODE_GO_OAUTH_CREDENTIALS_PATH",
95
+ "modelCatalogFile": "opencode-go-oauth-models.json"
91
96
  }
92
97
  },
93
98
  "apiKeyProviders": {
@@ -96,7 +101,6 @@
96
101
  "gemini": "GEMINI_API_KEY",
97
102
  "deepseek": "DEEPSEEK_API_KEY",
98
103
  "xai": "XAI_API_KEY",
99
- "opencode-go": "OPENCODE_API_KEY",
100
104
  "openrouter": "OPENROUTER_API_KEY"
101
105
  },
102
106
  "personalStateCounters": [
@@ -0,0 +1,7 @@
1
+ // Worker-thread body for process-runner.mjs: helper children (process-table
2
+ // enumeration, tree kills) are spawned on this thread, never on the host
3
+ // event loop (run-child.mjs).
4
+ import { runChild } from './run-child.mjs';
5
+ import { serveWorkerRequests } from './worker-requests.mjs';
6
+
7
+ serveWorkerRequests(runChild);
@@ -0,0 +1,38 @@
1
+ // Run short helper processes from one shared worker thread, so their
2
+ // synchronous native process creation never stalls the host event loop. A
3
+ // daemon profile under heavy agent load measured single PowerShell spawns
4
+ // blocking the daemon's loop for up to 7 s each. Separate from the git
5
+ // runner's worker: a slow helper start never queues a git child behind it.
6
+ import { SHARE_ENV } from 'node:worker_threads';
7
+ import { runChild } from './run-child.mjs';
8
+ import { createWorkerRequestClient } from './worker-requests.mjs';
9
+
10
+ // Created on first use. A bundled copy of this module (the desktop service's
11
+ // CommonJS bundle) has no module URL and no worker file beside it: there the
12
+ // child is started on the calling thread, exactly as before.
13
+ let requestProcess = null;
14
+ function processClient() {
15
+ if (requestProcess !== null) return requestProcess;
16
+ try {
17
+ // SHARE_ENV: children inherit the live process environment, exactly as a
18
+ // spawn from this thread would.
19
+ requestProcess = createWorkerRequestClient(new URL('./process-runner-worker.mjs', import.meta.url), {
20
+ env: SHARE_ENV,
21
+ });
22
+ } catch {
23
+ requestProcess = false;
24
+ }
25
+ return requestProcess;
26
+ }
27
+
28
+ /**
29
+ * Resolves to { code, stdout, stderr } (a non-zero exit is the caller's to
30
+ * judge). Rejects with code ETIMEDOUT after timeoutMs (the child is killed;
31
+ * 0 sets no deadline),
32
+ * EMAXBUFFER once stdout+stderr exceed maxBytes, or the spawn error itself.
33
+ */
34
+ export function runProcessOffThread(command, args, { cwd, input = '', env = null, timeoutMs, maxBytes }) {
35
+ const request = processClient();
36
+ const payload = { command, args, cwd, input, env, timeoutMs, maxBytes };
37
+ return request ? request(payload) : runChild(payload);
38
+ }
@@ -13,6 +13,7 @@ export const ACCOUNT_PROVIDERS = Object.freeze([
13
13
  'mimo-oauth',
14
14
  'cursor-oauth',
15
15
  'antigravity-oauth',
16
+ 'opencode-go-oauth',
16
17
  ]);
17
18
  const MAX_ACCOUNTS = 20;
18
19
  // `dataDir` defaults to this process's data dir; an isolated runtime passes
@@ -79,7 +80,7 @@ function normalizeLabels(pool) {
79
80
  // only; `limit` keeps the selected account until it reaches a limit and then
80
81
  // moves to the account with the most headroom; `headroom` starts every new
81
82
  // session on the account with the most headroom and keeps it for that session.
82
- export const ACCOUNT_POLICIES = Object.freeze(['manual', 'limit', 'headroom']);
83
+ const ACCOUNT_POLICIES = Object.freeze(['manual', 'limit', 'headroom']);
83
84
 
84
85
  // `auto` predates `policy` and is still written beside it, so a build that
85
86
  // knows only `auto` reads the same switching on/off. Whenever the two
@@ -13,7 +13,6 @@ export const AGENT_PROVIDER_ENV = Object.freeze({
13
13
  gemini: 'GEMINI_API_KEY',
14
14
  deepseek: 'DEEPSEEK_API_KEY',
15
15
  xai: 'XAI_API_KEY',
16
- 'opencode-go': 'OPENCODE_API_KEY',
17
16
  openrouter: 'OPENROUTER_API_KEY',
18
17
  });
19
18
 
@@ -88,7 +88,7 @@ export function readSourceWindow(text) {
88
88
  rows.push({ number, content: row[2] });
89
89
  continue;
90
90
  }
91
- const metadata = /^\[lines (\d+)-(\d+) of (\d+)(?:; pass offset:\d+ to continue)?\]$/.exec(line);
91
+ const metadata = /^\[lines (\d+)-(\d+) of (\d+)(?:; offset:\d+ for more)?\]$/.exec(line);
92
92
  if (!metadata || footer) return null;
93
93
  footer = metadata;
94
94
  totalLines = Number(metadata[3]);
@@ -1,4 +1,4 @@
1
- import { freemem, totalmem } from 'node:os';
1
+ import { availableParallelism, freemem, totalmem } from 'node:os';
2
2
  import { AsyncLocalStorage } from 'node:async_hooks';
3
3
  import { requestMemoryPressureSnapshot } from './memory-snapshot.mjs';
4
4
  import { nonNegativeInt, positiveInt } from './numbers.mjs';
@@ -6,12 +6,20 @@ import { nonNegativeInt, positiveInt } from './numbers.mjs';
6
6
  const MB = 1024 * 1024;
7
7
 
8
8
  // The unified daemon queues bursts instead of starting an unbounded number of
9
- // agent/provider/shell tasks in one process. Environment overrides remain
10
- // available for larger hosts; memory thresholds are diagnostic only.
9
+ // agent/provider tasks in one process. Shell commands start immediately: their
10
+ // only bound is maxShells (64) live foreground commands, a runaway guard
11
+ // rather than a CPU budget; the OS shares the cores. Environment overrides remain available; memory thresholds
12
+ // are diagnostic only.
13
+ // Agent leases are held only while an agent runs tools (they yield during
14
+ // provider I/O) and their tool work is mostly child-process I/O, so two per
15
+ // core keeps the host busy: 30-agent stress on 20 cores halved wall time at
16
+ // 40 versus 8 with no event-loop or memory cost. 8 is the floor for small
17
+ // hosts. maxHighLoad now bounds agents only and defaults to the same.
18
+ const AGENT_LIMIT = Math.max(8, 2 * availableParallelism());
11
19
  const RESOURCE_ADMISSION_DEFAULTS = Object.freeze({
12
- maxAgents: 8,
13
- maxShells: 8,
14
- maxHighLoad: 12,
20
+ maxAgents: AGENT_LIMIT,
21
+ maxShells: 64,
22
+ maxHighLoad: AGENT_LIMIT,
15
23
  maxQueue: 1024,
16
24
  minFreeMemoryMb: 0,
17
25
  maxRssMb: 0,
@@ -79,12 +87,15 @@ class ResourceAdmissionQueueFullError extends ResourcePressureError {
79
87
  * shells. Running work is never revoked: pressure only rejects a new request or
80
88
  * keeps a concurrency-blocked request in the bounded FIFO queue.
81
89
  *
82
- * A shell lease covers only the foreground part of a command: promotion to a
83
- * background job releases it (lib/shell-run-background/promote-job.mjs), so
84
- * background jobs count toward neither maxShells nor the maxHighLoad budget
85
- * shared with agents, and are not capped at all: they are mostly idle
86
- * servers/watchers at below-normal OS priority whose memory lives in their own
87
- * processes. Session/runtime close stops them (shell-jobs shutdownShellJobs).
90
+ * Shell leases are their own pool of maxShells: they are not part of the
91
+ * maxHighLoad budget, do not suspend the calling agent's lease, and never wait
92
+ * behind queued agent work, so a command starts at once unless maxShells
93
+ * commands are already running. A shell lease covers only the foreground part
94
+ * of a command: promotion to a background job releases it
95
+ * (lib/shell-run-background/promote-job.mjs), so background jobs are not
96
+ * capped at all: they are mostly idle servers/watchers at below-normal OS
97
+ * priority whose memory lives in their own processes. Session/runtime close
98
+ * stops them (shell-jobs shutdownShellJobs).
88
99
  */
89
100
  export class ResourceAdmissionController {
90
101
  constructor({ limits = {}, metrics = defaultMetrics, now = Date.now, env = process.env } = {}) {
@@ -98,6 +109,20 @@ export class ResourceAdmissionController {
98
109
  // Live leases for saturation diagnostics only (labels/ages in snapshot()).
99
110
  this.activeLeases = new Set();
100
111
  this.context = new AsyncLocalStorage();
112
+ // Admission waits by pool: first acquisition (agent/shell) and the
113
+ // reacquisition after a yielded provider call (restore). Shows whether
114
+ // the agent cap actually delays work.
115
+ this.waitStats = {};
116
+ }
117
+
118
+ _recordWait(pool, waitedMs) {
119
+ this.waitStats[pool] ??= { admitted: 0, waited: 0, totalWaitMs: 0, maxWaitMs: 0 };
120
+ const stats = this.waitStats[pool];
121
+ stats.admitted += 1;
122
+ if (waitedMs <= 0) return;
123
+ stats.waited += 1;
124
+ stats.totalWaitMs += waitedMs;
125
+ stats.maxWaitMs = Math.max(stats.maxWaitMs, waitedMs);
101
126
  }
102
127
 
103
128
  _recordMemoryPressure(kind) {
@@ -129,9 +154,14 @@ export class ResourceAdmissionController {
129
154
  }
130
155
 
131
156
  _canStart(kind) {
132
- const total = this.active.agent + this.active.shell;
133
- const kindLimit = kind === 'shell' ? this.limits.maxShells : this.limits.maxAgents;
134
- return total < this.limits.maxHighLoad && this.active[kind] < kindLimit;
157
+ if (kind === 'shell') return this.active.shell < this.limits.maxShells;
158
+ return this.active.agent < this.limits.maxHighLoad && this.active.agent < this.limits.maxAgents;
159
+ }
160
+
161
+ // Shell and agent waiters never delay each other's new requests.
162
+ _queuedInPool(lane) {
163
+ const shell = lane === 'shell';
164
+ return this.queue.some((item) => (item.kind === 'shell') === shell);
135
165
  }
136
166
 
137
167
  _adjustOwnerCount(kind, ownerKey, delta) {
@@ -240,6 +270,7 @@ export class ResourceAdmissionController {
240
270
  },
241
271
  };
242
272
  this.activeLeases.add(lease);
273
+ this._recordWait(kind, lease.queuedMs);
243
274
  return lease;
244
275
  }
245
276
 
@@ -294,8 +325,9 @@ export class ResourceAdmissionController {
294
325
  this._recordMemoryPressure(lane);
295
326
  const ambientParent = this.context.getStore();
296
327
  const detachedDependency = dependency === 'detached' && ambientParent?.controller === this;
297
- const parent = detachedDependency ? null : this._suspendParent(ambientParent);
298
- if (detachedDependency && (!this._canStart(lane) || this.queue.length > 0)) {
328
+ // A shell runs beside its agent instead of taking the agent's slot.
329
+ const parent = detachedDependency || lane === 'shell' ? null : this._suspendParent(ambientParent);
330
+ if (detachedDependency && (!this._canStart(lane) || this._queuedInPool(lane))) {
299
331
  const error = new ResourcePressureError(
300
332
  `detached nested ${lane} work has no admission capacity; retry after running work completes`,
301
333
  { kind: lane }
@@ -303,7 +335,7 @@ export class ResourceAdmissionController {
303
335
  error.code = 'ERESOURCEDEPENDENCY';
304
336
  return Promise.reject(error);
305
337
  }
306
- if (this._canStart(lane) && this.queue.length === 0) {
338
+ if (this._canStart(lane) && !this._queuedInPool(lane)) {
307
339
  const lease = this._lease(lane, null, parent, owner, taskPriority);
308
340
  lease.label = label;
309
341
  lease.signal = signal;
@@ -439,6 +471,7 @@ export class ResourceAdmissionController {
439
471
  if (item.restore) {
440
472
  item.parent.restorePending = null;
441
473
  item.parent.counted = true;
474
+ this._recordWait(`${item.kind}Restore`, Math.max(0, this.now() - item.queuedAt));
442
475
  this.active[item.kind] += 1;
443
476
  this._adjustOwnerCount(item.kind, item.ownerKey, 1);
444
477
  item.resolve();
@@ -461,6 +494,15 @@ export class ResourceAdmissionController {
461
494
  shell: this.activeByOwner.shell.size,
462
495
  },
463
496
  queued: this.queue.length,
497
+ waitStats: Object.fromEntries(
498
+ Object.entries(this.waitStats).map(([pool, stats]) => [
499
+ pool,
500
+ {
501
+ ...stats,
502
+ averageQueuedMs: stats.waited > 0 ? Math.round(stats.totalWaitMs / stats.waited) : 0,
503
+ },
504
+ ])
505
+ ),
464
506
  limits: {
465
507
  ...this.limits,
466
508
  maxAgents: wireLimit(this.limits.maxAgents),
@@ -0,0 +1,11 @@
1
+ export declare const ROUTINE_LIMITS: Readonly<{
2
+ backoffBaseMs: number;
3
+ pauseAfterFailures: number;
4
+ homeQueueLimit: number;
5
+ }>;
6
+
7
+ export declare function routineBackoffRemaining(
8
+ state: { consecutiveFailures?: unknown; lastFailedAt?: unknown } | null | undefined,
9
+ now?: number,
10
+ limits?: typeof ROUTINE_LIMITS
11
+ ): number;
@@ -0,0 +1,21 @@
1
+ // Safeguards of owned routines (schedules and webhook endpoints, see
2
+ // session-runtime/owned-automation-run.mjs): after a failure the next
3
+ // unattended fire waits `backoffBaseMs * 2^(n-1)` (n consecutive failures)
4
+ // and the routine switches itself off at `pauseAfterFailures`; a home thread
5
+ // holds at most `homeQueueLimit` routine turns waiting (and as many queued
6
+ // rows posted from outside its turns). Runs themselves are
7
+ // unlimited: no concurrency cap and no deadline.
8
+ export const ROUTINE_LIMITS = Object.freeze({
9
+ backoffBaseMs: 60_000,
10
+ pauseAfterFailures: 5,
11
+ homeQueueLimit: 200,
12
+ });
13
+
14
+ /** How long (ms) an unattended fire still waits after the routine's
15
+ * `consecutiveFailures`, the latest at `lastFailedAt`; 0 when it may run. */
16
+ export function routineBackoffRemaining(state, now = Date.now(), limits = ROUTINE_LIMITS) {
17
+ const failures = Number(state?.consecutiveFailures) || 0;
18
+ const at = state?.lastFailedAt ? new Date(state.lastFailedAt).getTime() : Number.NaN;
19
+ if (failures < 1 || !Number.isFinite(at)) return 0;
20
+ return Math.max(0, at + limits.backoffBaseMs * 2 ** (failures - 1) - now);
21
+ }
@@ -0,0 +1,10 @@
1
+ export interface RoutineTrigger {
2
+ kind: 'schedule' | 'webhook';
3
+ name: string;
4
+ event?: string;
5
+ }
6
+
7
+ export declare function routineTriggerHeader(input: { kind: string; name: string; project?: string }): string;
8
+ export declare function stripRoutineTriggerHeader(text: unknown): string;
9
+ export declare function normalizeRoutineTrigger(value: unknown): RoutineTrigger | null;
10
+ export declare function routineTriggerField(value: unknown): { routineTrigger?: RoutineTrigger };
@@ -0,0 +1,44 @@
1
+ // A routine fire delivered into its bot's home thread as a turn
2
+ // (session-runtime/routine-home-turn.mjs): the model-visible header line that
3
+ // opens the turn's prompt, and the `routineTrigger` marker its user row
4
+ // carries (live, persisted in meta.transcript, restored) so a chat paints it
5
+ // as a routine marker instead of a user bubble.
6
+
7
+ const HEADER_PREFIX = '[Routine trigger]';
8
+ const KINDS = new Set(['schedule', 'webhook']);
9
+
10
+ /** The first line of a routine turn's prompt: which routine fired and how to
11
+ * treat the turn. Only the turn's content carries it, never the system
12
+ * prompt, so the thread's prompt cache is untouched. */
13
+ export function routineTriggerHeader({ kind, name, project = '' }) {
14
+ const what = kind === 'webhook' ? 'webhook' : 'schedule';
15
+ return [
16
+ `${HEADER_PREFIX} Your ${what} "${String(name)}" fired.`,
17
+ 'Carry out its instructions below now, yourself or by delegating; nobody is watching this turn, so approvals wait for the user.',
18
+ 'Reply in this chat with the result.',
19
+ ...(project ? [`Project folder: ${project}`] : []),
20
+ ].join(' ');
21
+ }
22
+
23
+ /** `text` without the header line a routine turn opens with. */
24
+ export function stripRoutineTriggerHeader(text) {
25
+ const value = String(text ?? '');
26
+ if (!value.startsWith(HEADER_PREFIX)) return value;
27
+ const end = value.indexOf('\n');
28
+ return end < 0 ? '' : value.slice(end + 1).replace(/^\n+/, '');
29
+ }
30
+
31
+ /** A well-formed `{ kind, name, event? }` marker, or null. */
32
+ export function normalizeRoutineTrigger(value) {
33
+ if (!value || typeof value !== 'object') return null;
34
+ const name = typeof value.name === 'string' ? value.name.trim().slice(0, 200) : '';
35
+ if (!name || !KINDS.has(value.kind)) return null;
36
+ const event = typeof value.event === 'string' ? value.event.trim().slice(0, 200) : '';
37
+ return { kind: value.kind, name, ...(event ? { event } : {}) };
38
+ }
39
+
40
+ /** The `routineTrigger` field of a transcript row (absent when none). */
41
+ export function routineTriggerField(value) {
42
+ const trigger = normalizeRoutineTrigger(value?.routineTrigger);
43
+ return trigger ? { routineTrigger: trigger } : {};
44
+ }
@@ -0,0 +1,84 @@
1
+ // One child process run to completion, its output collected — the body of
2
+ // the off-thread runners (git-runner-worker.mjs, process-runner-worker.mjs).
3
+ // Starting a child process is a synchronous native call (CreateProcess on
4
+ // Windows, amplified by on-access scanning and seconds long under load), so
5
+ // those workers spawn here instead of on the host event loop.
6
+ // Resolves to { code, stdout, stderr }; rejects with code ETIMEDOUT after
7
+ // timeoutMs (the child is killed), EMAXBUFFER once stdout+stderr exceed
8
+ // maxBytes, or the spawn error itself.
9
+ import { spawn } from 'node:child_process';
10
+
11
+ export function runChild({ command, args, cwd, input, env, timeoutMs, maxBytes, stdoutEncoding = 'utf8' }) {
12
+ return new Promise((resolvePromise, rejectPromise) => {
13
+ const hasInput = (typeof input === 'string' || ArrayBuffer.isView(input)) && input.length > 0;
14
+ const child = spawn(command, args, {
15
+ cwd,
16
+ ...(env ? { env } : {}),
17
+ windowsHide: true,
18
+ stdio: [hasInput ? 'pipe' : 'ignore', 'pipe', 'pipe'],
19
+ });
20
+ const stdout = [];
21
+ const stderr = [];
22
+ let outputBytes = 0;
23
+ let stdinError = null;
24
+ let settled = false;
25
+ const finish = (error, result) => {
26
+ if (settled) return;
27
+ settled = true;
28
+ clearTimeout(timer);
29
+ if (error) rejectPromise(error);
30
+ else resolvePromise(result);
31
+ };
32
+ // timeoutMs 0: no deadline (the caller's own work bounds the child).
33
+ const timer =
34
+ timeoutMs > 0
35
+ ? setTimeout(() => {
36
+ const error = new Error(`${command} ${args.join(' ')} timed out after ${timeoutMs}ms`);
37
+ error.code = 'ETIMEDOUT';
38
+ try {
39
+ child.kill();
40
+ } catch {}
41
+ finish(error);
42
+ }, timeoutMs)
43
+ : null;
44
+ const collect = (chunks, chunk) => {
45
+ const next = Buffer.from(chunk);
46
+ outputBytes += next.length;
47
+ if (outputBytes > maxBytes) {
48
+ const error = new Error(`${command} ${args.join(' ')} exceeded ${maxBytes} output bytes`);
49
+ error.code = 'EMAXBUFFER';
50
+ try {
51
+ child.kill();
52
+ } catch {}
53
+ finish(error);
54
+ return;
55
+ }
56
+ chunks.push(next);
57
+ };
58
+ child.stdout.on('data', (chunk) => collect(stdout, chunk));
59
+ child.stderr.on('data', (chunk) => collect(stderr, chunk));
60
+ child.once('error', (error) => finish(error));
61
+ child.once('close', (code) => {
62
+ const result = {
63
+ code: Number(code ?? 1),
64
+ // 'base64' keeps non-UTF-8 bytes (a replayable patch) intact across the thread hop.
65
+ stdout: Buffer.concat(stdout).toString(stdoutEncoding === 'base64' ? 'base64' : 'utf8'),
66
+ stderr: Buffer.concat(stderr).toString('utf8'),
67
+ };
68
+ // A failed stdin write only matters when the child otherwise reported success.
69
+ if (stdinError && result.code === 0) {
70
+ finish(stdinError);
71
+ return;
72
+ }
73
+ finish(null, result);
74
+ });
75
+ if (child.stdin) {
76
+ // A short-lived child can close before stdin is flushed. Keep that
77
+ // transport race inside this promise instead of an unhandled EPIPE.
78
+ child.stdin.on('error', (error) => {
79
+ stdinError = error;
80
+ });
81
+ child.stdin.end(input);
82
+ }
83
+ });
84
+ }
@@ -1,13 +1,12 @@
1
- // schedule.model wire format shared by the channels-worker scheduler and the
2
- // engine-side run-now dispatch: either a config.presets id/name (legacy) or a
3
- // direct "provider/model[@effort][+fast][+noauto][?parameter=value]" route string
4
- // written by the desktop schedule editor (`+noauto`: Auto effort off for the
5
- // route; absent means on). Slash-form values become direct route
6
- // objects, which agent-dispatch consumes without a presets lookup.
7
- // The optional route fields an automation run carries, from a preset, a
8
- // maintenance slot or a parsed route ref. One shape so schedule and webhook
9
- // runs cannot drift when a field is added. modelParameters is copied so a
10
- // stored preset can never be mutated through the run.
1
+ // Model route-ref wire format (task sessions, provider model caches): either a
2
+ // config.presets id/name (legacy) or a direct
3
+ // "provider/model[@effort][+fast][+noauto][?parameter=value]" route string
4
+ // (`+noauto`: Auto effort off for the route; absent means on). Slash-form
5
+ // values become direct route objects, which agent-dispatch consumes without a
6
+ // presets lookup.
7
+ // The optional route fields a run carries, from a preset, a maintenance slot
8
+ // or a parsed route ref. modelParameters is copied so a stored preset can
9
+ // never be mutated through the run.
11
10
  export function modelRouteFields(slot = {}) {
12
11
  return {
13
12
  provider: slot.provider,