mixdog 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (423) hide show
  1. package/NOTICE.md +52 -9
  2. package/README.md +8 -4
  3. package/package.json +2 -2
  4. package/scripts/native-release-status.mjs +238 -0
  5. package/src/defaults/shipped-history.json +8 -1
  6. package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
  7. package/src/defaults/skills/setup/SKILL.md +23 -1
  8. package/src/defaults/skills/setup/references/actions.md +54 -4
  9. package/src/defaults/skills/setup/references/surfaces.md +23 -3
  10. package/src/defaults/skills/setup-guide/SKILL.md +17 -10
  11. package/src/defaults/skills/visualize/SKILL.md +9 -6
  12. package/src/defaults/skills/visualize/references/craft.md +8 -1
  13. package/src/help.mjs +1 -1
  14. package/src/lib/keychain-cjs.cjs +4 -1
  15. package/src/lib/rules-builder.cjs +14 -7
  16. package/src/output-styles/common.md +13 -8
  17. package/src/rules/agent-mode/AGENT_MODE.md +9 -6
  18. package/src/rules/agent-mode/MIXY.md +11 -6
  19. package/src/rules/lead/LEAD.md +2 -2
  20. package/src/rules/shared/10-tool-workflow.md +4 -0
  21. package/src/rules/shared/20-research.md +2 -0
  22. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
  23. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
  24. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
  25. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
  26. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
  27. package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
  28. package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
  29. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
  30. package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
  31. package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
  32. package/src/runtime/agent/orchestrator/config.mjs +11 -0
  33. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +81 -16
  34. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -4
  35. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +6 -10
  36. package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
  37. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +80 -31
  38. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  40. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +67 -38
  41. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
  42. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +7 -2
  43. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
  44. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +34 -16
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
  46. package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
  47. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
  48. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
  49. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +19 -1
  50. package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
  51. package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -0
  52. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -1
  53. package/src/runtime/agent/orchestrator/providers/mixdog-local.mjs +3 -1
  54. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +1 -0
  55. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +5 -5
  56. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +9 -5
  57. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +9 -1
  58. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +8 -2
  59. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +10 -2
  60. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +30 -3
  61. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +1 -1
  62. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +3 -1
  63. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +3 -1
  64. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
  65. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +14 -2
  66. package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -0
  67. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -0
  68. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
  69. package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
  70. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
  71. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
  72. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
  73. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +5 -5
  74. package/src/runtime/agent/orchestrator/runtime-core/route-context-state.mjs +81 -0
  75. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -1
  76. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +12 -1
  77. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +17 -6
  78. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +41 -10
  79. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +6 -4
  80. package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
  81. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +2 -0
  82. package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
  83. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
  84. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
  85. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +21 -2
  86. package/src/runtime/agent/orchestrator/session/agent-room.mjs +149 -45
  87. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
  88. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  89. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +14 -11
  90. package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
  91. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +68 -18
  92. package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
  93. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
  94. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
  95. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +5 -1
  96. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +1 -1
  97. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
  99. package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +230 -0
  100. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +156 -25
  101. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
  102. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +21 -9
  103. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
  104. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
  105. package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
  106. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
  107. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +189 -105
  108. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +9 -0
  109. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
  110. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +111 -9
  111. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -14
  112. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
  113. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +38 -5
  114. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +21 -0
  115. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
  116. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
  117. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
  118. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +46 -4
  119. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
  120. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
  121. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +4 -0
  122. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  123. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  124. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
  125. package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +99 -0
  126. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
  127. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
  128. package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
  129. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
  130. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +50 -0
  131. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
  132. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
  133. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
  134. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +62 -47
  135. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +6 -8
  136. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +12 -1
  137. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
  138. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +7 -1
  139. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
  140. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +1 -1
  141. package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
  142. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +5 -2
  143. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +42 -10
  144. package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
  145. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +35 -4
  146. package/src/runtime/agent/orchestrator/session/routine-result.mjs +179 -16
  147. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -1
  148. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
  149. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
  150. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
  151. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
  152. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
  153. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +8 -3
  154. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +36 -1
  155. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -1
  156. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
  157. package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
  158. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
  159. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
  160. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
  161. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +49 -14
  162. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +134 -17
  163. package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +35 -13
  164. package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
  165. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -3
  166. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
  167. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
  168. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
  169. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
  170. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +6 -14
  171. package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
  172. package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
  173. package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
  174. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
  175. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
  176. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +34 -21
  177. package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
  178. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
  179. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
  180. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
  181. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
  182. package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
  183. package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
  184. package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
  185. package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
  186. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
  187. package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
  188. package/src/runtime/attachments/attachment-reference.mjs +155 -0
  189. package/src/runtime/attachments/limits.mjs +5 -1
  190. package/src/runtime/attachments/office-extract.mjs +3 -6
  191. package/src/runtime/attachments/pdf-extract.mjs +84 -10
  192. package/src/runtime/attachments/store.mjs +55 -30
  193. package/src/runtime/browser-bridge/client.mjs +73 -20
  194. package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
  195. package/src/runtime/channels/lib/scheduler.mjs +14 -7
  196. package/src/runtime/channels/lib/state-file.mjs +15 -15
  197. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
  198. package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
  199. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
  200. package/src/runtime/channels/lib/worker-main.mjs +3 -2
  201. package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
  202. package/src/runtime/effort-judge/judge-client.mjs +6 -3
  203. package/src/runtime/effort-judge/model-install.mjs +16 -8
  204. package/src/runtime/effort-judge/model-manifest.json +7 -7
  205. package/src/runtime/local-provider/asset-installer.mjs +10 -4
  206. package/src/runtime/local-provider/catalog.mjs +5 -2
  207. package/src/runtime/local-provider/registered-models.mjs +64 -27
  208. package/src/runtime/local-provider/server.mjs +2 -3
  209. package/src/runtime/media/adapters/image-api.mjs +89 -0
  210. package/src/runtime/media/auth.mjs +64 -1
  211. package/src/runtime/media/catalog.mjs +66 -4
  212. package/src/runtime/media/jobs.mjs +4 -0
  213. package/src/runtime/media/lanes.mjs +46 -5
  214. package/src/runtime/media/media-usage.mjs +17 -0
  215. package/src/runtime/media/renditions.mjs +15 -15
  216. package/src/runtime/media/store.mjs +36 -35
  217. package/src/runtime/media/tool.mjs +8 -1
  218. package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
  219. package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
  220. package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
  221. package/src/runtime/memory/lib/pg/process.mjs +8 -4
  222. package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
  223. package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
  224. package/src/runtime/office/core/journal.mjs +7 -14
  225. package/src/runtime/office/design/library/design-library-core.mjs +4 -16
  226. package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
  227. package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
  228. package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
  229. package/src/runtime/office/pdf/pdf-render.mjs +30 -18
  230. package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
  231. package/src/runtime/office/portable/portable-soffice.mjs +4 -0
  232. package/src/runtime/shared/agent-kind-migration.mjs +200 -0
  233. package/src/runtime/shared/agent-kind.mjs +152 -0
  234. package/src/runtime/shared/agent-message-envelope.d.mts +6 -0
  235. package/src/runtime/shared/agent-message-envelope.mjs +44 -0
  236. package/src/runtime/shared/agent-reap-state.d.mts +4 -0
  237. package/src/runtime/shared/agent-route-config.d.mts +1 -0
  238. package/src/runtime/shared/agent-route-config.mjs +22 -8
  239. package/src/runtime/shared/agent-store.mjs +149 -0
  240. package/src/runtime/shared/agent-task-starts.mjs +27 -0
  241. package/src/runtime/shared/atomic-file.d.mts +50 -0
  242. package/src/runtime/shared/atomic-file.mjs +394 -132
  243. package/src/runtime/shared/background-tasks.mjs +7 -4
  244. package/src/runtime/shared/bot-hops.mjs +30 -0
  245. package/src/runtime/shared/bot-split-migration.mjs +457 -0
  246. package/src/runtime/shared/bounded-download.mjs +4 -2
  247. package/src/runtime/shared/config-patch.mjs +20 -1
  248. package/src/runtime/shared/config.mjs +39 -9
  249. package/src/runtime/shared/connector-catalog.d.mts +1 -2
  250. package/src/runtime/shared/connector-catalog.mjs +2 -4
  251. package/src/runtime/shared/connector-triggers.mjs +2 -0
  252. package/src/runtime/shared/defaults-separation.mjs +6 -2
  253. package/src/runtime/shared/delegated-approval-host.mjs +74 -0
  254. package/src/runtime/shared/err-text.mjs +7 -1
  255. package/src/runtime/shared/error-presentation.mjs +113 -10
  256. package/src/runtime/shared/file-has-data.mjs +28 -0
  257. package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
  258. package/src/runtime/shared/handoff-artifacts.mjs +61 -0
  259. package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
  260. package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
  261. package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
  262. package/src/runtime/shared/model-route-fallback.mjs +79 -7
  263. package/src/runtime/shared/pending-agent-work.mjs +54 -0
  264. package/src/runtime/shared/plain-preview.mjs +22 -17
  265. package/src/runtime/shared/process-lifecycle.mjs +8 -12
  266. package/src/runtime/shared/projects.mjs +50 -41
  267. package/src/runtime/shared/provider-accounts.mjs +17 -12
  268. package/src/runtime/shared/routine-trigger.d.mts +6 -1
  269. package/src/runtime/shared/routine-trigger.mjs +14 -6
  270. package/src/runtime/shared/run-child.d.mts +3 -0
  271. package/src/runtime/shared/run-child.mjs +24 -3
  272. package/src/runtime/shared/sensitive-path-rules.d.mts +15 -0
  273. package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
  274. package/src/runtime/shared/session-baseline-store.mjs +8 -2
  275. package/src/runtime/shared/singleton-owner.mjs +7 -6
  276. package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
  277. package/src/runtime/shared/staged-update.mjs +4 -2
  278. package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
  279. package/src/runtime/shared/tool-execution-contract.mjs +6 -0
  280. package/src/runtime/shared/transcript-metadata.mjs +28 -3
  281. package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
  282. package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
  283. package/src/runtime/shared/turn-snapshot.mjs +44 -2
  284. package/src/runtime/shared/usage-readout-totals.mjs +15 -13
  285. package/src/runtime/shared/user-cwd.mjs +9 -4
  286. package/src/runtime/shared/user-data-guard.mjs +46 -44
  287. package/src/runtime/shared/utf8-cut.mjs +10 -0
  288. package/src/runtime/shared/worktrees/activity-gate.mjs +269 -61
  289. package/src/runtime/shared/worktrees/registry.mjs +26 -26
  290. package/src/runtime/tidy/core-install.mjs +26 -4
  291. package/src/runtime/tidy/install.mjs +91 -23
  292. package/src/runtime/web-search/lib/config.mjs +4 -16
  293. package/src/session-runtime/agent-home-delivery.mjs +859 -136
  294. package/src/session-runtime/agent-room-delivery.mjs +167 -19
  295. package/src/session-runtime/agent-task-sessions.mjs +831 -69
  296. package/src/session-runtime/agent-tool-routing.mjs +1 -0
  297. package/src/session-runtime/boot/apis.mjs +58 -24
  298. package/src/session-runtime/boot/config.mjs +1 -0
  299. package/src/session-runtime/boot/facade.mjs +11 -1
  300. package/src/session-runtime/boot/infrastructure.mjs +14 -2
  301. package/src/session-runtime/boot/providers.mjs +16 -6
  302. package/src/session-runtime/boot/shared.mjs +12 -6
  303. package/src/session-runtime/boot/tools.mjs +2 -2
  304. package/src/session-runtime/bot-status.mjs +432 -0
  305. package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
  306. package/src/session-runtime/config-lifecycle.mjs +78 -32
  307. package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
  308. package/src/session-runtime/handoff-attachments.mjs +593 -0
  309. package/src/session-runtime/held-requests.mjs +36 -33
  310. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
  311. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
  312. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +45 -6
  313. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
  314. package/src/session-runtime/lifecycle/teardown.mjs +11 -3
  315. package/src/session-runtime/mcp-glue/connect.mjs +100 -186
  316. package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
  317. package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
  318. package/src/session-runtime/media-api.mjs +5 -2
  319. package/src/session-runtime/model-route/route-persist.mjs +2 -2
  320. package/src/session-runtime/model-route/route-tuning.mjs +11 -2
  321. package/src/session-runtime/model-route/set-route.mjs +82 -2
  322. package/src/session-runtime/native-web-search.mjs +2 -2
  323. package/src/session-runtime/new-session-config.mjs +6 -1
  324. package/src/session-runtime/owned-automation-run.mjs +8 -1
  325. package/src/session-runtime/room-member-gate.mjs +16 -3
  326. package/src/session-runtime/route-resolution.mjs +21 -19
  327. package/src/session-runtime/route-state.mjs +1 -59
  328. package/src/session-runtime/routine-home-turn.mjs +5 -3
  329. package/src/session-runtime/runtime-bootstrap.mjs +5 -3
  330. package/src/session-runtime/runtime-paths.mjs +11 -5
  331. package/src/session-runtime/runtime-tunables.mjs +6 -0
  332. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +11 -2
  333. package/src/session-runtime/services/agent-tool/close-flow.mjs +4 -2
  334. package/src/session-runtime/services/agent-tool/execute-send.mjs +1 -0
  335. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +1 -0
  336. package/src/session-runtime/services/agent-tool/helpers.mjs +24 -5
  337. package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
  338. package/src/session-runtime/services/agent-tool/send-flow.mjs +36 -24
  339. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -0
  340. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
  341. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +12 -6
  342. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
  343. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  344. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +22 -2
  345. package/src/session-runtime/services/agent-tool/worker-index.mjs +4 -6
  346. package/src/session-runtime/services/agent-tool.mjs +6 -0
  347. package/src/session-runtime/services/daemon-crash-capture/daemon-exit-record.mjs +1 -1
  348. package/src/session-runtime/services/daemon-crash-capture/retention.mjs +4 -3
  349. package/src/session-runtime/services/hook-bus/config-loader.mjs +14 -5
  350. package/src/session-runtime/services/hook-bus/rule-file.mjs +49 -11
  351. package/src/session-runtime/services/plugin-admin.mjs +26 -26
  352. package/src/session-runtime/services/provider-admin.mjs +14 -4
  353. package/src/session-runtime/services/schedule-access.mjs +33 -4
  354. package/src/session-runtime/services/seeds.mjs +4 -3
  355. package/src/session-runtime/services/usage-dashboard.mjs +1 -1
  356. package/src/session-runtime/services/usage-stats-model.mjs +2 -1
  357. package/src/session-runtime/session-create/materialize.mjs +2 -3
  358. package/src/session-runtime/session-create/session-options.mjs +15 -2
  359. package/src/session-runtime/settings-builtin-tools-api.mjs +63 -1
  360. package/src/session-runtime/settings-compaction-api.mjs +86 -39
  361. package/src/session-runtime/setup-tool/executor.mjs +20 -3
  362. package/src/session-runtime/setup-tool/extended-actions.mjs +19 -7
  363. package/src/session-runtime/setup-tool/settings-contract.mjs +37 -1
  364. package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
  365. package/src/session-runtime/skills-api.mjs +12 -5
  366. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +265 -0
  367. package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
  368. package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
  369. package/src/session-runtime/tool-policy/policy-stage.mjs +165 -0
  370. package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
  371. package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
  372. package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
  373. package/src/session-runtime/tool-policy-refresh.mjs +47 -358
  374. package/src/session-runtime/tool-surface.mjs +5 -3
  375. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +99 -81
  376. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  377. package/src/session-runtime/turn/turn-run.mjs +2 -1
  378. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
  379. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +578 -301
  380. package/src/session-runtime/workflow-agents-api/agent-route.mjs +113 -53
  381. package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
  382. package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
  383. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
  384. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
  385. package/src/session-runtime/workspace/workspace-state.mjs +7 -6
  386. package/src/standalone/daemon-agent-control.mjs +4 -1
  387. package/src/standalone/daemon-session-control.mjs +60 -11
  388. package/src/standalone/daemon.mjs +34 -4
  389. package/src/standalone/local-session-runtime.mjs +22 -14
  390. package/src/standalone/session-client.mjs +7 -2
  391. package/src/standalone/session-protocol.mjs +7 -0
  392. package/src/standalone/session-service/agent-tree/agent-turns.mjs +46 -3
  393. package/src/standalone/session-service/agent-tree.mjs +4 -3
  394. package/src/standalone/session-service/session-calls/session-turns.mjs +19 -0
  395. package/src/standalone/session-service.mjs +11 -0
  396. package/src/standalone/session-state-projection.mjs +19 -9
  397. package/src/standalone/session-tool-output.mjs +35 -9
  398. package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
  399. package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
  400. package/src/tui/app/slash-commands.mjs +1 -1
  401. package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
  402. package/src/tui/dist/index.mjs +599 -342
  403. package/src/tui/prompt-history-store.mjs +16 -21
  404. package/src/tui/session/context-state.mjs +4 -0
  405. package/src/tui/session/notice-surface.mjs +3 -4
  406. package/src/tui/session/session-api/intake/abort.mjs +19 -1
  407. package/src/tui/session/session-api/media.mjs +2 -1
  408. package/src/tui/session/session-api/routes-agent-definitions.mjs +75 -0
  409. package/src/tui/session/session-api/routes-write.mjs +203 -0
  410. package/src/tui/session/session-api/routes.mjs +23 -236
  411. package/src/tui/session/session-api/settings.mjs +14 -1
  412. package/src/tui/session/session-flow/drain.mjs +28 -3
  413. package/src/tui/session/session-flow/failed-turn-rewind.mjs +4 -2
  414. package/src/tui/session/session-flow/queue/take-entries.mjs +8 -0
  415. package/src/tui/session/session-flow/steering.mjs +8 -3
  416. package/src/tui/session/tool-approval.mjs +185 -20
  417. package/src/tui/session/transcript-intake.mjs +4 -0
  418. package/src/tui/session/turn-live-call.mjs +11 -3
  419. package/src/tui/session/turn.mjs +36 -17
  420. package/src/tui/transcript-tool-failures.mjs +8 -2
  421. package/src/vendor/statusline/src/gateway/route-meta.mjs +7 -8
  422. package/src/vendor/statusline/src/gateway/session-routes.mjs +6 -7
  423. package/src/rules/agent-mode/ROUTINE.md +0 -6
@@ -14,7 +14,7 @@ import {
14
14
  } from './native-web-search/tool-shape.mjs';
15
15
  import { createWebSearchRouteCandidates } from './native-web-search/routes.mjs';
16
16
  import { reportNativeWebSearchUsage } from './native-web-search-usage.mjs';
17
- import { canFallbackRoute } from '../runtime/shared/model-route-fallback.mjs';
17
+ import { canFallbackCapacityRoute } from '../runtime/shared/model-route-fallback.mjs';
18
18
 
19
19
  export function createNativeWebSearch(deps) {
20
20
  const {
@@ -103,7 +103,7 @@ export function createNativeWebSearch(deps) {
103
103
  try {
104
104
  return await sendCandidate(candidate, toolType, webSearchArgs, signal);
105
105
  } catch (err) {
106
- if (!canFallbackRoute(err, { signal })) throw err;
106
+ if (!canFallbackCapacityRoute(err, { signal })) throw err;
107
107
  errors.push(
108
108
  `${candidate.provider}${candidate.model ? `/${candidate.model}` : ''}/${toolType}: ${err?.message || String(err)}`
109
109
  );
@@ -1,4 +1,5 @@
1
1
  import { isDeepStrictEqual } from 'node:util';
2
+ import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
2
3
  import { flushPendingSessionConfigWrites } from './config-lifecycle.mjs';
3
4
 
4
5
  // Run only after the lifecycle has established that it needs a NEW session.
@@ -27,7 +28,11 @@ export function createNewSessionConfig({
27
28
  if (!initialConfig || typeof initialConfig !== 'object') {
28
29
  reloadFullConfig();
29
30
  if (!firstSession || !initialRouteExplicit) {
30
- rt.route = resolveRoute(rt.config, {});
31
+ const configured = resolveRoute(rt.config, {});
32
+ // With no Lead model configured the model picked for this runtime's
33
+ // still-empty conversation (a session-only choice never writes the
34
+ // Lead route) stands; the reload must not drop it before the first turn.
35
+ if (clean(configured?.model) || !clean(rt.route?.model)) rt.route = configured;
31
36
  }
32
37
  }
33
38
  invalidateOutputStyleStatusCache();
@@ -101,7 +101,7 @@ async function queueResult(row, item, entry, { deliver, recordDelivery, onDelive
101
101
  /**
102
102
  * `row` is `{ name, ownerAgentId }`; `run({ signal })` resolves `{ sessionId,
103
103
  * result }` (`signal` is the caller's cancellation, if any). Resolves the
104
- * outcome, or `{ skipped: true, reason: 'owner' | 'overlap' | 'backoff' }`
104
+ * outcome, or `{ skipped: true, reason: 'owner' | 'overlap' | 'backoff' | 'paused' }`
105
105
  * (an owner skip also names `ownerProblem` and its `message`); a failed run
106
106
  * rejects.
107
107
  */
@@ -141,6 +141,13 @@ export async function runOwnedAutomation(kind, row, run, deps = {}) {
141
141
  const state = await Promise.resolve()
142
142
  .then(() => record.state(name))
143
143
  .catch(() => null);
144
+ // Switched off (by the user, or by the failure limit): the cron claim and
145
+ // the webhook handler already refuse it, but a one-shot timer or a
146
+ // dispatch that raced the pause must not run it either.
147
+ if (state?.enabled === false) {
148
+ log(`${kind} "${name}": skipped, switched off`);
149
+ return await skip('paused');
150
+ }
144
151
  const wait = routineBackoffRemaining(state, now(), limits);
145
152
  if (wait > 0) {
146
153
  log(`${kind} "${name}": skipped, backing off ${Math.ceil(wait / 1000)}s after failures in a row`);
@@ -2,6 +2,9 @@
2
2
  // anything that can change files or state asks the user through the ordinary
3
3
  // approval flow, whatever the agent's own permission or hook rules say — even
4
4
  // an agent that normally runs auto-approved. A hook's deny still wins.
5
+ // Opening a task session (`session create`) runs as freely as in the agent's
6
+ // home thread: it changes nothing itself, and the task session is the user's
7
+ // own coding Lead, whose every side effect follows its usual approval rules.
5
8
  import { analyzeShellCommandEffects } from '../runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs';
6
9
 
7
10
  const READ_ONLY_TOOLS = new Set([
@@ -37,12 +40,22 @@ export async function isReadOnlyRoomCall({ name, args, cwd }, analyze = analyzeS
37
40
  }
38
41
  }
39
42
 
43
+ /** Whether `name(args)` opens a task session (session create). */
44
+ export function isTaskSessionCreate({ name, args }) {
45
+ return (
46
+ name === 'session' &&
47
+ String(args?.action ?? '')
48
+ .trim()
49
+ .toLowerCase() === 'create'
50
+ );
51
+ }
52
+
40
53
  /** The PreToolUse decision for a room member's call: the hook's own `decision`
41
- * when it denies or the call only reads; otherwise an approval ask that keeps
42
- * any rewrite the hook made. */
54
+ * when it denies, the call only reads, or it opens a task session; otherwise
55
+ * an approval ask that keeps any rewrite the hook made. */
43
56
  export async function roomMemberToolDecision(call, decision, analyze) {
44
57
  const action = String(decision?.action || decision?.decision || '').toLowerCase();
45
58
  if (action === 'deny' || action === 'block') return decision;
46
- if (await isReadOnlyRoomCall(call, analyze)) return decision;
59
+ if (isTaskSessionCreate(call) || (await isReadOnlyRoomCall(call, analyze))) return decision;
47
60
  return { ...(decision && typeof decision === 'object' ? decision : {}), action: 'ask', reason: ROOM_APPROVAL_REASON };
48
61
  }
@@ -1,5 +1,5 @@
1
- // Route resolution against the live runtime record: pick a model for a
2
- // model-less first turn and refresh the route's effort / Fast / context
1
+ // Route resolution against the live runtime record: refuse a model-less first
2
+ // turn (no auto-pick) and refresh the route's effort / Fast / context
3
3
  // fields from provider metadata.
4
4
  import { ensureProviderEnabled } from '../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
5
5
  import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
@@ -22,17 +22,15 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
22
22
  if (routeHasModel()) return rt.route;
23
23
  const models = await runAbortable(signal, () => collectProviderModels());
24
24
  throwIfAborted(signal);
25
- const picked = models[0] || null;
26
- if (!picked) {
25
+ // A model chosen during the catalog read stands: a new task's reservation
26
+ // prewarm starts on the empty route, its draft model lands meanwhile, and
27
+ // the first prompt joins this very prewarm.
28
+ if (routeHasModel()) return rt.route;
29
+ if (!models?.length) {
27
30
  throw new Error('No provider models available. Open /providers to sign in, then /model to choose a model.');
28
31
  }
29
- rt.route = {
30
- ...rt.route,
31
- provider: picked.provider,
32
- model: picked.id,
33
- preset: null,
34
- };
35
- return rt.route;
32
+ // Never auto-pick: the user chooses the model.
33
+ throw new Error('No model selected. Choose a model with /model first.');
36
34
  }
37
35
 
38
36
  async function refreshRouteEffort(modelMetaOverride = null, expectedRoute = null, signal = null, lease = null) {
@@ -53,15 +51,19 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
53
51
  .find((option) => option?.id === 'context')
54
52
  ?.options?.find((option) => clean(option?.value) === contextValue);
55
53
  const modelDisplay = routeModelDisplay(rt.config, targetRoute, modelMeta);
56
- const selectedContextWindow = [contextState.selectedContextWindow, contextOption?.contextWindow]
54
+ // Without a known window the selection (share, exact tokens, resolved
55
+ // window) is kept as requested — the session sizes it from the provider's
56
+ // window; dropping it silently put the route back on the model's default.
57
+ // With one it is the clamped value, absent when it is the default window.
58
+ const windowKnown = contextState.contextDefaultPercent !== undefined;
59
+ const selectedContextWindow = [
60
+ contextState.selectedContextWindow,
61
+ contextOption?.contextWindow,
62
+ windowKnown ? undefined : targetRoute.selectedContextWindow,
63
+ ]
57
64
  .map(Number)
58
65
  .find((value) => value > 0);
59
- // Without a known window the exact selection is kept as requested; with
60
- // one it is the clamped value, absent when it is the default window.
61
- const contextTokens =
62
- contextState.contextDefaultPercent === undefined
63
- ? normalizeContextTokens(targetRoute.contextTokens)
64
- : contextState.contextTokens;
66
+ const contextTokens = windowKnown ? contextState.contextTokens : normalizeContextTokens(targetRoute.contextTokens);
65
67
  const { contextTokens: _requestedTokens, ...routeFields } = targetRoute;
66
68
  rt.route = {
67
69
  ...routeFields,
@@ -69,7 +71,7 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
69
71
  fastCapable,
70
72
  effectiveEffort,
71
73
  effortOptions: effortItemsFor(rt.route.provider, modelMeta, effectiveEffort),
72
- contextPercent: contextState.contextPercent,
74
+ contextPercent: windowKnown ? contextState.contextPercent : targetRoute.contextPercent,
73
75
  contextDefaultPercent: contextState.contextDefaultPercent,
74
76
  ...(contextTokens ? { contextTokens } : {}),
75
77
  ...(selectedContextWindow ? { selectedContextWindow } : {}),
@@ -7,8 +7,6 @@ import {
7
7
  import { clean, hasOwn } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
8
8
  import { coerceEffortFor } from '../runtime/agent/orchestrator/runtime-core/effort.mjs';
9
9
  import { fastCapableFor } from '../runtime/agent/orchestrator/runtime-core/model-capabilities.mjs';
10
- import { providerCachedModelMetadataSync } from '../runtime/agent/orchestrator/providers/provider-catalog-cache.mjs';
11
- import { contextWindowRange, normalizeContextTokens } from '../runtime/shared/llm/default-context-window.mjs';
12
10
 
13
11
  export function resolveRouteEffortState(targetRoute = {}, modelMeta = null) {
14
12
  const requested = hasOwn(targetRoute, 'effort') ? targetRoute.effort : targetRoute.preset?.effort || null;
@@ -36,63 +34,7 @@ export function selectionFastCapable(provider, modelMeta, effort, modelParameter
36
34
  return !modelMetaLooksResolved(modelMeta) || fastCapableFor(provider, modelMeta, effort, modelParameters);
37
35
  }
38
36
 
39
- // The persisted provider model rows are the SAME source the picker sized its
40
- // slider against, so they carry both windows (openai-oauth: 272k default /
41
- // 1M max). Reading them keeps a percentage saved against the picker's scale
42
- // meaningful; anything that only knows a single window would silently rescale
43
- // it (30% of 272k instead of 30% of 1M).
44
- function cachedRouteWindows(provider, model) {
45
- const row = providerCachedModelMetadataSync(provider, model)?.rawProviderModel || null;
46
- if (!row) return null;
47
- const contextWindow = Number(row.contextWindow ?? row.context_window ?? row.max_input_tokens) || 0;
48
- const maxContextWindow = Number(row.maxContextWindow ?? row.max_context_window) || 0;
49
- return contextWindow > 0 || maxContextWindow > 0 ? { contextWindow, maxContextWindow } : null;
50
- }
51
-
52
- export function resolveRouteContextState(targetRoute = {}, modelMeta = null, windowLookup = cachedRouteWindows) {
53
- // Only providers that implement getCachedModelInfo (openai-oauth, cursor,
54
- // openai-compat, opencode-go) hand lookupModelMeta a window; every other one
55
- // (anthropic-oauth, grok-oauth, gemini, …) gets the bare `{ id, provider }`
56
- // placeholder. Reading the window from that alone yields 0, which dropped the
57
- // saved context percentage for the entire session — while resolveSessionContextMeta
58
- // went on to size that session from the provider/catalog window (Claude Opus 5:
59
- // a full 1M rather than the selected 500k). Read the cached provider row here so
60
- // the percentage and the session boundary cannot disagree.
61
- const windowMeta =
62
- Number(modelMeta?.contextWindow) > 0 || Number(modelMeta?.maxContextWindow) > 0
63
- ? modelMeta
64
- : windowLookup?.(clean(targetRoute?.provider), clean(targetRoute?.model)) || modelMeta;
65
- const { defaultWindow, maxWindow } = contextWindowRange({
66
- provider: clean(targetRoute?.provider),
67
- contextWindow: windowMeta?.contextWindow,
68
- maxContextWindow: windowMeta?.maxContextWindow,
69
- });
70
- if (!maxWindow) {
71
- return { contextPercent: undefined, contextDefaultPercent: undefined, selectedContextWindow: undefined };
72
- }
73
- const contextDefaultPercent = Math.max(10, Math.min(100, Math.round((defaultWindow / maxWindow) * 10) * 10));
74
- // An exact token selection overrides the 10% stops. It is clamped to the
75
- // selectable range; one that lands on the default window is the default.
76
- const requestedTokens = normalizeContextTokens(targetRoute?.contextTokens);
77
- if (requestedTokens) {
78
- const contextTokens = Math.max(Math.ceil(maxWindow * 0.1), Math.min(maxWindow, requestedTokens));
79
- if (contextTokens === defaultWindow) {
80
- return { contextPercent: contextDefaultPercent, contextDefaultPercent, selectedContextWindow: defaultWindow };
81
- }
82
- const contextPercent = Math.max(10, Math.min(100, Math.round((contextTokens / maxWindow) * 10) * 10));
83
- return { contextPercent, contextDefaultPercent, selectedContextWindow: contextTokens, contextTokens };
84
- }
85
- const requested = Number(targetRoute?.contextPercent);
86
- const contextPercent =
87
- Number.isFinite(requested) && requested > 0
88
- ? Math.max(10, Math.min(100, Math.round(requested / 10) * 10))
89
- : contextDefaultPercent;
90
- const selectedContextWindow =
91
- contextPercent === contextDefaultPercent
92
- ? defaultWindow
93
- : Math.max(1, Math.floor((maxWindow * contextPercent) / 100));
94
- return { contextPercent, contextDefaultPercent, selectedContextWindow };
95
- }
37
+ export { resolveRouteContextState } from '../runtime/agent/orchestrator/runtime-core/route-context-state.mjs';
96
38
 
97
39
  /**
98
40
  * Human label for the statusline. A display-only user alias
@@ -9,8 +9,10 @@
9
9
  * it rides the thread's queue as its own `routine` entry (one per turn, never
10
10
  * merged or steered into another), shows as a routine marker row, and selects
11
11
  * skills only from the routine's instructions (`skillSelection`), never from a
12
- * webhook payload. While it runs the thread counts as unattended, so its
13
- * approvals are held for the owner (held-requests.mjs). Resolves with the
12
+ * webhook payload. While it runs the thread counts as an unattended run
13
+ * (held-requests.mjs): the saved routine is the user's grant, so it never asks
14
+ * (outbound actions are allowed within the bot's permissions; payments and
15
+ * permanent deletes are refused, human-gate/run-policy.mjs). Resolves with the
14
16
  * reply once the turn ends; rejects when the turn fails, is cancelled, or the
15
17
  * caller's `signal` aborts (which also aborts the turn once it runs).
16
18
  */
@@ -126,7 +128,7 @@ export async function runRoutineTurn(
126
128
  onCommitted: () => {
127
129
  if (started) return;
128
130
  started = true;
129
- // Nobody watches this turn: its approvals are held for the owner.
131
+ // Nobody watches this turn: it never asks (run-policy.mjs).
130
132
  unmark = markUnattendedRun(homeId, { kind, agentId, name });
131
133
  if (aborted) void abortTurn();
132
134
  },
@@ -13,22 +13,24 @@ import {
13
13
  CODE_GRAPH_TOOL_DEFS,
14
14
  STATUSLINE_SESSION_ROUTES,
15
15
  STANDALONE_ROOT,
16
- STANDALONE_DATA_DIR,
16
+ standaloneDataDir,
17
17
  } from './runtime-paths.mjs';
18
18
 
19
19
  export function prepareStandaloneEnvironment() {
20
20
  process.env.MIXDOG_QUIET_SESSION_LOG ??= '1';
21
21
  const startedAt = performance.now();
22
+ // Resolved per runtime start: this start's data folder, not the first one's.
23
+ const dataDir = standaloneDataDir();
22
24
  ensureStandaloneEnvironment({
23
25
  rootDir: STANDALONE_ROOT,
24
- dataDir: STANDALONE_DATA_DIR,
26
+ dataDir,
25
27
  });
26
28
  // Office journals exist only for cross-process crash recovery, so startup just
27
29
  // prunes expired ones in the background. Surfacing them as session context made
28
30
  // every new session (agents included) re-announce unrelated leftovers for the
29
31
  // full 30-day retention window; recovery stays reachable on demand through
30
32
  // office action=transactions / action=recover.
31
- listOfficeJournals(STANDALONE_DATA_DIR).catch(() => {});
33
+ listOfficeJournals(dataDir).catch(() => {});
32
34
  bootProfile('standalone-env:ready', { ms: (performance.now() - startedAt).toFixed(1) });
33
35
  }
34
36
 
@@ -1,6 +1,6 @@
1
- import { homedir } from 'node:os';
2
- import { dirname, join } from 'node:path';
1
+ import { dirname } from 'node:path';
3
2
  import { fileURLToPath } from 'node:url';
3
+ import { resolvePluginData } from '../runtime/shared/plugin-paths.mjs';
4
4
 
5
5
  export const RUNTIME = '../runtime/agent/orchestrator';
6
6
  export const WEB_SEARCH_RUNTIME = '../runtime/web-search/index.mjs';
@@ -12,10 +12,16 @@ export const STATUSLINE_SESSION_ROUTES = '../vendor/statusline/src/gateway/sessi
12
12
 
13
13
  const SESSION_RUNTIME_DIR = dirname(fileURLToPath(import.meta.url));
14
14
  export const STANDALONE_ROOT = dirname(SESSION_RUNTIME_DIR);
15
- const mixdogHome = process.env.MIXDOG_HOME || join(homedir(), '.mixdog');
16
- export const STANDALONE_DATA_DIR = process.env.MIXDOG_DATA_DIR || join(mixdogHome, 'data');
15
+
16
+ /**
17
+ * The standalone data directory, resolved from the environment on every call.
18
+ * A runtime start (a pristine boundary, a second page session) retargets
19
+ * MIXDOG_DATA_DIR, so a load-time constant would point every later start back
20
+ * at the first run's folder.
21
+ */
22
+ export const standaloneDataDir = resolvePluginData;
17
23
 
18
24
  /** The data directory a runtime writes to: its config module's plugin data dir, else the standalone default. */
19
25
  export function pluginDataDir(cfgMod) {
20
- return cfgMod.getPluginData?.() || STANDALONE_DATA_DIR;
26
+ return cfgMod.getPluginData?.() || standaloneDataDir();
21
27
  }
@@ -36,6 +36,12 @@ export function readRuntimeTunables() {
36
36
  // connected tools fold synchronously; in-flight servers join through the
37
37
  // late-tool announcement path. Operators may opt back into a grace window.
38
38
  mcpTurnGraceMs: envDelayMs('MIXDOG_MCP_TURN_GRACE_MS', 0, { min: 0, max: 2_000 }),
39
+ // A spawned agent's first turn may be its only one, so it waits for the
40
+ // initial connect — but only this long: a slow-but-alive server (a
41
+ // 20 s handshake is seen in the wild) must not hold the first model
42
+ // request for its whole startup budget. Later servers join through the
43
+ // late-tool announcement path on the agent's next turn.
44
+ mcpAgentGraceMs: envDelayMs('MIXDOG_MCP_AGENT_GRACE_MS', 3_000, { min: 0, max: 30_000 }),
39
45
  // Boot-time remote start is deferred past the first frame; see the caller.
40
46
  remoteAutoStartDelayMs: envDelayMs('MIXDOG_REMOTE_AUTOSTART_DELAY_MS', 1_500, { min: 0, max: 60_000 }),
41
47
  providerWarmupEnabled:
@@ -5,6 +5,7 @@ import { cancelBackgroundTask, listBackgroundTasks } from '../../../../runtime/s
5
5
  import { presentErrorText } from '../../../../runtime/shared/err-text.mjs';
6
6
  import { clean } from '../helpers.mjs';
7
7
  import { isLeadPoolAgent } from '../worker-rows.mjs';
8
+ import { isUnnotifiedRestartFailure } from '../worker-index/row-liveness.mjs';
8
9
 
9
10
  export function createCloseAll({ registry, close }) {
10
11
  const { tags, tagAgents, tagCwds } = registry;
@@ -17,11 +18,13 @@ export function createCloseAll({ registry, close }) {
17
18
 
18
19
  // Drop the closed workers' rows: every non-Lead row for an unscoped
19
20
  // teardown, only this owner's (plus the rows just closed) for a scoped one.
21
+ // A row whose owner is still owed its restart failure stays (a process exit
22
+ // closes every worker; the next process tells the owner).
20
23
  function purgeWorkerRows(ownerSessionId, closedSessionIds) {
21
24
  registry.flushWorkerIndexMutations();
22
25
  registry.writeWorkerRows((byKey, tombstonesByKey) => {
23
26
  for (const [key, row] of [...byKey.entries()]) {
24
- if (isLeadPoolAgent(row.agent)) continue;
27
+ if (isLeadPoolAgent(row.agent) || isUnnotifiedRestartFailure(row)) continue;
25
28
  if (
26
29
  ownerSessionId &&
27
30
  clean(row.ownerSessionId) !== ownerSessionId &&
@@ -38,15 +41,20 @@ export function createCloseAll({ registry, close }) {
38
41
  // Lead's workers: the worker index and task registry are shared by every
39
42
  // Lead in the process, and an unscoped sweep wiped sibling Leads' idle
40
43
  // workers mid-window.
44
+ // A process exit (`scope.processExit`) closes the workers but keeps their
45
+ // rows: the next process lists the finished ones for their pane window and
46
+ // settles the ones the exit cut off (restart-notify), exactly as after a
47
+ // crash. Dropping them emptied every sub-agent list after a daemon restart.
41
48
  return async function closeAll(reason = 'cli-agent-close-all', scope = {}) {
42
49
  const ownerSessionId = clean(scope.callerSessionId);
50
+ const keepRows = scope.processExit === true;
43
51
  const context = ownerSessionId ? { callerSessionId: ownerSessionId } : {};
44
52
  registry.refreshTagsFromSessions({ scanSessions: false, context });
45
53
  const closed = [];
46
54
  const failed = [];
47
55
  for (const { tag, session } of registry.agentSessionEntries({ scanSessions: false, context })) {
48
56
  try {
49
- closed.push(await close({ sessionId: session.id }, context));
57
+ closed.push(await close({ sessionId: session.id }, context, { keepRow: keepRows }));
50
58
  } catch (err) {
51
59
  failed.push({ tag, error: presentErrorText(err, { surface: 'agent' }) });
52
60
  }
@@ -57,6 +65,7 @@ export function createCloseAll({ registry, close }) {
57
65
  closed.push({ closed: true, tag: task.tag || null, sessionId: task.sessionId || null, task_id: task.task_id });
58
66
  }
59
67
  if (!ownerSessionId) resetLocalTagState();
68
+ if (keepRows) return { closed, failed };
60
69
  const closedSessionIds = new Set(closed.map((row) => clean(row.sessionId)).filter(Boolean));
61
70
  purgeWorkerRows(ownerSessionId, closedSessionIds);
62
71
  return { closed, failed };
@@ -37,7 +37,9 @@ export function createCloseFlow({ mgr, registry, views }) {
37
37
  }
38
38
  }
39
39
 
40
- async function close(args, context = {}) {
40
+ /** `keepRow`: a process exit closes the worker but leaves its row (and its
41
+ * descendants') for the next process (close-all.mjs). */
42
+ async function close(args, context = {}, { keepRow = false } = {}) {
41
43
  const scopedContext = agentScope(args, context);
42
44
  registry.refreshTagsFromSessions({ scanSessions: registry.wantsSessionScan(args), context: scopedContext });
43
45
  const taskId = taskIdFromArgs(args);
@@ -73,7 +75,7 @@ export function createCloseFlow({ mgr, registry, views }) {
73
75
  if (task?.taskId) cancelBackgroundTask(task.taskId, CLOSE_REASON);
74
76
  // Drop the row only once the cancellation is DURABLY recorded: a failed
75
77
  // close that still forgot the row would leave no cancelled state behind.
76
- if (ok) {
78
+ if (ok && !keepRow) {
77
79
  registry.forgetTerminalSession(tag, sessionId);
78
80
  for (const descendantSessionId of descendantSessionIds) {
79
81
  registry.removeWorkerRow({ sessionId: descendantSessionId });
@@ -70,6 +70,7 @@ export function createSendDispatch({ registry, defaultCwd, sendFlow, spawnFlow,
70
70
  async function send(args, { scopedContext, callerCwd, context, notifyContext }) {
71
71
  try {
72
72
  const prepared = await sendFlow.prepareSend(args, scopedContext);
73
+ await sendFlow.adoptCaller(prepared, notifyContext);
73
74
  return sendFlow.dispatchToExistingSession(prepared, notifyContext);
74
75
  } catch (err) {
75
76
  return await respawnDeadTagSend(err, args, { callerCwd, context, notifyContext });
@@ -51,6 +51,7 @@ export function createSpawnDispatch({
51
51
  }
52
52
  if (liveSessionId && registry.getLiveSession(liveSessionId)) {
53
53
  const prepared = await sendFlow.prepareSend({ ...args, tag: explicitTag }, scopedContext);
54
+ await sendFlow.adoptCaller(prepared, notifyContext);
54
55
  const route = requestedRoute(args);
55
56
  return {
56
57
  reused: sendFlow.dispatchToExistingSession(route ? { ...prepared, route } : prepared, notifyContext, {
@@ -12,6 +12,8 @@ import {
12
12
  import { PRESET_ALIASES } from './tool-def.mjs';
13
13
  import { positiveInt } from '../../../runtime/shared/numbers.mjs';
14
14
  import { clean } from '../../../runtime/shared/clean.mjs';
15
+ import { readAgentDefinitionKind } from '../../../runtime/shared/agent-kind.mjs';
16
+ import { isStoreBot, userDefinitionDir } from '../../../runtime/shared/agent-store.mjs';
15
17
  import { normalizeContextTokens } from '../../../runtime/shared/llm/default-context-window.mjs';
16
18
 
17
19
  export { positiveInt };
@@ -300,13 +302,18 @@ const _frontmatterPermCache = new Map(); // key -> { value, atMs }
300
302
  const FRONTMATTER_PERM_CACHE_TTL_MS = envTimeoutMs('MIXDOG_AGENT_FRONTMATTER_TTL_MS', 5_000);
301
303
 
302
304
  function agentDeleted(cleanAgent, dataDir) {
303
- return Boolean(dataDir) && existsSync(join(dataDir, 'agents', cleanAgent, '.deleted'));
305
+ return Boolean(dataDir) && existsSync(join(userDefinitionDir(dataDir, cleanAgent), '.deleted'));
304
306
  }
305
307
 
306
308
  /** Where an agent's definition may live, in precedence order: the data dir
307
309
  * (user/custom agents) before the shipped source root. */
308
310
  function agentDefinitionFiles(cleanAgent, dataDir, standaloneSourceRoot) {
309
311
  const candidates = [];
312
+ if (dataDir && isStoreBot(dataDir, cleanAgent)) {
313
+ // A bot of the store: only its own folder (never the agents/ original).
314
+ candidates.push(join(userDefinitionDir(dataDir, cleanAgent), 'AGENT.md'));
315
+ return candidates;
316
+ }
310
317
  if (dataDir) {
311
318
  candidates.push(join(dataDir, 'agents', cleanAgent, 'AGENT.md'));
312
319
  candidates.push(join(dataDir, 'agents', `${cleanAgent}.md`));
@@ -353,13 +360,25 @@ export function readAgentFrontmatterPermission(agent, dataDir, standaloneSourceR
353
360
  }
354
361
 
355
362
  const _frontmatterKindCache = new Map(); // key -> { value, atMs }
363
+ const _frontmatterKindValueCache = new Map(); // key -> { value, atMs }
356
364
 
357
- /** The agent definition's frontmatter `kind` (isContactAgentId reads it), or
358
- * null when it sets none. */
365
+ /** The agent definition's kind (isContactAgentId reads it), by the one
366
+ * read-only rule (agent-kind.mjs), cached per agent for the frontmatter TTL. */
359
367
  export function readAgentFrontmatterKind(agent, dataDir, standaloneSourceRoot) {
360
- return cachedFrontmatterValue(_frontmatterKindCache, agent, dataDir, standaloneSourceRoot, (fm) =>
361
- typeof fm.kind === 'string' && fm.kind.trim() ? fm.kind.trim() : null
368
+ const id = clean(agent);
369
+ if (!id || agentDeleted(id, dataDir)) return null;
370
+ const cacheKey = `${dataDir}\u0000${id}`;
371
+ const cached = _frontmatterKindCache.get(cacheKey);
372
+ if (cached && Date.now() - cached.atMs < FRONTMATTER_PERM_CACHE_TTL_MS) return cached.value;
373
+ // An explicit kind in the definition in effect (any layout) wins; only an
374
+ // unmarked user copy goes to the evidence rule.
375
+ const explicit = cachedFrontmatterValue(_frontmatterKindValueCache, id, dataDir, standaloneSourceRoot, (fm) =>
376
+ typeof fm.kind === 'string' && fm.kind.trim() ? fm.kind.trim().toLowerCase() : null
362
377
  );
378
+ const value =
379
+ explicit || (dataDir ? readAgentDefinitionKind({ dataDir, shippedRoot: standaloneSourceRoot, id }) : null);
380
+ _frontmatterKindCache.set(cacheKey, { value, atMs: Date.now() });
381
+ return value;
363
382
  }
364
383
 
365
384
  /** The agent definition's `firstResponseTimeoutMs` (a non-negative integer;
@@ -28,6 +28,16 @@ export function restartNotificationId(row) {
28
28
  return `restart:${clean(row.task_id) || `${clean(row.sessionId)}:${clean(row.finishedAt)}`}`;
29
29
  }
30
30
 
31
+ /** The agent task id an execution id names: a task's own id, or the task a
32
+ * restart notification (restartNotificationId) reports; null for one keyed
33
+ * by session because its row recorded no task id. */
34
+ export function agentTaskIdOfExecution(executionId) {
35
+ const id = clean(executionId);
36
+ if (!id.startsWith('restart:')) return id || null;
37
+ const rest = id.slice('restart:'.length);
38
+ return rest && !rest.includes(':') ? rest : null;
39
+ }
40
+
31
41
  /** `pendingRestartFailures()` lists rows whose owner is not yet told;
32
42
  * `markRestartNotified(rows)` stamps them. `mgr` supplies the persisted
33
43
  * pending queue (enqueuePendingMessage / markCompletionEntry /
@@ -16,7 +16,14 @@ import {
16
16
  terminalResultHook,
17
17
  } from './job-task-reconcile.mjs';
18
18
  import { createTurnReviewCollector } from './turn-review.mjs';
19
+ import { handoffContent } from '../../handoff-attachments.mjs';
20
+ import { rebindDelegation } from '../../../runtime/agent/orchestrator/session/human-gate/delegation.mjs';
19
21
  import { settledWorkerStatus } from './worker-index/row-liveness.mjs';
22
+ import { whileTurnDispatched } from '../../../runtime/agent/orchestrator/session/manager/runtime-state.mjs';
23
+
24
+ function workerResultIdentity({ session, tag, sessionId }) {
25
+ return { tag, sessionId, agent: session.agent || null, provider: session.provider, model: session.model };
26
+ }
20
27
 
21
28
  // `send` to an existing worker: resolve the live session, run one follow-up
22
29
  // turn under the progress watchdog, and reconcile the job/worker row. Busy
@@ -41,11 +48,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
41
48
  return (result) => {
42
49
  const abnormalError = abnormalEmptyFinishError(result, session.agent || sendAgent);
43
50
  return {
44
- tag,
45
- sessionId,
46
- agent: session.agent || null,
47
- provider: session.provider,
48
- model: session.model,
51
+ ...workerResultIdentity({ session, tag, sessionId }),
49
52
  content: result?.content || '',
50
53
  ...(sessionSurface?.canonical === true ? { handoffOnly: true } : {}),
51
54
  ...(abnormalError ? { error: abnormalError } : {}),
@@ -69,12 +72,16 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
69
72
  return hooks;
70
73
  }
71
74
 
72
- function runTurn({ session, sessionId, prompt, args }, turnHooks) {
75
+ function runTurn({ session, sessionId, prompt: text, args }, turnHooks) {
73
76
  const cwd = session.cwd || defaultCwd;
74
- if (canUseSessionSurface(session)) {
75
- return sessionSurface.runTurn({ session, prompt, context: args.context || null, cwd, ...turnHooks });
76
- }
77
- return mgr.askSession(sessionId, prompt, args.context || null, null, cwd, null, turnHooks);
77
+ // The caller's forwarded files ride along as attachment parts.
78
+ const prompt = handoffContent(text, args.attachmentParts);
79
+ return whileTurnDispatched(sessionId, () => {
80
+ if (canUseSessionSurface(session)) {
81
+ return sessionSurface.runTurn({ session, prompt, context: args.context || null, cwd, ...turnHooks });
82
+ }
83
+ return mgr.askSession(sessionId, prompt, args.context || null, null, cwd, null, turnHooks);
84
+ });
78
85
  }
79
86
 
80
87
  async function runSend(prepared, notifyContext = null, job = null) {
@@ -107,11 +114,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
107
114
  const settleCancelled = (error, result = null) => {
108
115
  finalStatus = 'cancelled';
109
116
  reconcileJobCancelled(job, {
110
- tag,
111
- sessionId,
112
- agent: session.agent || null,
113
- provider: session.provider,
114
- model: session.model,
117
+ ...workerResultIdentity({ session, tag, sessionId }),
115
118
  content: turnPartialHandoff(error, mgr.getSession(sessionId), handoffMsgStart) || result?.content || '',
116
119
  });
117
120
  };
@@ -142,11 +145,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
142
145
  if (partial) {
143
146
  finalStatus = 'idle';
144
147
  const value = {
145
- tag,
146
- sessionId,
147
- agent: session.agent || null,
148
- provider: session.provider,
149
- model: session.model,
148
+ ...workerResultIdentity({ session, tag, sessionId }),
150
149
  content: watchdogStoppedHandoff(error, partial),
151
150
  stallAbort: true,
152
151
  };
@@ -161,7 +160,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
161
160
  turnReview.complete();
162
161
  watchdog?.stop?.();
163
162
  registry.upsertWorkerSessionDeferred(session, tag, {
164
- ...settledWorkerStatus(finalStatus, stalled),
163
+ ...settledWorkerStatus(finalStatus, stalled, job),
165
164
  finishedAt: new Date().toISOString(),
166
165
  });
167
166
  reconcileJobFinally(job, finalStatus);
@@ -185,6 +184,14 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
185
184
  return { ...prepared, session: mgr.getSession(sessionId) || session };
186
185
  }
187
186
 
187
+ // The calling session hands this worker new work (a `send`, or a spawn of its
188
+ // tag): from now on the worker acts as that caller does, so a run's worker
189
+ // asks when the attended chat reuses it and the other way round. Not for a
190
+ // completion wake, which is the worker's own continuation.
191
+ function adoptCaller({ sessionId }, notifyContext) {
192
+ return rebindDelegation(sessionId, notifyContext?.callerSessionId);
193
+ }
194
+
188
195
  // Shared send dispatch for an already-resolved live session. Used by the
189
196
  // `send` branch AND by the `spawn` branch when an explicit tag maps to a
190
197
  // live session (reuse path). Busy sessions queue the prompt; idle ones run a
@@ -194,7 +201,11 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
194
201
  const { session, sessionId, prompt } = prepared;
195
202
  const tag = registry.tagForSession(sessionId);
196
203
  if (canUseSessionSurface(session) && views.isSessionBusy(sessionId)) {
197
- const queued = await sessionSurface.enqueueTurn({ session, prompt, context: prepared.args.context || null });
204
+ const queued = await sessionSurface.enqueueTurn({
205
+ session,
206
+ prompt: handoffContent(prompt, prepared.args.attachmentParts),
207
+ context: prepared.args.context || null,
208
+ });
198
209
  if (queued) {
199
210
  return renderResult({ queued: true, ...extras, tag, sessionId, agent: session.agent || null, ...queued });
200
211
  }
@@ -204,7 +215,8 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
204
215
  views.isSessionBusy(sessionId) &&
205
216
  typeof mgr.enqueuePendingMessage === 'function'
206
217
  ) {
207
- const queueDepth = mgr.enqueuePendingMessage(sessionId, prompt);
218
+ // The queued follow-up keeps the forwarded files, as the canonical queue does.
219
+ const queueDepth = mgr.enqueuePendingMessage(sessionId, handoffContent(prompt, prepared.args.attachmentParts));
208
220
  return renderResult({ queued: true, ...extras, tag, sessionId, agent: session.agent || null, queueDepth });
209
221
  }
210
222
  const job = spawnFlow.startJob(
@@ -247,5 +259,5 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
247
259
  return true;
248
260
  }
249
261
 
250
- return { prepareSend, dispatchToExistingSession, wakeIdleWorker };
262
+ return { prepareSend, adoptCaller, dispatchToExistingSession, wakeIdleWorker };
251
263
  }