mixdog 1.4.2 → 1.4.3

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 (417) hide show
  1. package/package.json +2 -2
  2. package/scripts/build-shipped-history.mjs +15 -5
  3. package/scripts/gate-local.mjs +65 -19
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +2 -1
  6. package/scripts/lib/run-node-tests.mjs +17 -5
  7. package/scripts/lib/test-failure-summary.mjs +1 -8
  8. package/scripts/lib/test-spawn-ledger.mjs +33 -2
  9. package/scripts/post-release-check.mjs +26 -16
  10. package/scripts/provider-pingpong-live.mjs +1 -1
  11. package/scripts/prune-embedding-runtime.mjs +3 -1
  12. package/scripts/release-paths.mjs +7 -1
  13. package/src/defaults/shipped-history.json +20 -0
  14. package/src/defaults/skills/setup/SKILL.md +2 -2
  15. package/src/defaults/skills/setup/references/actions.md +16 -3
  16. package/src/defaults/skills/setup/references/surfaces.md +3 -0
  17. package/src/defaults/skills/setup-guide/SKILL.md +6 -1
  18. package/src/lib/instruction-text.cjs +36 -0
  19. package/src/lib/rules-builder.cjs +34 -20
  20. package/src/orchestration/balanced.md +23 -0
  21. package/src/orchestration/focused.md +22 -0
  22. package/src/orchestration/none.md +5 -0
  23. package/src/orchestration/swarm.md +24 -0
  24. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  25. package/src/rules/agent-mode/MIXY.md +2 -2
  26. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +0 -1
  28. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +4 -2
  29. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +0 -9
  30. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  31. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  32. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  33. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +4 -4
  34. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -1
  35. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +199 -46
  36. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +3 -5
  37. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +9 -3
  38. package/src/runtime/agent/orchestrator/mcp/client.mjs +3 -5
  39. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  40. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  41. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  42. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  43. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  45. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  46. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  47. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  48. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  49. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  50. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  51. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  52. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +10 -1
  53. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  54. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +30 -0
  55. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  56. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  57. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  58. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  59. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  60. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  61. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  62. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  63. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  64. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  65. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  66. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  67. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  68. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  69. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  70. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -48
  71. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  72. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  73. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  74. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +9 -0
  75. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  76. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +1 -1
  77. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  79. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  80. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  81. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +2 -2
  82. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  83. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  84. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  85. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  86. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  87. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  88. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +1 -1
  89. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +1 -1
  90. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +1 -1
  91. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  92. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +1 -2
  94. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  97. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  99. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  100. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  101. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  102. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  103. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  104. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  105. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  106. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +6 -1
  107. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  108. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  109. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  110. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +57 -26
  111. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  112. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  113. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  114. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  115. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  116. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  117. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  118. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  119. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  120. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  121. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  122. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  123. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  124. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  125. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  126. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +19 -0
  127. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +19 -10
  128. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +5 -0
  129. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  130. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +31 -0
  131. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  132. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +42 -6
  133. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  134. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +11 -1
  135. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  136. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  137. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  138. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  139. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  140. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +1 -1
  141. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  142. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  143. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +1 -1
  144. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  145. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  146. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  147. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  148. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  149. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  150. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  151. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  152. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  153. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +14 -5
  154. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +2 -2
  155. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  156. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  157. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  158. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  159. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  160. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  161. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  162. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  163. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  164. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  165. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  166. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  167. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +7 -3
  168. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +27 -9
  169. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  170. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  172. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  173. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +1 -2
  174. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  175. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  176. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  177. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  178. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  179. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  180. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  181. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  182. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +2 -2
  183. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +1 -1
  184. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +0 -4
  185. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  186. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  187. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  188. package/src/runtime/attachments/store.d.mts +1 -0
  189. package/src/runtime/attachments/store.mjs +2 -2
  190. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  191. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  192. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  193. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  194. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  195. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  196. package/src/runtime/channels/lib/whisper-server.mjs +12 -12
  197. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  198. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  199. package/src/runtime/connectors/connector-accounts-mcp.mjs +169 -33
  200. package/src/runtime/connectors/gmail-app-password.mjs +2 -2
  201. package/src/runtime/connectors/google-mcp.mjs +1 -1
  202. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  203. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  204. package/src/runtime/explore/explorer.mjs +0 -5
  205. package/src/runtime/explore/tool.mjs +3 -3
  206. package/src/runtime/local-provider/hardware.mjs +1 -1
  207. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  208. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  209. package/src/runtime/media/media-usage.mjs +1 -1
  210. package/src/runtime/media/store.mjs +1 -1
  211. package/src/runtime/memory/index.mjs +11 -1
  212. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  213. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  214. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  215. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  216. package/src/runtime/memory/lib/memory.mjs +17 -0
  217. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  218. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  219. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  220. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  221. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  222. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  223. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  224. package/src/runtime/office/capabilities.mjs +1 -1
  225. package/src/runtime/office/core/office-core.mjs +1 -1
  226. package/src/runtime/office/design/content-model.mjs +3 -3
  227. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  228. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  229. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  230. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  231. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  232. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  233. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  234. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  235. package/src/runtime/shared/atomic-file.d.mts +8 -0
  236. package/src/runtime/shared/background-tasks.mjs +22 -4
  237. package/src/runtime/shared/background-wait.mjs +66 -0
  238. package/src/runtime/shared/child-guardian.mjs +17 -7
  239. package/src/runtime/shared/config.mjs +313 -16
  240. package/src/runtime/shared/connector-catalog.d.mts +4 -5
  241. package/src/runtime/shared/connector-catalog.mjs +11 -1
  242. package/src/runtime/shared/file-lock.mjs +8 -3
  243. package/src/runtime/shared/git-runner.mjs +7 -2
  244. package/src/runtime/shared/idle-gc.mjs +30 -7
  245. package/src/runtime/shared/llm/http-agent.mjs +8 -5
  246. package/src/runtime/shared/llm/system-proxy.mjs +2 -1
  247. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  248. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  249. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  250. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  251. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  252. package/src/runtime/shared/process-runner.mjs +8 -4
  253. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  254. package/src/runtime/shared/routine-trigger.mjs +34 -0
  255. package/src/runtime/shared/run-child.d.mts +2 -1
  256. package/src/runtime/shared/run-child.mjs +70 -18
  257. package/src/runtime/shared/session-scratch.mjs +14 -2
  258. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  259. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  260. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  261. package/src/runtime/shared/tool-work-units.mjs +31 -6
  262. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  263. package/src/runtime/shared/turn-worktree-snapshot.mjs +6 -11
  264. package/src/runtime/shared/worker-requests.mjs +17 -3
  265. package/src/runtime/shared/worktrees/branch-management.mjs +1 -5
  266. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  267. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  268. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  269. package/src/runtime/shared/worktrees/git.mjs +44 -11
  270. package/src/runtime/shared/worktrees/include.mjs +6 -4
  271. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  272. package/src/runtime/shared/worktrees/manager.mjs +772 -75
  273. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  274. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  275. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  276. package/src/runtime/tidy/process.mjs +2 -1
  277. package/src/runtime/web-search/index.mjs +3 -22
  278. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  279. package/src/runtime/web-search/tool-defs.mjs +17 -26
  280. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  281. package/src/session-runtime/boot/apis.mjs +27 -4
  282. package/src/session-runtime/boot/begin.mjs +2 -0
  283. package/src/session-runtime/boot/config.mjs +10 -1
  284. package/src/session-runtime/boot/facade.mjs +1 -0
  285. package/src/session-runtime/boot/providers.mjs +70 -3
  286. package/src/session-runtime/boot/session.mjs +2 -0
  287. package/src/session-runtime/boot/tools.mjs +69 -25
  288. package/src/session-runtime/channel-config-api.mjs +1 -0
  289. package/src/session-runtime/config-change-effects.mjs +179 -0
  290. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  291. package/src/session-runtime/config-lifecycle.mjs +160 -24
  292. package/src/session-runtime/conversation-import/discovery.mjs +86 -7
  293. package/src/session-runtime/conversation-import/service.mjs +3 -2
  294. package/src/session-runtime/goal-facade-api.mjs +49 -3
  295. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  296. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  297. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +3 -11
  298. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +18 -4
  299. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  300. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  301. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  302. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  303. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  304. package/src/session-runtime/lifecycle/teardown/session-close.mjs +4 -4
  305. package/src/session-runtime/lifecycle-api.mjs +1 -0
  306. package/src/session-runtime/mcp-glue/server-catalog.mjs +14 -3
  307. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  308. package/src/session-runtime/model-route/set-route.mjs +40 -7
  309. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  310. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  311. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  312. package/src/session-runtime/provider-readiness.mjs +53 -4
  313. package/src/session-runtime/resource-api.mjs +1 -1
  314. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  315. package/src/session-runtime/resource-mcp-connector-accounts.mjs +5 -1
  316. package/src/session-runtime/resource-mcp-secrets.mjs +3 -3
  317. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  318. package/src/session-runtime/routine-executor.mjs +152 -0
  319. package/src/session-runtime/routine-home-turn.mjs +46 -5
  320. package/src/session-runtime/runtime-facade.mjs +5 -0
  321. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  322. package/src/session-runtime/schedule-session-run.mjs +1 -0
  323. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  324. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  325. package/src/session-runtime/services/agent-tool/send-flow.mjs +110 -6
  326. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  327. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  328. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +24 -6
  329. package/src/session-runtime/services/agent-tool.mjs +51 -1
  330. package/src/session-runtime/services/channel-admin.mjs +18 -0
  331. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  332. package/src/session-runtime/services/plugin-admin.mjs +4 -0
  333. package/src/session-runtime/services/seeds.mjs +7 -0
  334. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  335. package/src/session-runtime/session-create/materialize.mjs +4 -2
  336. package/src/session-runtime/session-create/session-options.mjs +2 -0
  337. package/src/session-runtime/settings-builtin-tools-api.mjs +1 -9
  338. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +1 -1
  339. package/src/session-runtime/setup-tool/executor.mjs +8 -1
  340. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  341. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  342. package/src/session-runtime/setup-tool/tool-defs.mjs +26 -1
  343. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  344. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  345. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  346. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  347. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  348. package/src/session-runtime/tool-surface.mjs +38 -1
  349. package/src/session-runtime/turn/agent-ops.mjs +10 -2
  350. package/src/session-runtime/turn/session-ops.mjs +2 -0
  351. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  352. package/src/session-runtime/turn/turn-run.mjs +1 -1
  353. package/src/session-runtime/webhook-session-run.mjs +2 -0
  354. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +1 -4
  355. package/src/session-runtime/workflow-agents-api/agent-route.mjs +3 -10
  356. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  357. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  358. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  359. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  360. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  361. package/src/session-runtime/workspace/session-view.mjs +1 -1
  362. package/src/session-runtime/workspace/transitions.mjs +20 -4
  363. package/src/session-runtime/workspace/worktree-maintenance.mjs +126 -6
  364. package/src/session-runtime/workspace/worktree-setup.mjs +13 -1
  365. package/src/session-runtime/workspace/worktree-tool.mjs +16 -0
  366. package/src/standalone/daemon-agent-control.mjs +25 -8
  367. package/src/standalone/daemon-desktop-runtime.mjs +6 -2
  368. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  369. package/src/standalone/daemon.mjs +54 -2
  370. package/src/standalone/local-session-runtime.mjs +16 -0
  371. package/src/standalone/session-client/daemon-unavailable.mjs +1 -1
  372. package/src/standalone/session-protocol.mjs +11 -0
  373. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  374. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  375. package/src/standalone/session-service/quota-resume.mjs +9 -0
  376. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  377. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  378. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  379. package/src/standalone/session-service/session-calls.mjs +2 -1
  380. package/src/tui/App.jsx +8 -0
  381. package/src/tui/app/clipboard.mjs +1 -1
  382. package/src/tui/app/create-app-pickers.mjs +2 -0
  383. package/src/tui/app/doctor.mjs +2 -2
  384. package/src/tui/app/panel-signature.mjs +1 -1
  385. package/src/tui/app/settings-picker.mjs +53 -8
  386. package/src/tui/app/shell-layout/row-budgets.mjs +2 -2
  387. package/src/tui/app/slash-commands.mjs +1 -1
  388. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  389. package/src/tui/app/slash-dispatch/session-commands.mjs +1 -1
  390. package/src/tui/app/use-prompt-queue-history.mjs +2 -2
  391. package/src/tui/app/use-transcript-activity.mjs +1 -1
  392. package/src/tui/app/use-transcript-window/geometry.mjs +1 -1
  393. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  394. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  395. package/src/tui/components/question-panel-model.mjs +4 -4
  396. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  397. package/src/tui/components/user-message-skills.mjs +1 -1
  398. package/src/tui/dist/index.mjs +309 -30
  399. package/src/tui/markdown/render-ansi.mjs +1 -1
  400. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  401. package/src/tui/session/agent-job-feed.mjs +2 -0
  402. package/src/tui/session/context-state.mjs +3 -0
  403. package/src/tui/session/quota-resume.mjs +1 -1
  404. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  405. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  406. package/src/tui/session/session-api/routes-agent-definitions.mjs +5 -0
  407. package/src/tui/session/session-api/worktree.mjs +13 -1
  408. package/src/tui/session/session-flow/drain.mjs +11 -14
  409. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  410. package/src/tui/session/turn-quiet.mjs +1 -1
  411. package/src/tui/session/turn.mjs +3 -0
  412. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  413. package/src/tui/spinner-meta.mjs +3 -3
  414. package/src/tui/spinner-verbs.mjs +2 -2
  415. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  416. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  417. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -6,7 +6,7 @@ import {
6
6
  gmailAppPasswordValue,
7
7
  connectorAccountServers,
8
8
  } from '../runtime/shared/connector-catalog.mjs';
9
- import { forgetConnectorAccountHealth, retireConnectorAccount } from '../runtime/connectors/connector-accounts-mcp.mjs';
9
+ import { forgetConnectorAccountHealth } from '../runtime/connectors/connector-accounts-mcp.mjs';
10
10
  import { oauthCredentialOf } from './resource-mcp-servers.mjs';
11
11
 
12
12
  /** Every config `servers` connects with, a multi-account server's accounts
@@ -73,13 +73,13 @@ export function createMcpServerSecrets({
73
73
  await forgetUnusedGmailAppPassword(gmailAppPasswordAccount(cfg));
74
74
  if (!cfg?.url || !cfg.oauthClientId) return;
75
75
  const servers = expandedConfigs(resolveConfiguredMcpCatalog().servers);
76
- if (!servers.some((other) => other.url === cfg.url && other.oauthClientId)) await saveOAuthClientSecret(cfg.url, '');
76
+ if (!servers.some((other) => other.url === cfg.url && other.oauthClientId))
77
+ await saveOAuthClientSecret(cfg.url, '');
77
78
  };
78
79
  // A removed account keeps no sign-in another configured server or account
79
80
  // does not share: `{ signIn, revoked }` as removeMcpServer reports it.
80
81
  const releaseAccount = async (accountCfg) => {
81
82
  forgetConnectorAccountHealth(accountCfg.name);
82
- retireConnectorAccount(accountCfg.connector, accountCfg.name);
83
83
  const address = gmailAppPasswordAccount(accountCfg);
84
84
  if (address) {
85
85
  const forgotten = await forgetUnusedGmailAppPassword(address);
@@ -29,6 +29,7 @@ export function createPluginsResourceApi({ deps, sync, decorate }) {
29
29
  pluginsStatus,
30
30
  resolveMcpCatalog = () => ({ adoption: null }),
31
31
  flushSkillsSave,
32
+ invalidateSkills,
32
33
  } = deps;
33
34
  const pluginData = () => cfgMod.getPluginData?.();
34
35
 
@@ -59,6 +60,9 @@ export function createPluginsResourceApi({ deps, sync, decorate }) {
59
60
  return { plugin, status: pluginsStatus() };
60
61
  },
61
62
  async updatePlugin(plugin = {}) {
63
+ // Windows refuses to rename a directory holding an open recursive
64
+ // skill watch, so drop the watchers before the root is swapped.
65
+ invalidateSkills?.();
62
66
  const updated = registryUpdatePlugin(pluginKey(plugin), { dataDir: pluginData() });
63
67
  await adoptPluginServerCopies();
64
68
  await sync.reconcilePluginsAndAnnounce();
@@ -0,0 +1,152 @@
1
+ /**
2
+ * A routine (schedule or webhook) may name an executor: a workflow sub-agent
3
+ * (Worker, …) on its own configured route. Each fire is then carried out by
4
+ * that sub-agent first, headless and to its end, and only its final report
5
+ * goes to the owner bot's home thread, which relays it (routine-home-turn.mjs).
6
+ * No executor = the bot does the work itself, as before.
7
+ *
8
+ * The executor is a delegatable workflow agent: never a bot (contact agent) or
9
+ * Mixy, never one that is unknown or turned off — refused when the routine is
10
+ * saved (assertRoutineExecutor) and again when it fires (a sub-agent that
11
+ * disappeared or was turned off since fails the fire; nothing falls back).
12
+ *
13
+ * The run is unattended like the bot's own routine turn: it is created under a
14
+ * session id marked as that routine's run (held-requests.mjs markUnattendedRun)
15
+ * so the sub-agent's record carries the run stamp (human-gate/delegation.mjs):
16
+ * it never asks, payments and permanent deletes are refused
17
+ * (human-gate/run-policy.mjs). A sub-agent session has no `agent`, `session`
18
+ * or `ask_user` tool (AGENT_WORKER_DENIED_TOOLS), so it can start no task
19
+ * session and ask nobody.
20
+ */
21
+ import { randomUUID } from 'node:crypto';
22
+ import { MIXY_AGENT_ID } from '../runtime/agent/orchestrator/session/agent-home.mjs';
23
+ import {
24
+ BUILTIN_SLOT_AGENT_IDS,
25
+ normalizeWorkflowId,
26
+ } from '../runtime/agent/orchestrator/runtime-core/workflow-ids.mjs';
27
+ import { storeInlineDocumentPart, storeInlineImagePart } from '../runtime/attachments/store.mjs';
28
+ import { MIXY_BOT_ID } from '../runtime/shared/agent-store.mjs';
29
+ import { automationPromptContent } from '../runtime/shared/automation-attachments.mjs';
30
+ import { routineExecutorHeader } from '../runtime/shared/routine-trigger.mjs';
31
+ import { scheduleOwnerAgentId } from './agent-home-delivery.mjs';
32
+ import { markUnattendedRun } from './held-requests.mjs';
33
+
34
+ /** `routineExecutorProblem` codes and the error each one raises. */
35
+ export const ROUTINE_EXECUTOR_PROBLEMS = Object.freeze({
36
+ unknown: (id) => `executor agent "${id}" is not an available sub-agent: pick one from the workflow agents`,
37
+ 'not-agent': (id) =>
38
+ `executor agent "${id}" is a bot, not a workflow sub-agent: pick a sub-agent such as Worker, or leave it unset`,
39
+ disabled: (id) => `executor agent "${id}" is turned off: turn it on in the workflow agents or pick another`,
40
+ });
41
+
42
+ /** The stored form of an executor id: lower-cased with dashes; null for none. */
43
+ export function normalizeExecutorAgentId(value) {
44
+ const text = typeof value === 'string' ? value.trim() : '';
45
+ return text ? normalizeWorkflowId(text, text.toLowerCase()) : null;
46
+ }
47
+
48
+ async function defaultProbe(id) {
49
+ const [{ workflowHelpers }, { getPluginData, loadConfig }, { isAgentDisabled, isContactAgentId }] = await Promise.all(
50
+ [
51
+ import('./boot/shared.mjs'),
52
+ import('../runtime/agent/orchestrator/config.mjs'),
53
+ import('../runtime/shared/agent-route-config.mjs'),
54
+ ]
55
+ );
56
+ const dataDir = getPluginData();
57
+ // The fresh scan: an agent made a moment ago counts.
58
+ const listed = workflowHelpers.listCustomAgentIds(dataDir).includes(id) && !BUILTIN_SLOT_AGENT_IDS.has(id);
59
+ const definition = listed ? workflowHelpers.loadAgentDefinition(dataDir, id) : null;
60
+ return {
61
+ listed: Boolean(definition),
62
+ contact: Boolean(definition) && isContactAgentId(id, definition.kind),
63
+ disabled: isAgentDisabled(loadConfig({ secrets: false }), id),
64
+ };
65
+ }
66
+
67
+ /** Why `id` (normalized) cannot execute a routine: a ROUTINE_EXECUTOR_PROBLEMS
68
+ * code, '' when it can. `probe(id)` → `{ listed, contact, disabled }`. */
69
+ export async function routineExecutorProblem(id, probe = defaultProbe) {
70
+ if (id === MIXY_AGENT_ID || id === MIXY_BOT_ID) return 'not-agent';
71
+ const facts = await probe(id);
72
+ if (!facts.listed) return 'unknown';
73
+ if (facts.contact) return 'not-agent';
74
+ return facts.disabled ? 'disabled' : '';
75
+ }
76
+
77
+ /** The executor id to store for a save's `executorAgentId` (null/empty = none),
78
+ * or the error naming why it cannot be one. */
79
+ export async function assertRoutineExecutor(value, probe = defaultProbe) {
80
+ if (value == null) return null;
81
+ if (typeof value !== 'string') throw new Error('executorAgentId must be a sub-agent id (a string) or null');
82
+ const id = normalizeExecutorAgentId(value);
83
+ if (!id) return null;
84
+ const problem = await routineExecutorProblem(id, probe);
85
+ if (problem) throw new Error(ROUTINE_EXECUTOR_PROBLEMS[problem](id));
86
+ return id;
87
+ }
88
+
89
+ /** An inline image/PDF/Office part as the stored reference part a sub-agent's
90
+ * prompt may carry (handoff-attachments.mjs admits references only). */
91
+ const referencePart = (part) => (part.type === 'image' ? storeInlineImagePart(part) : storeInlineDocumentPart(part));
92
+
93
+ /**
94
+ * Carry out one fire of routine `name` with sub-agent `agentId` and resolve its
95
+ * final report (trimmed text). `prompt` is the routine's instructions (plus a
96
+ * webhook's fenced payload); `ownerAgentId` the bot whose run it is. Rejects
97
+ * when the executor is no longer valid, fails, is cancelled, or `signal` aborts.
98
+ */
99
+ export async function runRoutineExecutor(
100
+ {
101
+ agentId,
102
+ kind,
103
+ name,
104
+ ownerAgentId = null,
105
+ prompt,
106
+ // The trusted part of `prompt` (the routine's instructions): the only text
107
+ // the executor's skills are selected from, never a webhook payload.
108
+ skillSelection = '',
109
+ attachments = null,
110
+ cwd = null,
111
+ signal = null,
112
+ },
113
+ { surface, probe = defaultProbe } = {}
114
+ ) {
115
+ const problem = await routineExecutorProblem(agentId, probe);
116
+ if (problem) throw new Error(`${kind} "${name}" cannot run: ${ROUTINE_EXECUTOR_PROBLEMS[problem](agentId)}`);
117
+ if (typeof surface?.runAgent !== 'function') throw new Error('routine run: the agent service is not running');
118
+ const header = routineExecutorHeader({ kind, name, project: cwd ? String(cwd) : '' });
119
+ const content = automationPromptContent(`${header}\n\n${prompt}`, attachments);
120
+ const parts = Array.isArray(content) ? content : [{ type: 'text', text: content }];
121
+ const attachmentParts = parts.slice(1).map(referencePart).filter(Boolean);
122
+ // The id the executor is created under: marked as this routine's unattended
123
+ // run for as long as it works (its record keeps the run stamp afterwards).
124
+ const parentSessionId = `routine_exec_${randomUUID()}`;
125
+ const unmark = markUnattendedRun(parentSessionId, {
126
+ kind,
127
+ agentId: scheduleOwnerAgentId({ ownerAgentId }),
128
+ name,
129
+ });
130
+ try {
131
+ const result = await surface.runAgent(
132
+ {
133
+ agent: agentId,
134
+ prompt: parts[0].text,
135
+ skillSelection: String(skillSelection ?? ''),
136
+ ...(cwd ? { cwd: String(cwd) } : {}),
137
+ ...(attachmentParts.length ? { attachmentParts } : {}),
138
+ },
139
+ { callerSessionId: parentSessionId },
140
+ { signal }
141
+ );
142
+ return String(result?.content ?? '').trim();
143
+ } catch (error) {
144
+ // The caller's own cancellation stays as it is.
145
+ if (signal?.aborted) throw error;
146
+ throw new Error(`${kind} "${name}": executor agent "${agentId}" failed: ${error?.message || error}`, {
147
+ cause: error,
148
+ });
149
+ } finally {
150
+ unmark();
151
+ }
152
+ }
@@ -14,7 +14,10 @@
14
14
  * (outbound actions are allowed within the bot's permissions; payments and
15
15
  * permanent deletes are refused, human-gate/run-policy.mjs). Resolves with the
16
16
  * reply once the turn ends; rejects when the turn fails, is cancelled, or the
17
- * caller's `signal` aborts (which also aborts the turn once it runs). A
17
+ * caller's `signal` aborts (which also aborts the turn once it runs). With an
18
+ * `executorAgentId` the fire is first carried out by that sub-agent
19
+ * (routine-executor.mjs) and the turn holds only its final report, which the
20
+ * bot relays; the quiet marker as the report wakes nobody and resolves it. A
18
21
  * heartbeat turn past its wall-clock cap is aborted and resolves with no reply
19
22
  * (`timedOut`).
20
23
  */
@@ -25,12 +28,16 @@ import { automationPromptContent } from '../runtime/shared/automation-attachment
25
28
  import { ROUTINE_LIMITS } from '../runtime/shared/routine-limits.mjs';
26
29
  import {
27
30
  HEARTBEAT_TURN_LIMITS,
31
+ ROUTINE_QUIET,
28
32
  isHeartbeatSession,
33
+ isRoutineQuietReply,
29
34
  normalizeRoutineTrigger,
35
+ routineRelayHeader,
30
36
  routineTriggerHeader,
31
37
  } from '../runtime/shared/routine-trigger.mjs';
32
38
  import { agentHomeLiveSurface, scheduleOwnerAgentId } from './agent-home-delivery.mjs';
33
39
  import { markUnattendedRun, unattendedRunOf } from './held-requests.mjs';
40
+ import { runRoutineExecutor } from './routine-executor.mjs';
34
41
 
35
42
  // Routine turns waiting or running per home thread.
36
43
  const waiting = new Map();
@@ -72,6 +79,9 @@ export async function runRoutineTurn(
72
79
  // thread and the routine trigger header.
73
80
  sessionId = null,
74
81
  header = null,
82
+ // A workflow sub-agent that carries the fire out first (routine-executor.mjs):
83
+ // the bot's turn then holds only its final report, for the bot to relay.
84
+ executorAgentId = null,
75
85
  },
76
86
  {
77
87
  surface = agentHomeLiveSurface(),
@@ -79,9 +89,10 @@ export async function runRoutineTurn(
79
89
  limit = ROUTINE_LIMITS.homeQueueLimit,
80
90
  log = (line) => process.stderr.write(`mixdog routines: ${line}\n`),
81
91
  timers = globalThis,
92
+ executor = runRoutineExecutor,
82
93
  } = {}
83
94
  ) {
84
- const body = String(prompt || '').trim();
95
+ let body = String(prompt || '').trim();
85
96
  if (!body) throw new Error(`${kind} "${name}" has no instructions`);
86
97
  if (signal?.aborted) throw abortError(signal);
87
98
  if (typeof surface?.submit !== 'function') throw new Error('routine run: the session service is not running');
@@ -91,12 +102,42 @@ export async function runRoutineTurn(
91
102
  if (!home || home.closed === true) {
92
103
  throw new Error(`the bot "${agentId}" has no chat yet: open it once in the app`);
93
104
  }
105
+ let opening = header || routineTriggerHeader({ kind, name, project: cwd ? String(cwd) : '' });
106
+ let selection = String(skillSelection ?? body);
107
+ let turnAttachments = attachments;
108
+ if (executorAgentId) {
109
+ const report = String(
110
+ (await executor(
111
+ {
112
+ agentId: executorAgentId,
113
+ kind,
114
+ name,
115
+ ownerAgentId: agentId,
116
+ prompt: body,
117
+ skillSelection: selection,
118
+ attachments,
119
+ cwd,
120
+ signal,
121
+ },
122
+ { surface }
123
+ )) ?? ''
124
+ ).trim();
125
+ if (signal?.aborted) throw abortError(signal);
126
+ if (!report) throw new Error(`${kind} "${name}": executor agent "${executorAgentId}" returned no report`);
127
+ // Nothing to tell: the bot is not woken.
128
+ if (isRoutineQuietReply(report)) return { sessionId: homeId, result: ROUTINE_QUIET };
129
+ // The bot only relays the report: it is derived from whatever the executor
130
+ // read (a webhook's payload included), so it selects no skill.
131
+ body = report;
132
+ opening = routineRelayHeader({ kind, name, executor: executorAgentId, project: cwd ? String(cwd) : '' });
133
+ selection = '';
134
+ turnAttachments = null;
135
+ }
94
136
  const queued = waiting.get(homeId) || 0;
95
137
  if (queued >= limit) throw new Error(`${limit} routine runs already wait in this bot's chat`);
96
138
  waiting.set(homeId, queued + 1);
97
139
  const trigger = normalizeRoutineTrigger({ kind, name, event });
98
- const opening = header || routineTriggerHeader({ kind, name, project: cwd ? String(cwd) : '' });
99
- const content = automationPromptContent(`${opening}\n\n${body}`, attachments);
140
+ const content = automationPromptContent(`${opening}\n\n${body}`, turnAttachments);
100
141
  return new Promise((resolve, reject) => {
101
142
  let started = false;
102
143
  let aborted = false;
@@ -150,7 +191,7 @@ export async function runRoutineTurn(
150
191
  restorable: false,
151
192
  // Esc ends this fire; it is never put back in the queue.
152
193
  abortDiscardOnAbort: true,
153
- skillSelection: String(skillSelection ?? body),
194
+ skillSelection: selection,
154
195
  transcriptMeta: { routineTrigger: trigger },
155
196
  onCommitted: () => {
156
197
  if (started) return;
@@ -24,6 +24,7 @@ export function createRuntimeFacade({
24
24
  getOrchestrationMode,
25
25
  getOutputStyle,
26
26
  getContextStatus,
27
+ getContextStatusSettled = async (options) => getContextStatus(options),
27
28
  getContextStatusForSession,
28
29
  renameSessionTitle,
29
30
  }) {
@@ -144,6 +145,10 @@ export function createRuntimeFacade({
144
145
  contextStatus(options) {
145
146
  return getContextStatus(options);
146
147
  },
148
+ /** The context status once an empty session took moved settings (async callers). */
149
+ contextStatusSettled(options) {
150
+ return getContextStatusSettled(options);
151
+ },
147
152
  contextStatusForSession(session) {
148
153
  return getContextStatusForSession(session);
149
154
  },
@@ -6,13 +6,10 @@
6
6
  // deps, so the runtime can hand them straight through.
7
7
  import {
8
8
  builtinFeatureActive,
9
- featureDisallowedToolsFor,
10
9
  localGitToolsActive,
11
10
  } from '../runtime/agent/orchestrator/runtime-core/builtin-features.mjs';
12
11
  import { recapEnabled } from '../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
13
- import { browserBridgeAvailableSync } from '../runtime/browser-bridge/client.mjs';
14
- import { computerBridgeAvailableSync } from '../runtime/computer-bridge/client.mjs';
15
- import { terminalBridgeAvailableSync } from '../runtime/terminal-bridge/client.mjs';
12
+ import { liveFeatureDisallowedTools } from '../runtime/agent/orchestrator/runtime-core/tool-availability.mjs';
16
13
 
17
14
  export function createRuntimeFeatureGates({ getConfig, getToolProfile }) {
18
15
  return {
@@ -29,12 +26,6 @@ export function createRuntimeFeatureGates({ getConfig, getToolProfile }) {
29
26
  tidyToolEnabledFn: () => builtinFeatureActive(getConfig(), 'tidy'),
30
27
  // Browser/Computer activate on live desktop-bridge presence, so the probe
31
28
  // runs per call instead of being captured at boot.
32
- featureDisallowedTools: () =>
33
- featureDisallowedToolsFor(getConfig(), {
34
- browserAvailable: browserBridgeAvailableSync(),
35
- computerAvailable: computerBridgeAvailableSync(),
36
- terminalAvailable: terminalBridgeAvailableSync(),
37
- toolProfile: getToolProfile(),
38
- }),
29
+ featureDisallowedTools: () => liveFeatureDisallowedTools(getConfig(), { toolProfile: getToolProfile() }),
39
30
  };
40
31
  }
@@ -26,6 +26,7 @@ export async function runScheduleSession(
26
26
  kind: 'schedule',
27
27
  name: schedule.name,
28
28
  ownerAgentId: schedule.ownerAgentId,
29
+ executorAgentId: schedule.executorAgentId || null,
29
30
  prompt: body,
30
31
  attachments: schedule.attachments,
31
32
  cwd: schedule.cwd || null,
@@ -84,11 +84,16 @@ export function reconcileJobCancelled(job, value) {
84
84
  } catch {}
85
85
  }
86
86
 
87
- export function reconcileJobStreamStalled(job, error) {
87
+ /** A turn that threw. `identity` is the owner-facing result shape: a failure
88
+ * after answers the turn went on past (error.carriedReport, turn-report.mjs)
89
+ * reports them with the failure. */
90
+ export function reconcileJobStreamStalled(job, error, identity = {}) {
88
91
  if (!job?.taskId || job._terminalResultValue !== undefined) return;
92
+ const report = typeof error?.carriedReport === 'string' ? error.carriedReport : '';
89
93
  try {
90
94
  reconcileBackgroundTask(job.taskId, {
91
95
  status: 'failed',
96
+ ...(report ? { result: { ...identity, content: report } } : {}),
92
97
  error,
93
98
  terminalReason: 'agent-stream-stalled',
94
99
  });
@@ -4,6 +4,8 @@
4
4
  import { resolveAgentWatchdogPolicy } from '../../../../runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs';
5
5
  import { buildAgentTaskProgressFields } from '../../agent-task-status.mjs';
6
6
  import { getProgressWatchdogState } from '../../agent-watchdog-registry.mjs';
7
+ import { _liveSessions } from '../../../../runtime/agent/orchestrator/session/store/live-state.mjs';
8
+ import { todoProgress } from '../../../../runtime/agent/orchestrator/runtime-core/todo-list.mjs';
7
9
 
8
10
  // Job statuses that can never progress again (mirrors TERMINAL_STATUSES in
9
11
  // runtime/shared/background-tasks.mjs; 'canceled' accepted defensively).
@@ -46,6 +48,11 @@ export function terminalJobFrozenFields(status, now = Date.now()) {
46
48
  * the diagnostics through renderJob/list directly. */
47
49
  export function liveAgentStatusRow(row) {
48
50
  if (!row || typeof row !== 'object') return row;
51
+ // The agent's own todo progress, from its live session only (an evicted
52
+ // idle worker is not re-read on every pulse).
53
+ const live = row.sessionId ? _liveSessions.get(row.sessionId) : null;
54
+ const todo = live ? todoProgress(live) : null;
55
+ if (todo) row = { ...row, todo };
49
56
  const {
50
57
  silent_for: _silentFor,
51
58
  staleSeconds: _staleSeconds,
@@ -7,7 +7,20 @@ import {
7
7
  watchdogPartialHandoffFromError,
8
8
  watchdogStoppedHandoff,
9
9
  } from '../../../runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs';
10
- import { clean, normalizeAgentName, resolvePrompt } from './helpers.mjs';
10
+ import { reconcileAgentSession } from '../../../runtime/agent/orchestrator/agent-runtime/session-builder.mjs';
11
+ import {
12
+ agentPresetName,
13
+ clean,
14
+ normalizeAgentName,
15
+ presetKey,
16
+ readAgentFrontmatterPermission,
17
+ resolvePrompt,
18
+ } from './helpers.mjs';
19
+ import { normalizeAgentPermission } from '../../../runtime/shared/markdown-frontmatter.mjs';
20
+ import { resolveAgentSessionPermission } from '../../../runtime/agent/orchestrator/internal-agents.mjs';
21
+ import { resolveAgentSpawnPreset } from './spawn-preset.mjs';
22
+ import { flushPendingSessionConfigWrites } from '../../config-lifecycle/config-writers.mjs';
23
+ import { AGENT_ROUTE_KEYS } from '../../agent-profile-changes.mjs';
11
24
  import { abnormalEmptyFinishError, renderResult } from './render.mjs';
12
25
  import {
13
26
  reconcileJobCancelled,
@@ -22,15 +35,38 @@ import { rebindDelegation } from '../../../runtime/agent/orchestrator/session/hu
22
35
  import { settledWorkerStatus } from './worker-index/row-liveness.mjs';
23
36
  import { whileTurnDispatched } from '../../../runtime/agent/orchestrator/session/manager/runtime-state.mjs';
24
37
  import { takeStoppedShellJobs } from '../../../runtime/agent/orchestrator/session/manager/turn-reap.mjs';
38
+ import { turnReportText } from '../../../runtime/agent/orchestrator/session/loop/turn-report.mjs';
25
39
 
26
40
  function workerResultIdentity({ session, tag, sessionId }) {
27
41
  return { tag, sessionId, agent: session.agent || null, provider: session.provider, model: session.model };
28
42
  }
29
43
 
44
+ /** A reused worker runs with the permission its agent's definition grants
45
+ * now, resolved as a spawn resolves it (spawn-plan.mjs). */
46
+ export function followAgentPermission(session, { dataDir, sourceRoot }) {
47
+ const agent = normalizeAgentName(session?.agent);
48
+ if (!agent || !dataDir) return;
49
+ const defined = normalizeAgentPermission(readAgentFrontmatterPermission(agent, dataDir, sourceRoot));
50
+ const permission = resolveAgentSessionPermission(agent, defined || null);
51
+ if (permission) session.permission = permission;
52
+ else delete session.permission;
53
+ }
54
+
30
55
  // `send` to an existing worker: resolve the live session, run one follow-up
31
56
  // turn under the progress watchdog, and reconcile the job/worker row. Busy
32
57
  // sessions queue the prompt instead.
33
- export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionSurface, registry, views, spawnFlow }) {
58
+ export function createSendFlow({
59
+ mgr,
60
+ cfgMod = null,
61
+ dataDir = null,
62
+ STANDALONE_SOURCE_ROOT = null,
63
+ defaultCwd,
64
+ sessionSurface,
65
+ canUseSessionSurface,
66
+ registry,
67
+ views,
68
+ spawnFlow,
69
+ }) {
34
70
  async function prepareSend(args, context = {}) {
35
71
  registry.refreshTagsFromSessions({ scanSessions: registry.wantsSessionScan(args), context });
36
72
  const target = clean(args.tag || args.sessionId);
@@ -51,7 +87,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
51
87
  const abnormalError = abnormalEmptyFinishError(result, session.agent || sendAgent);
52
88
  return {
53
89
  ...workerResultIdentity({ session, tag, sessionId }),
54
- content: result?.content || '',
90
+ content: turnReportText(result),
55
91
  ...(sessionSurface?.canonical === true ? { handoffOnly: true } : {}),
56
92
  ...(abnormalError ? { error: abnormalError } : {}),
57
93
  };
@@ -82,6 +118,13 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
82
118
  if (canUseSessionSurface(session)) {
83
119
  return sessionSurface.runTurn({ session, prompt, context: args.context || null, cwd, ...turnHooks });
84
120
  }
121
+ // An in-process session has no turn start of its own to reconcile it
122
+ // (a canonical child's runtime does, reconcileTurnSettings): bring its
123
+ // settings-gated tools, connectors, compaction, prompt settings and its
124
+ // agent's permission (as its definition stands: a narrowed one applies)
125
+ // to the settings now.
126
+ reconcileAgentSession(session);
127
+ followAgentPermission(session, { dataDir, sourceRoot: STANDALONE_SOURCE_ROOT });
85
128
  return mgr.askSession(sessionId, prompt, args.context || null, null, cwd, null, turnHooks);
86
129
  });
87
130
  }
@@ -129,7 +172,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
129
172
  handoffMsgStart = resolveHandoffMessageStartIndex(mgr.getSession(sessionId));
130
173
  const turnHooks = buildTurnHooks({ sessionId, notifyContext, job, turnReview, completionValue });
131
174
  const result = await runTurn(prepared, turnHooks);
132
- // Early preview no longer suppresses the canonical body notification;
175
+ // The early preview does not suppress the canonical body notification;
133
176
  // notifyTaskCompletion fires once with output via resolve/reconcile.
134
177
  const finalValue = completionValue(result);
135
178
  if (job?.status === 'cancelled') {
@@ -162,7 +205,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
162
205
  }
163
206
  finalStatus = 'error';
164
207
  noteStoppedShellJobsOnError(error, await takeStoppedShellJobs(sessionId));
165
- reconcileJobStreamStalled(job, error);
208
+ reconcileJobStreamStalled(job, error, workerResultIdentity({ session, tag, sessionId }));
166
209
  throw error;
167
210
  } finally {
168
211
  turnReview.complete();
@@ -204,8 +247,69 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
204
247
  // `send` branch AND by the `spawn` branch when an explicit tag maps to a
205
248
  // live session (reuse path). Busy sessions queue the prompt; idle ones run a
206
249
  // background send job that continues the existing session (context kept).
250
+ // A worker that runs on its agent's configured route follows that route, as
251
+ // a bot's home chat does (agent-route-follow.mjs): a model picked for the
252
+ // agent since the spawn applies from this send. A worker started on an
253
+ // explicit model or preset keeps it.
254
+ async function agentRouteToFollow({ session }) {
255
+ const agent = normalizeAgentName(session?.agent);
256
+ if (!agent || !cfgMod?.loadConfig) return null;
257
+ await flushPendingSessionConfigWrites();
258
+ let current;
259
+ try {
260
+ current = resolveAgentSpawnPreset(cfgMod.loadConfig(), { agent });
261
+ } catch {
262
+ return null;
263
+ }
264
+ const spawnedOn = clean(session.presetName || session.preset);
265
+ const own = new Set([`agent-${agent}`, agentPresetName(agent), presetKey(current.preset), current.presetName]);
266
+ if (!spawnedOn || !own.has(spawnedOn)) return null;
267
+ const preset = current.preset;
268
+ if (!preset.provider || !preset.model) return null;
269
+ // Every route key the agent's route sets (an effort or Fast change alone
270
+ // included); a key it leaves unset is the route default either way.
271
+ const value = (key, source) => {
272
+ if (key === 'fast') return source?.fast === true;
273
+ if (key === 'autoEffort') return source?.autoEffort !== false;
274
+ return source?.[key] == null ? null : JSON.stringify(source[key]);
275
+ };
276
+ const set = AGENT_ROUTE_KEYS.filter(
277
+ (key) => key === 'fast' || key === 'autoEffort' || (preset[key] !== undefined && preset[key] !== null)
278
+ );
279
+ const matches = (target) => set.every((key) => value(key, preset) === value(key, target));
280
+ // Against the route the session's next turn runs on: one held for it
281
+ // (heldRoute, an in-process worker that was busy), else its own.
282
+ if (matches(session)) {
283
+ // Saved back to the running route: an earlier hold is obsolete.
284
+ if (session.heldRoute) mgr.holdSessionRoute?.(session.id, null);
285
+ return null;
286
+ }
287
+ if (session.heldRoute && matches({ ...session, ...session.heldRoute })) return null;
288
+ const route = {};
289
+ for (const key of set) {
290
+ if (key === 'fast') route.fast = preset.fast === true;
291
+ else if (key === 'autoEffort') {
292
+ if (preset.autoEffort === false) route.autoEffort = false;
293
+ } else route[key] = preset[key];
294
+ }
295
+ return route;
296
+ }
297
+
207
298
  async function dispatchToExistingSession(requested, notifyContext, extras = {}) {
208
- const prepared = requested.route ? await applyRequestedRoute(requested) : requested;
299
+ let followed = requested.route ? null : await agentRouteToFollow(requested);
300
+ if (followed && !canUseSessionSurface(requested.session)) {
301
+ // An in-process session takes the followed route in place, between
302
+ // turns; a running one finishes on the route it started on and holds
303
+ // the new one for its next turn, which runs the queued work.
304
+ if (!views.isSessionBusy(requested.sessionId)) {
305
+ const { session } = requested;
306
+ const crossProvider = followed.provider !== session.provider || followed.model !== session.model;
307
+ mgr.updateSessionRoute?.(requested.sessionId, followed, { session, crossProvider });
308
+ } else mgr.holdSessionRoute?.(requested.sessionId, followed);
309
+ followed = null;
310
+ }
311
+ const routed = followed ? { ...requested, route: followed } : requested;
312
+ const prepared = routed.route ? await applyRequestedRoute(routed) : routed;
209
313
  const { session, sessionId, prompt } = prepared;
210
314
  const tag = registry.tagForSession(sessionId);
211
315
  if (canUseSessionSurface(session) && views.isSessionBusy(sessionId)) {
@@ -10,6 +10,7 @@ import { clean, terminalPidForContext } from '../helpers.mjs';
10
10
  import { renderResult } from '../render.mjs';
11
11
  import { closeManagedSession } from '../../../lifecycle/shared.mjs';
12
12
  import { hopOf } from '../../../../runtime/shared/bot-hops.mjs';
13
+ import { notDoneReport } from '../../../../runtime/agent/orchestrator/runtime-core/todo-list.mjs';
13
14
 
14
15
  /** The completion callback that hands a worker's result back to its caller session; null without a handoff. */
15
16
  function handoffNotifier(handoffSessionId, notifySessionCompletion) {
@@ -86,6 +87,17 @@ export function createJobStarter({ mgr, notifyStatusChange, notifySessionComplet
86
87
  }
87
88
  },
88
89
  });
90
+ // Success, failure or cancellation: the report names what the agent's own
91
+ // todo list leaves undone. The Lead never receives the list otherwise.
92
+ task.reportAppendix = () => {
93
+ const sessionId = task.meta?.sessionId || jobMeta?.sessionId;
94
+ if (!sessionId) return '';
95
+ try {
96
+ return notDoneReport(mgr.getSession(sessionId));
97
+ } catch {
98
+ return '';
99
+ }
100
+ };
89
101
  // The model's tool call that started this job owns it (its result message
90
102
  // carries the id: agent-task-starts.mjs).
91
103
  recordAgentTaskStart(notifyContext?.toolCallId, task.taskId);
@@ -22,6 +22,7 @@ import { workspaceCwdLock } from '../../../workspace/admission-gate.mjs';
22
22
  import { isContactAgentId } from '../../../../runtime/agent/orchestrator/runtime-core/workflow-ids.mjs';
23
23
  import { assertBotChainTarget } from '../../../../runtime/shared/bot-hops.mjs';
24
24
  import { actingAgentOf, delegationChainOf } from '../../../bot-chain.mjs';
25
+ import { flushPendingSessionConfigWrites } from '../../../config-lifecycle/config-writers.mjs';
25
26
 
26
27
  export function createSpawnPlanner({
27
28
  mgr = null,
@@ -36,6 +37,10 @@ export function createSpawnPlanner({
36
37
  }) {
37
38
  /** Shared spawn-prep validations (agent/preset/tag/cwd/prompt). */
38
39
  async function resolveSpawnPlan(args, callerCwd, context, prepState) {
40
+ // A setting a runtime of this process adopted (an agent's model picked a
41
+ // moment ago) is written behind a debounce: drain it so the read below
42
+ // sees what the runtimes hold in memory.
43
+ await flushPendingSessionConfigWrites();
39
44
  const config = cfgMod.loadConfig();
40
45
  const agent = normalizeAgentName(args.agent);
41
46
  if (!agent) throw new Error('agent spawn: agent is required');