mixdog 1.2.5 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (493) hide show
  1. package/LICENSES/simple-icons-CC0-1.0.txt +30 -0
  2. package/NOTICE.md +19 -0
  3. package/package.json +4 -1
  4. package/scripts/check-model-recommendations.mjs +89 -0
  5. package/scripts/gate-local.mjs +7 -0
  6. package/scripts/lib/gate-scheduler.mjs +2 -2
  7. package/scripts/lib/isolated-test-env.mjs +16 -0
  8. package/scripts/lib/run-node-tests.mjs +5 -14
  9. package/scripts/provider-pingpong-live.mjs +9 -9
  10. package/src/agents/advisor/AGENT.md +4 -4
  11. package/src/agents/advisor/agent.json +1 -1
  12. package/src/agents/reviewer/AGENT.md +5 -4
  13. package/src/agents/reviewer/agent.json +1 -1
  14. package/src/defaults/shipped-history.json +17 -0
  15. package/src/defaults/skills/browser-use/SKILL.md +7 -1
  16. package/src/defaults/skills/computer-use/SKILL.md +3 -1
  17. package/src/defaults/skills/memory-management/SKILL.md +4 -1
  18. package/src/defaults/skills/setup/references/actions.md +11 -4
  19. package/src/defaults/skills/setup-guide/SKILL.md +175 -0
  20. package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
  21. package/src/defaults/skills/visualize/SKILL.md +3 -2
  22. package/src/lib/rules-builder.cjs +56 -7
  23. package/src/output-styles/common.md +22 -6
  24. package/src/output-styles/detailed.md +7 -5
  25. package/src/output-styles/minimal.md +7 -3
  26. package/src/output-styles/simple.md +2 -3
  27. package/src/rules/agent/AGENT.md +7 -1
  28. package/src/rules/agent-mode/AGENT_MODE.md +24 -0
  29. package/src/rules/agent-mode/MIXY.md +21 -0
  30. package/src/rules/agent-mode/ROUTINE.md +6 -0
  31. package/src/rules/lead/LEAD.md +9 -4
  32. package/src/rules/shared/10-tool-workflow.md +2 -1
  33. package/src/rules/shared/60-verification.md +4 -5
  34. package/src/rules/shared/70-delivery.md +3 -0
  35. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
  36. package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
  37. package/src/runtime/agent/orchestrator/config.mjs +6 -0
  38. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
  39. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +182 -13
  40. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +5 -3
  41. package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
  42. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +215 -0
  43. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +58 -64
  44. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
  45. package/src/runtime/agent/orchestrator/mcp/client.mjs +122 -15
  46. package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
  47. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
  48. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
  49. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
  50. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
  51. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
  52. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
  53. package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
  54. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
  55. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  56. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +41 -19
  57. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
  58. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
  59. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
  60. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
  61. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
  62. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
  63. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +11 -5
  64. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
  65. package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
  66. package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
  69. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
  70. package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
  71. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
  72. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  74. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
  75. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  76. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
  78. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
  79. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
  80. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  81. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
  82. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  83. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
  84. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
  85. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
  86. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
  88. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
  89. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
  90. package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
  91. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
  92. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
  93. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
  94. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
  95. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
  96. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
  97. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
  98. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
  99. package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
  100. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +98 -4
  101. package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
  102. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
  103. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +15 -8
  104. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
  105. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
  106. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
  107. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -4
  108. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +4 -1
  109. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +50 -20
  110. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
  111. package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
  112. package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
  113. package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
  114. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
  115. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
  116. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
  117. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +162 -0
  118. package/src/runtime/agent/orchestrator/session/agent-room.mjs +641 -0
  119. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
  120. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
  121. package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
  122. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
  123. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
  124. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
  125. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
  126. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +165 -0
  127. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
  128. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
  129. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
  130. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
  131. package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
  132. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
  133. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
  134. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
  135. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +16 -1
  136. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +82 -33
  137. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +11 -4
  138. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
  139. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
  140. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +7 -0
  141. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
  142. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +6 -1
  143. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  144. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
  145. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
  146. package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
  147. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
  148. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
  149. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
  150. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
  151. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
  152. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
  153. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
  154. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -5
  155. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +55 -8
  156. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
  157. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
  158. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
  159. package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
  160. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
  161. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +24 -0
  162. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
  163. package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
  164. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +70 -0
  165. package/src/runtime/agent/orchestrator/session/routine-result.mjs +277 -0
  166. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
  167. package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
  168. package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
  169. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
  170. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
  171. package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
  172. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
  173. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
  174. package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
  175. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
  176. package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +325 -0
  177. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +84 -21
  178. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
  179. package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
  180. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
  181. package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
  182. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
  183. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
  184. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
  185. package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
  186. package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
  187. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
  188. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +44 -1
  189. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
  190. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
  191. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
  192. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
  193. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
  194. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
  195. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
  196. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
  197. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
  198. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
  199. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
  200. package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
  201. package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
  202. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
  203. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
  205. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
  206. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
  207. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
  208. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
  209. package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
  210. package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
  211. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
  212. package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
  213. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
  214. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
  215. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
  216. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
  217. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
  218. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
  219. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
  220. package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
  221. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +123 -32
  222. package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
  224. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
  225. package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
  226. package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
  227. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
  228. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
  229. package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
  230. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  231. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
  232. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +64 -2
  233. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +10 -2
  234. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
  235. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +8 -0
  236. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -1
  237. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
  238. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +104 -55
  239. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
  240. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
  241. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
  242. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  243. package/src/runtime/attachments/office-extract.mjs +11 -9
  244. package/src/runtime/browser-bridge/client.mjs +24 -0
  245. package/src/runtime/channels/lib/scheduler.mjs +40 -12
  246. package/src/runtime/channels/lib/schedules-db.mjs +71 -12
  247. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
  248. package/src/runtime/channels/lib/webhook.mjs +0 -1
  249. package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
  250. package/src/runtime/channels/lib/worker-main.mjs +17 -20
  251. package/src/runtime/computer-bridge/client.mjs +28 -1
  252. package/src/runtime/connectors/gmail-app-password.mjs +690 -0
  253. package/src/runtime/connectors/google-mcp.mjs +446 -0
  254. package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
  255. package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
  256. package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
  257. package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
  258. package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
  259. package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
  260. package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
  261. package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
  262. package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
  263. package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
  264. package/src/runtime/memory/lib/memory.mjs +7 -1
  265. package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
  266. package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
  267. package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
  268. package/src/runtime/memory/lib/tool-call-handler.mjs +9 -5
  269. package/src/runtime/memory/tool-defs.mjs +5 -0
  270. package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
  271. package/src/runtime/office/core/tabular.mjs +1 -1
  272. package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
  273. package/src/runtime/office/portable/docx-formatting.mjs +1 -1
  274. package/src/runtime/office/portable/docx-runs.mjs +1 -1
  275. package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
  276. package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
  277. package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
  278. package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
  279. package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
  280. package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
  281. package/src/runtime/office/portable/portable-opc.mjs +27 -13
  282. package/src/runtime/office/portable/portable-pivot.mjs +3 -3
  283. package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
  284. package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
  285. package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
  286. package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
  287. package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
  288. package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
  289. package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
  290. package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
  291. package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
  292. package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
  293. package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
  294. package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
  295. package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
  296. package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
  297. package/src/runtime/office/portable/portable-xml.mjs +1 -1
  298. package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
  299. package/src/runtime/shared/agent-avatar.d.mts +64 -0
  300. package/src/runtime/shared/agent-avatar.mjs +320 -0
  301. package/src/runtime/shared/agent-route-config.d.mts +3 -0
  302. package/src/runtime/shared/agent-route-config.mjs +16 -0
  303. package/src/runtime/shared/atomic-file.mjs +36 -14
  304. package/src/runtime/shared/background-tasks.mjs +60 -20
  305. package/src/runtime/shared/child-spawn-gate.mjs +26 -16
  306. package/src/runtime/shared/config.mjs +8 -11
  307. package/src/runtime/shared/connector-accounts.mjs +15 -0
  308. package/src/runtime/shared/connector-catalog.d.mts +52 -0
  309. package/src/runtime/shared/connector-catalog.mjs +230 -0
  310. package/src/runtime/shared/connector-triggers.d.mts +3 -0
  311. package/src/runtime/shared/connector-triggers.mjs +43 -0
  312. package/src/runtime/shared/file-lock.mjs +7 -1
  313. package/src/runtime/shared/file-permissions-worker.mjs +38 -0
  314. package/src/runtime/shared/file-permissions.d.mts +19 -4
  315. package/src/runtime/shared/file-permissions.mjs +310 -4
  316. package/src/runtime/shared/git-runner-worker.mjs +6 -78
  317. package/src/runtime/shared/google-oauth-client.mjs +24 -0
  318. package/src/runtime/shared/held-request-host.d.mts +12 -0
  319. package/src/runtime/shared/held-request-host.mjs +71 -0
  320. package/src/runtime/shared/llm/http-agent.mjs +7 -3
  321. package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
  322. package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
  323. package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
  324. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
  325. package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
  326. package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
  327. package/src/runtime/shared/memory-snapshot.mjs +5 -1
  328. package/src/runtime/shared/notify-trace.mjs +8 -1
  329. package/src/runtime/shared/plain-preview.d.mts +1 -0
  330. package/src/runtime/shared/plain-preview.mjs +28 -0
  331. package/src/runtime/shared/pristine-execution-contract.json +5 -1
  332. package/src/runtime/shared/process-runner-worker.mjs +7 -0
  333. package/src/runtime/shared/process-runner.mjs +38 -0
  334. package/src/runtime/shared/provider-accounts.mjs +2 -1
  335. package/src/runtime/shared/provider-api-key.mjs +0 -1
  336. package/src/runtime/shared/read-row-numbers.mjs +1 -1
  337. package/src/runtime/shared/resource-admission.mjs +60 -18
  338. package/src/runtime/shared/routine-limits.d.mts +11 -0
  339. package/src/runtime/shared/routine-limits.mjs +21 -0
  340. package/src/runtime/shared/routine-trigger.d.mts +10 -0
  341. package/src/runtime/shared/routine-trigger.mjs +44 -0
  342. package/src/runtime/shared/run-child.mjs +84 -0
  343. package/src/runtime/shared/schedule-model-ref.mjs +9 -10
  344. package/src/runtime/shared/session-activity-signal.mjs +23 -0
  345. package/src/runtime/shared/shell-output-summary.mjs +23 -0
  346. package/src/runtime/shared/singleton-owner.mjs +126 -42
  347. package/src/runtime/shared/slow-span.mjs +4 -12
  348. package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
  349. package/src/runtime/shared/tool-output-limit.mjs +4 -2
  350. package/src/runtime/shared/tool-output-marker.mjs +58 -0
  351. package/src/runtime/shared/transcript-metadata.mjs +10 -0
  352. package/src/runtime/shared/turn-changes.mjs +0 -8
  353. package/src/runtime/shared/usage-readout-totals.mjs +56 -0
  354. package/src/runtime/shared/user-data-guard.mjs +131 -34
  355. package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
  356. package/src/runtime/shared/worktrees/git-head.mjs +20 -2
  357. package/src/runtime/shared/worktrees/lock.mjs +3 -2
  358. package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
  359. package/src/runtime/tidy/runners/biome.mjs +3 -1
  360. package/src/runtime/tidy/shadow.mjs +2 -1
  361. package/src/runtime/web-search/index.mjs +5 -7
  362. package/src/runtime/web-search/lib/formatter.mjs +42 -6
  363. package/src/runtime/web-search/tool-defs.mjs +6 -1
  364. package/src/session-runtime/agent-home-delivery.mjs +459 -0
  365. package/src/session-runtime/agent-profile-changes.mjs +21 -0
  366. package/src/session-runtime/agent-room-delivery.mjs +92 -0
  367. package/src/session-runtime/agent-task-sessions.mjs +200 -0
  368. package/src/session-runtime/boot/apis.mjs +50 -18
  369. package/src/session-runtime/boot/facade.mjs +5 -8
  370. package/src/session-runtime/boot/infrastructure.mjs +28 -17
  371. package/src/session-runtime/boot/tools.mjs +3 -0
  372. package/src/session-runtime/channel-config-api.mjs +53 -5
  373. package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
  374. package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
  375. package/src/session-runtime/held-requests.mjs +228 -0
  376. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
  377. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
  378. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
  379. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +31 -2
  380. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  381. package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
  382. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
  383. package/src/session-runtime/lifecycle/session-switch/resume.mjs +11 -4
  384. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
  385. package/src/session-runtime/lifecycle/shared.mjs +25 -2
  386. package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
  387. package/src/session-runtime/lifecycle/teardown.mjs +5 -2
  388. package/src/session-runtime/lifecycle-api.mjs +3 -1
  389. package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
  390. package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
  391. package/src/session-runtime/mcp-oauth-login.mjs +112 -15
  392. package/src/session-runtime/model-route/set-route.mjs +14 -3
  393. package/src/session-runtime/owned-automation-run.mjs +229 -0
  394. package/src/session-runtime/provider-auth/login.mjs +10 -6
  395. package/src/session-runtime/provider-auth/setup.mjs +19 -2
  396. package/src/session-runtime/provider-catalog-cache.mjs +101 -25
  397. package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
  398. package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
  399. package/src/session-runtime/provider-models.mjs +76 -10
  400. package/src/session-runtime/provider-readiness.mjs +4 -0
  401. package/src/session-runtime/resource-api.mjs +5 -0
  402. package/src/session-runtime/resource-mcp-api.mjs +107 -13
  403. package/src/session-runtime/resource-skills-api.mjs +12 -0
  404. package/src/session-runtime/room-member-gate.mjs +48 -0
  405. package/src/session-runtime/routine-home-turn.mjs +156 -0
  406. package/src/session-runtime/routine-owner.mjs +48 -0
  407. package/src/session-runtime/schedule-session-run.mjs +30 -64
  408. package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
  409. package/src/session-runtime/services/agent-tool/helpers.mjs +10 -0
  410. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
  411. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
  412. package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
  413. package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
  414. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
  415. package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
  416. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
  417. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
  418. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
  419. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
  420. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
  421. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
  422. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
  423. package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
  424. package/src/session-runtime/services/agent-tool.mjs +20 -0
  425. package/src/session-runtime/services/channel-admin.mjs +93 -24
  426. package/src/session-runtime/services/memory-access.mjs +37 -0
  427. package/src/session-runtime/services/provider-admin.mjs +166 -59
  428. package/src/session-runtime/services/schedule-access.mjs +91 -0
  429. package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
  430. package/src/session-runtime/services/usage-dashboard.mjs +27 -69
  431. package/src/session-runtime/session-create/session-options.mjs +34 -7
  432. package/src/session-runtime/session-hooks.mjs +16 -8
  433. package/src/session-runtime/setup-tool/executor.mjs +68 -6
  434. package/src/session-runtime/setup-tool/extended-actions.mjs +72 -14
  435. package/src/session-runtime/setup-tool/settings-contract.mjs +8 -6
  436. package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
  437. package/src/session-runtime/skills-api.mjs +16 -1
  438. package/src/session-runtime/tool-policy-refresh.mjs +238 -29
  439. package/src/session-runtime/turn/session-ops.mjs +10 -3
  440. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +11 -2
  441. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +3 -0
  442. package/src/session-runtime/usage-stats-api.mjs +6 -1
  443. package/src/session-runtime/webhook-session-run.mjs +49 -67
  444. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
  445. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +556 -22
  446. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
  447. package/src/session-runtime/workflow-agents-api.mjs +4 -1
  448. package/src/standalone/channel-transport/http-routes.mjs +10 -9
  449. package/src/standalone/daemon-agent-control.mjs +1 -8
  450. package/src/standalone/daemon-desktop-runtime.mjs +20 -7
  451. package/src/standalone/daemon-owner.mjs +117 -25
  452. package/src/standalone/daemon-session-control.mjs +11 -2
  453. package/src/standalone/daemon.mjs +61 -17
  454. package/src/standalone/session-call-cache.mjs +6 -0
  455. package/src/standalone/session-protocol.mjs +28 -1
  456. package/src/standalone/session-service/retention/busy.mjs +7 -2
  457. package/src/standalone/session-service/session-calls/session-turns.mjs +9 -0
  458. package/src/standalone/session-service.mjs +19 -0
  459. package/src/standalone/session-transport/routes.mjs +7 -6
  460. package/src/tui/app/model-options.mjs +39 -2
  461. package/src/tui/app/model-picker.mjs +16 -2
  462. package/src/tui/app/provider-setup-picker.mjs +1 -2
  463. package/src/tui/app/slash-commands.mjs +20 -0
  464. package/src/tui/dist/index.mjs +487 -128
  465. package/src/tui/session/context-state.mjs +6 -1
  466. package/src/tui/session/notice-surface.mjs +35 -4
  467. package/src/tui/session/notice-text.mjs +0 -1
  468. package/src/tui/session/queue-helpers.mjs +2 -1
  469. package/src/tui/session/session-api/extensions.mjs +4 -0
  470. package/src/tui/session/session-api/intake/submission.mjs +12 -13
  471. package/src/tui/session/session-api/integrations.mjs +9 -5
  472. package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
  473. package/src/tui/session/session-api/lifecycle.mjs +17 -1
  474. package/src/tui/session/session-api/routes.mjs +48 -3
  475. package/src/tui/session/session-flow/drain.mjs +20 -3
  476. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
  477. package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
  478. package/src/tui/session/session-flow/steering.mjs +104 -24
  479. package/src/tui/session/session-flow.mjs +2 -0
  480. package/src/tui/session/tool-approval.mjs +26 -5
  481. package/src/tui/session/transcript-intake.mjs +6 -2
  482. package/src/tui/session/transcript-spill.mjs +5 -1
  483. package/src/tui/session/tui-steering-persist.mjs +65 -42
  484. package/src/tui/session/turn-live-call.mjs +56 -0
  485. package/src/tui/session/turn-stream.mjs +33 -0
  486. package/src/tui/session/turn.mjs +50 -7
  487. package/src/ui/statusline.mjs +1 -6
  488. package/src/ui/streaming-markdown-heal.mjs +24 -7
  489. package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
  490. package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
  491. package/src/workflows/default/WORKFLOW.md +9 -13
  492. package/src/session-runtime/automation-agents.mjs +0 -94
  493. package/src/session-runtime/automation-workflow.mjs +0 -59
@@ -64,6 +64,15 @@ import {
64
64
  beginOAuthLogin as beginCommandCodeOAuthLogin,
65
65
  loginOAuth as loginCommandCodeOAuth,
66
66
  } from '../../runtime/agent/orchestrator/providers/command-code-oauth-login.mjs';
67
+ import {
68
+ describeOpenCodeGoOAuthCredentials,
69
+ forgetOpenCodeGoOAuthCredentials,
70
+ hasOpenCodeGoOAuthCredentials,
71
+ } from '../../runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs';
72
+ import {
73
+ beginOAuthLogin as beginOpenCodeGoOAuthLogin,
74
+ loginOAuth as loginOpenCodeGoOAuth,
75
+ } from '../../runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs';
67
76
  import {
68
77
  beginCursorOAuthLogin,
69
78
  describeCursorOAuthCredentials,
@@ -101,7 +110,6 @@ import {
101
110
  } from '../../runtime/agent/orchestrator/providers/custom-provider-config.mjs';
102
111
 
103
112
  const API_PROVIDERS = Object.freeze([
104
- Object.freeze({ id: 'opencode-go', name: 'OpenCode Go API', env: 'OPENCODE_API_KEY', url: 'https://opencode.ai' }),
105
113
  Object.freeze({ id: 'openrouter', name: 'OpenRouter', env: 'OPENROUTER_API_KEY', url: 'https://openrouter.ai/keys' }),
106
114
  Object.freeze({
107
115
  id: 'openai',
@@ -176,6 +184,16 @@ const OAUTH_PROVIDERS = Object.freeze([
176
184
  begin: beginCommandCodeOAuthLogin,
177
185
  login: loginCommandCodeOAuth,
178
186
  }),
187
+ Object.freeze({
188
+ id: 'opencode-go-oauth',
189
+ name: 'OpenCode Go OAuth',
190
+ desc: 'Sign in with your OpenCode account (OpenCode Go subscription)',
191
+ has: hasOpenCodeGoOAuthCredentials,
192
+ describe: describeOpenCodeGoOAuthCredentials,
193
+ forget: forgetOpenCodeGoOAuthCredentials,
194
+ begin: beginOpenCodeGoOAuthLogin,
195
+ login: loginOpenCodeGoOAuth,
196
+ }),
179
197
  Object.freeze({
180
198
  id: 'mimo-oauth',
181
199
  name: 'MiMo',
@@ -349,6 +367,7 @@ function oauthAuthFields(p, auth) {
349
367
  status: auth.status || (authenticated ? 'Set' : 'Not Set'),
350
368
  detail: auth.detail || p.desc,
351
369
  expiresAt: auth.expiresAt || null,
370
+ plan: auth.plan || null,
352
371
  usable: auth.usable === true || (auth.usable == null && authenticated),
353
372
  refreshable: auth.refreshable === true,
354
373
  reauthRequired: auth.reauthRequired === true,
@@ -381,7 +400,7 @@ export function isCustomProviderConfig(entry) {
381
400
  return Boolean(entry) && typeof entry === 'object' && entry.type === 'custom';
382
401
  }
383
402
 
384
- export function isCustomProviderId(id) {
403
+ function isCustomProviderId(id) {
385
404
  return CUSTOM_ID_RE.test(String(id || ''));
386
405
  }
387
406
 
@@ -552,7 +571,11 @@ async function modelProxyProviderSetup(options) {
552
571
  // Signed in but switched off on the desktop.
553
572
  else if (!enabled && authState === 'present') status = 'Off';
554
573
  return {
555
- id, name, group, type, enabled,
574
+ id,
575
+ name,
576
+ group,
577
+ type,
578
+ enabled,
556
579
  authenticated,
557
580
  usable,
558
581
  ...(group === 'local' ? { detected: enabled } : {}),
@@ -847,6 +870,10 @@ export function listProviderAccounts(provider) {
847
870
  let identity = null;
848
871
  if (typeof auth.email === 'string' && auth.email.trim()) identity = auth.email.trim();
849
872
  else if (typeof auth.accountId === 'string' && auth.accountId.trim()) identity = auth.accountId.trim();
873
+ // An organization-scoped login names the organization it acts for.
874
+ if (typeof auth.orgName === 'string' && auth.orgName.trim()) {
875
+ identity = identity ? `${identity} · ${auth.orgName.trim()}` : auth.orgName.trim();
876
+ }
850
877
  return {
851
878
  id: row.id,
852
879
  label: row.label,
@@ -932,8 +959,8 @@ async function withTimeout(run, ms, label) {
932
959
  }
933
960
  }
934
961
 
935
- function existingCustomEntry(cfgMod, id) {
936
- const entry = cfgMod.loadConfig().providers?.[id];
962
+ function existingCustomEntry(config, id) {
963
+ const entry = config.providers?.[id];
937
964
  if (!isCustomProviderId(id) || !isCustomProviderConfig(entry)) throw new Error(`unknown custom provider "${id}"`);
938
965
  return entry;
939
966
  }
@@ -995,16 +1022,15 @@ function withStoredSettings(input, entry) {
995
1022
  return out;
996
1023
  }
997
1024
 
998
- // Validated, secret-free config for `input`; the key (typed, else stored for an
999
- // existing provider) is resolved separately and never enters the config.
1000
- async function resolveCustomInput(cfgMod, rawInput, options) {
1001
- let input = inputObject(rawInput);
1002
- validateCustomTransportFields(input);
1025
+ // Validated, secret-free config for `input` over one config snapshot (the
1026
+ // stored entry supplies an edit's omitted settings); the key (typed, else
1027
+ // stored for an existing provider) is resolved separately and never enters
1028
+ // the config. Synchronous, so a caller can merge and commit one snapshot.
1029
+ function customInputAt(snapshot, input, normalizeCustomProviderConfig, options) {
1003
1030
  const id = input.id === undefined ? null : input.id;
1004
- if (id) input = withStoredSettings(input, existingCustomEntry(cfgMod, id));
1005
- const { normalizeCustomProviderConfig } = await loadCustomProviderModule();
1006
- const config = normalizeCustomProviderConfig(input, options);
1007
- const typed = typeof input.apiKey === 'string' ? input.apiKey.trim() : '';
1031
+ const merged = id ? withStoredSettings(input, existingCustomEntry(snapshot, id)) : input;
1032
+ const config = normalizeCustomProviderConfig(merged, options);
1033
+ const typed = typeof merged.apiKey === 'string' ? merged.apiKey.trim() : '';
1008
1034
  const keyless = config.auth === 'none';
1009
1035
  const envName = keyless ? '' : config.apiKeyEnv || '';
1010
1036
  let apiKey = '';
@@ -1013,36 +1039,71 @@ async function resolveCustomInput(cfgMod, rawInput, options) {
1013
1039
  return { id, config, typed: keyless || envName ? '' : typed, apiKey, keyless, envName };
1014
1040
  }
1015
1041
 
1042
+ async function resolveCustomInput(cfgMod, rawInput, options) {
1043
+ const input = inputObject(rawInput);
1044
+ validateCustomTransportFields(input);
1045
+ const { normalizeCustomProviderConfig } = await loadCustomProviderModule();
1046
+ return customInputAt(cfgMod.loadConfig(), input, normalizeCustomProviderConfig, options);
1047
+ }
1048
+
1049
+ function requireCustomKey({ apiKey, keyless, envName }) {
1050
+ if (!keyless && !envName && !apiKey) throw new Error('API key is required');
1051
+ }
1052
+
1053
+ // One key transaction per provider, from reading the rollback key to the
1054
+ // config commit or rollback: a failed save restores the key the preceding
1055
+ // save committed and never one a newer save wrote. Settings-only saves and
1056
+ // other providers never wait.
1057
+ const customKeySaves = new Map();
1058
+
1059
+ function serializeCustomKeySave(id, run) {
1060
+ const result = (customKeySaves.get(id) || Promise.resolve()).then(run);
1061
+ const settled = result.then(
1062
+ () => {},
1063
+ () => {}
1064
+ );
1065
+ customKeySaves.set(id, settled);
1066
+ settled.then(() => {
1067
+ if (customKeySaves.get(id) === settled) customKeySaves.delete(id);
1068
+ });
1069
+ return result;
1070
+ }
1071
+
1016
1072
  export async function saveCustomProvider(cfgMod, rawInput) {
1017
1073
  requireLocalProviderManagement();
1018
- const {
1019
- id: existingId,
1020
- config,
1021
- typed,
1022
- apiKey,
1023
- keyless,
1024
- envName,
1025
- } = await resolveCustomInput(cfgMod, rawInput, { requireModels: false });
1026
- if (!keyless && !envName && !apiKey) throw new Error('API key is required');
1074
+ // Early verdict: an invalid save never touches the keychain.
1075
+ const resolved = await resolveCustomInput(cfgMod, rawInput, { requireModels: false });
1076
+ requireCustomKey(resolved);
1077
+ const { id: existingId, typed } = resolved;
1027
1078
  const id = existingId || `custom-${randomUUID()}`;
1028
- const entry = { ...config, type: 'custom', enabled: config.enabled !== false };
1029
- const account = SECRET_ACCOUNTS.agentApiKey(id);
1030
- const previousKey = typed && existingId ? getAgentApiKey(id) : null;
1031
- if (typed) await saveSecretAsync(account, typed);
1032
- try {
1033
- const current = cfgMod.loadConfig();
1034
- cfgMod.saveConfig(
1035
- { ...current, providers: { ...(current.providers || {}), [id]: entry } },
1036
- { baseConfig: current }
1037
- );
1038
- } catch (error) {
1039
- if (typed) {
1040
- if (previousKey) await saveSecretAsync(account, previousKey);
1041
- else await deleteSecretAsync(account);
1079
+ const { normalizeCustomProviderConfig } = await loadCustomProviderModule();
1080
+ const commit = async () => {
1081
+ const account = SECRET_ACCOUNTS.agentApiKey(id);
1082
+ const previousKey = typed && existingId ? getAgentApiKey(id) : null;
1083
+ if (typed) await saveSecretAsync(account, typed);
1084
+ let entry;
1085
+ try {
1086
+ // Synchronous from here: omitted settings come from the config this
1087
+ // save commits over, so an edit that landed during the awaits above (a
1088
+ // model's visibility, a peer save, a removal) is never reverted.
1089
+ const current = cfgMod.loadConfig();
1090
+ const latest = customInputAt(current, rawInput, normalizeCustomProviderConfig, { requireModels: false });
1091
+ requireCustomKey(latest);
1092
+ entry = { ...latest.config, type: 'custom', enabled: latest.config.enabled !== false };
1093
+ cfgMod.saveConfig(
1094
+ { ...current, providers: { ...(current.providers || {}), [id]: entry } },
1095
+ { baseConfig: current }
1096
+ );
1097
+ } catch (error) {
1098
+ if (typed) {
1099
+ if (previousKey) await saveSecretAsync(account, previousKey);
1100
+ else await deleteSecretAsync(account);
1101
+ }
1102
+ throw error;
1042
1103
  }
1043
- throw error;
1044
- }
1045
- return customProviderRow(id, entry);
1104
+ return customProviderRow(id, entry);
1105
+ };
1106
+ return typed ? serializeCustomKeySave(id, commit) : commit();
1046
1107
  }
1047
1108
 
1048
1109
  const MODEL_PATCH_KEYS = new Set(['manual', 'hidden', 'name', 'contextWindow', 'maxOutputTokens', 'reasoning']);
@@ -1078,7 +1139,7 @@ export async function updateCustomProviderModel(cfgMod, rawId, rawModelId, patch
1078
1139
  // Everything below is synchronous: the provider is read, patched and saved
1079
1140
  // without yielding, so a concurrent update can never be overwritten by a
1080
1141
  // provider object read before the await above.
1081
- const entry = existingCustomEntry(cfgMod, id);
1142
+ const entry = existingCustomEntry(cfgMod.loadConfig(), id);
1082
1143
  const current = normalizeCustomProviderConfig(entry, { requireModels: false });
1083
1144
  const overrides = new Map(Object.entries(current.modelOverrides || {}));
1084
1145
  if (patch === null) {
@@ -1128,6 +1189,69 @@ export async function updateCustomProviderModel(cfgMod, rawId, rawModelId, patch
1128
1189
  return customProviderRow(id, saved);
1129
1190
  }
1130
1191
 
1192
+ const MODEL_PREFERENCE_KEYS = new Set(['model', 'hidden', 'favorite']);
1193
+ export const MODEL_PREFERENCE_CHANGES_MAX = 5_000;
1194
+
1195
+ function modelPreferenceChanges(raw) {
1196
+ if (!Array.isArray(raw) || raw.length > MODEL_PREFERENCE_CHANGES_MAX) {
1197
+ throw new TypeError('model preference changes are invalid');
1198
+ }
1199
+ return raw.map((change) => {
1200
+ plainPatch(change, MODEL_PREFERENCE_KEYS, 'model preference change');
1201
+ const model = typeof change.model === 'string' ? change.model.trim() : '';
1202
+ if (!model) throw new TypeError('model id is required');
1203
+ for (const key of ['hidden', 'favorite']) {
1204
+ if (change[key] !== undefined && typeof change[key] !== 'boolean') {
1205
+ throw new TypeError(`model preference ${key} is invalid`);
1206
+ }
1207
+ }
1208
+ return { model, hidden: change.hidden, favorite: change.favorite };
1209
+ });
1210
+ }
1211
+
1212
+ /**
1213
+ * The model management card's save for one provider: whether each model is
1214
+ * listed in /model (`hidden`) and whether it is a favorite. Both live in the
1215
+ * shared per-model store `modelSettings["provider/model"]` — except a custom
1216
+ * provider's visibility, which stays its own `modelOverrides[id].hidden`, the
1217
+ * store its edit dialog, the runtime catalog and SSH servers already honor.
1218
+ * `hidden: false` is an explicit choice (it also lists a model the family
1219
+ * limit would leave out); an absent field keeps the stored value.
1220
+ */
1221
+ export function saveModelPreferences(cfgMod, rawProvider, rawChanges) {
1222
+ const provider = String(rawProvider || '').trim();
1223
+ const changes = modelPreferenceChanges(rawChanges);
1224
+ const full = cfgMod.loadConfig();
1225
+ if (!isKnownProvider(provider, full)) throw new TypeError(`unknown provider "${provider}"`);
1226
+ const custom = isCustomProviderId(provider);
1227
+ const modelSettings = { ...(full.modelSettings || {}) };
1228
+ for (const { model, hidden, favorite } of changes) {
1229
+ const key = `${provider}/${model}`;
1230
+ const setting = { ...(modelSettings[key] || {}) };
1231
+ if (hidden !== undefined && !custom) setting.hidden = hidden;
1232
+ if (favorite === true) setting.favorite = true;
1233
+ else if (favorite === false) delete setting.favorite;
1234
+ if (Object.keys(setting).length) modelSettings[key] = setting;
1235
+ else delete modelSettings[key];
1236
+ }
1237
+ const next = { ...full, modelSettings };
1238
+ const customHidden = custom ? changes.filter((change) => change.hidden !== undefined) : [];
1239
+ if (customHidden.length) {
1240
+ requireLocalProviderManagement();
1241
+ const entry = full.providers[provider];
1242
+ const current = normalizeStoredCustomConfig(entry);
1243
+ const overrides = new Map(Object.entries(current.modelOverrides || {}));
1244
+ for (const { model, hidden } of customHidden) overrides.set(model, { ...overrides.get(model), hidden });
1245
+ const config = normalizeStoredCustomConfig({ ...current, modelOverrides: Object.fromEntries(overrides) });
1246
+ next.providers = {
1247
+ ...full.providers,
1248
+ [provider]: { ...config, type: 'custom', enabled: entry.enabled !== false },
1249
+ };
1250
+ }
1251
+ cfgMod.saveConfig(next, { baseConfig: full });
1252
+ return { provider, changed: changes.length, customCatalogChanged: customHidden.length > 0 };
1253
+ }
1254
+
1131
1255
  // Drops every stored model setting and route that names the provider.
1132
1256
  function withoutProviderReferences(config, id) {
1133
1257
  const next = { ...config };
@@ -1152,7 +1276,7 @@ function withoutProviderReferences(config, id) {
1152
1276
  export async function removeCustomProvider(cfgMod, rawId) {
1153
1277
  requireLocalProviderManagement();
1154
1278
  const id = String(rawId || '').trim();
1155
- existingCustomEntry(cfgMod, id);
1279
+ existingCustomEntry(cfgMod.loadConfig(), id);
1156
1280
  // Secret first: a real keychain failure (locked, permission) leaves the
1157
1281
  // provider registered so the removal can be retried. A missing secret
1158
1282
  // (keyless provider) is not an error.
@@ -1235,23 +1359,6 @@ export async function saveOpenAIUsageSessionKey(cfgMod, secret) {
1235
1359
  return { provider: 'openai', type: 'usage-auth', authenticated: true };
1236
1360
  }
1237
1361
 
1238
- export async function saveOpenCodeGoUsageAuth(cfgMod, { apiKey } = {}) {
1239
- requireLocalProviderManagement();
1240
- const secret = String(apiKey || '').trim();
1241
- if (!secret) throw new Error('OpenCode console API key is required for usage lookup');
1242
- // Subscription meters are read with a console service-account key holding the
1243
- // `all` permission. The console accepts no other credential for them, so
1244
- // rejecting anything else here keeps unusable auth out of the keychain.
1245
- if (!/^(?:oc_sk_|sk-)/.test(secret))
1246
- throw new Error('OpenCode usage auth must be a console API key (oc_sk_… or sk-…) with all permissions');
1247
- await saveSecretAsync(SECRET_ACCOUNTS.opencodeGoConsoleKey, secret);
1248
- // Usage auth may be a different key from the inference key. Only flip the
1249
- // model provider on when a model key actually exists; otherwise usage-only
1250
- // setups get routed to the provider with apiKey 'no-key' and fail with 401s.
1251
- if (getAgentApiKey('opencode-go')) updateConfigProvider(cfgMod, 'opencode-go', { enabled: true });
1252
- return { provider: 'opencode-go', type: 'usage-auth', authenticated: true };
1253
- }
1254
-
1255
1362
  export async function forgetProviderAuth(cfgModOrProvider, maybeProvider, requestedAccountId) {
1256
1363
  requireLocalProviderManagement();
1257
1364
  const cfgMod = maybeProvider === undefined ? null : cfgModOrProvider;
@@ -0,0 +1,91 @@
1
+ // Who may manage automations (schedules and webhooks) from a chat, by the
2
+ // calling session's provenance. Enforced by every setup automation action
3
+ // (setup-tool/extended-actions.mjs), the chat-facing door of channel-admin:
4
+ // - the human's own sessions (an ordinary Lead session, Mixy's home) manage
5
+ // every automation and may move one to an agent that exists;
6
+ // - another agent's home thread manages only the automations it owns and can
7
+ // never give one away;
8
+ // - a headless run (schedule, webhook, delegated agent, or a session that
9
+ // cannot be resolved) manages none — nor does it change any other setting
10
+ // (setup-tool/executor.mjs refuses every mutating setup action for it).
11
+ // - a group-room member session is no background run, but it speaks for the
12
+ // room, not for the user: it creates or changes no agent, automation or
13
+ // other setting either.
14
+ // The app's own panels call channel-admin directly and act for the human.
15
+ import { MIXY_AGENT_ID, agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
16
+ import { roomMemberOfSession } from '../../runtime/agent/orchestrator/session/agent-room.mjs';
17
+ import { mixyDisplayName } from '../../runtime/agent/orchestrator/session/mixy-name.mjs';
18
+ import { isAgentOwner } from '../../runtime/agent/orchestrator/agent-owner.mjs';
19
+
20
+ const INTERACTIVE_SOURCE_TYPES = new Set(['', 'lead', 'cli']);
21
+
22
+ /** `{ kind: 'human' | 'agent' | 'room-member' | 'headless', agentId? }` of a session record. */
23
+ export function scheduleCallerScope(session) {
24
+ const id = String(session?.id || '');
25
+ const member = roomMemberOfSession(id);
26
+ if (member) return { kind: 'room-member', agentId: member.agentId };
27
+ const homeAgent = agentIdOfHomeSession(id);
28
+ if (homeAgent) return homeAgent === MIXY_AGENT_ID ? { kind: 'human' } : { kind: 'agent', agentId: homeAgent };
29
+ const headless =
30
+ !id ||
31
+ isAgentOwner(session) ||
32
+ Boolean(session.parentSessionId) ||
33
+ Boolean(session.ownerSessionId && session.ownerSessionId !== id) ||
34
+ !INTERACTIVE_SOURCE_TYPES.has(String(session.sourceType || '').toLowerCase());
35
+ return headless ? { kind: 'headless' } : { kind: 'human' };
36
+ }
37
+
38
+ /** Throws unless `scope` may `action` the `kind` ('schedule' | 'webhook')
39
+ * automation `current` (null when creating) with `owner` the requested owner
40
+ * ('' keeps the saved one). `agentIds` are the agents a transfer may name;
41
+ * Mixy always counts. */
42
+ export function assertAutomationAccess(
43
+ scope,
44
+ { kind = 'schedule', action, current = null, owner = '', agentIds = [] }
45
+ ) {
46
+ if (scope?.kind === 'room-member') throw new Error(`A group-room member cannot ${action} ${kind}s`);
47
+ if (scope?.kind !== 'human' && scope?.kind !== 'agent') {
48
+ throw new Error(`A background run cannot ${action} ${kind}s`);
49
+ }
50
+ const requested = String(owner ?? '').trim();
51
+ const saved = current ? current.owner || MIXY_AGENT_ID : '';
52
+ if (scope.kind === 'agent') {
53
+ if (current && saved !== scope.agentId) {
54
+ throw new Error(
55
+ `${kind === 'webhook' ? 'Webhook' : 'Schedule'} "${current.name}" belongs to another agent; this thread manages only its own ${kind}s`
56
+ );
57
+ }
58
+ if (requested && requested !== scope.agentId) throw new Error(`This thread cannot give a ${kind} to another agent`);
59
+ return;
60
+ }
61
+ if (requested && requested !== saved && requested !== MIXY_AGENT_ID && !agentIds.includes(requested)) {
62
+ throw new Error(`Agent "${requested}" does not exist`);
63
+ }
64
+ }
65
+
66
+ /** Throws unless `caller` (scope `scope`) is Mixy — its home thread or an
67
+ * ordinary Lead session acting as 'lead': only Mixy creates, edits or
68
+ * deletes agent definitions from a chat. The app's own panels call the agent
69
+ * editor directly and act for the human. */
70
+ export function assertAgentEditorAccess(scope, caller, action) {
71
+ const acting = String(caller?.agent || '').trim();
72
+ if (scope?.kind === 'human' && (!acting || acting === MIXY_AGENT_ID)) return;
73
+ const name = mixyDisplayName();
74
+ throw new Error(
75
+ `Only ${name} (the representative agent) can create, edit or delete agents (setup ${action}); ask the user to do it with ${name} or in the Agents settings`
76
+ );
77
+ }
78
+
79
+ /** Throws when an agent's home thread changes another agent's settings. */
80
+ export function assertOwnAgentSettings(scope, agentId, action) {
81
+ if (scope?.kind === 'agent' && String(agentId || '').trim() !== scope.agentId) {
82
+ throw new Error(`This thread manages only its own agent's settings (setup ${action})`);
83
+ }
84
+ }
85
+
86
+ /** Throws when `scope` is a headless run: it reads settings, never changes them. */
87
+ export function assertInteractiveCaller(scope, action) {
88
+ if (scope?.kind === 'human' || scope?.kind === 'agent') return;
89
+ if (scope?.kind === 'room-member') throw new Error(`A group-room member cannot change settings (setup ${action})`);
90
+ throw new Error(`A background run cannot change settings (setup ${action})`);
91
+ }
@@ -242,7 +242,7 @@ function providerDescription(id, group) {
242
242
  return 'MiMo Token Plan subscription quota';
243
243
  case 'antigravity-oauth':
244
244
  return 'Antigravity subscription quota';
245
- case 'opencode-go':
245
+ case 'opencode-go-oauth':
246
246
  return 'OpenCode Go subscription quota';
247
247
  case 'openai':
248
248
  return 'OpenAI API billing';
@@ -349,7 +349,7 @@ const PROVIDER_RANKS = {
349
349
  'mimo-oauth': 34,
350
350
  'cursor-oauth': 35,
351
351
  'antigravity-oauth': 36,
352
- 'opencode-go': 40,
352
+ 'opencode-go-oauth': 38,
353
353
  openai: 50,
354
354
  anthropic: 60,
355
355
  deepseek: 70,
@@ -2,11 +2,6 @@ import {
2
2
  fetchOAuthUsageSnapshot,
3
3
  readCachedOAuthUsageSnapshot,
4
4
  } from '../../runtime/agent/orchestrator/providers/oauth-usage.mjs';
5
- import {
6
- fetchOpenCodeGoUsageSnapshot,
7
- openCodeGoUsageConfigStatus,
8
- readCachedOpenCodeGoUsageSnapshot,
9
- } from '../../runtime/agent/orchestrator/providers/opencode-go-usage.mjs';
10
5
  import {
11
6
  fetchApiUsageSnapshot,
12
7
  readCachedApiUsageSnapshot,
@@ -118,69 +113,32 @@ async function apiProviderRow(item, { config, providers, preview, refreshFor, sn
118
113
  if (row.authenticated) {
119
114
  let hasQuota = false;
120
115
  let apiUsageSnapshot = null;
121
- if (item.id === 'opencode-go') {
122
- const usageStatus = openCodeGoUsageConfigStatus(config);
123
- try {
124
- let snapshot = null;
125
- if (refreshFor(item.id)) snapshot = await fetchOpenCodeGoUsageSnapshot(config, { force: true });
126
- else snapshot = readCachedOpenCodeGoUsageSnapshot();
127
- if (!snapshot && !refreshFor(item.id) && usageStatus.ready) {
128
- snapshot = await fetchOpenCodeGoUsageSnapshot(config);
129
- }
130
- if (snapshot) {
131
- hasQuota = applyWindowQuota(row, snapshot?.quotaWindows, {
132
- source: 'opencode-go-console',
133
- detail: 'subscription quota',
134
- });
135
- row.updatedAt = num(snapshot?.cachedAt, null);
136
- } else {
137
- row.status = 'missing';
138
- row.source = 'usage-auth-missing';
139
- row.sourceLabel = 'usage auth';
140
- row.primary = '';
141
- row.detail = usageStatus.ready
142
- ? 'OpenCode Go usage not found'
143
- : 'Set an OpenCode console API key (all permissions) for usage';
144
- }
145
- } catch (err) {
146
- if (String(err?.code || '').startsWith('OPENCODE_GO_USAGE_')) {
147
- row.status = 'missing';
148
- row.source = 'usage-auth-missing';
149
- row.sourceLabel = 'usage auth';
150
- row.primary = '';
151
- row.detail = usageStatus.ready
152
- ? 'OpenCode Go usage not found'
153
- : 'Set an OpenCode console API key (all permissions) for usage';
154
- }
155
- }
156
- } else {
157
- const snapshot = await apiSnapshot(item.id, snapshotOptions(item.id));
158
- apiUsageSnapshot = snapshot;
159
- const known = snapshotRemaining(snapshot);
160
- const usage = snapshotUsage(snapshot);
161
- const tokenUsage = snapshotTokenUsage(snapshot);
162
- const windows = normaliseWindows(snapshot?.quotaWindows, clean(snapshot?.source) || 'provider-api');
163
- const estimated = localBudget(providerCfg);
164
- row.updatedAt = num(snapshot?.cachedAt, null);
165
- if (known) {
166
- applyKnownRemaining(row, known, { estimated: false });
167
- row.sourceLabel = 'API';
168
- hasQuota = true;
169
- } else if (windows.length) {
170
- hasQuota = applyWindowQuota(row, windows, {
171
- source: clean(snapshot?.source) || 'provider-api',
172
- detail: 'provider quota',
173
- });
174
- } else if (estimated) {
175
- applyKnownRemaining(row, estimated, { estimated: true });
176
- hasQuota = true;
177
- } else if (usage) {
178
- applyKnownUsage(row, usage);
179
- hasQuota = true;
180
- } else if (tokenUsage) {
181
- applyTokenUsage(row, tokenUsage);
182
- hasQuota = true;
183
- }
116
+ const snapshot = await apiSnapshot(item.id, snapshotOptions(item.id));
117
+ apiUsageSnapshot = snapshot;
118
+ const known = snapshotRemaining(snapshot);
119
+ const usage = snapshotUsage(snapshot);
120
+ const tokenUsage = snapshotTokenUsage(snapshot);
121
+ const windows = normaliseWindows(snapshot?.quotaWindows, clean(snapshot?.source) || 'provider-api');
122
+ const estimated = localBudget(providerCfg);
123
+ row.updatedAt = num(snapshot?.cachedAt, null);
124
+ if (known) {
125
+ applyKnownRemaining(row, known, { estimated: false });
126
+ row.sourceLabel = 'API';
127
+ hasQuota = true;
128
+ } else if (windows.length) {
129
+ hasQuota = applyWindowQuota(row, windows, {
130
+ source: clean(snapshot?.source) || 'provider-api',
131
+ detail: 'provider quota',
132
+ });
133
+ } else if (estimated) {
134
+ applyKnownRemaining(row, estimated, { estimated: true });
135
+ hasQuota = true;
136
+ } else if (usage) {
137
+ applyKnownUsage(row, usage);
138
+ hasQuota = true;
139
+ } else if (tokenUsage) {
140
+ applyTokenUsage(row, tokenUsage);
141
+ hasQuota = true;
184
142
  }
185
143
  if (!row.includeInTotal && !hasQuota) {
186
144
  const estimated = localBudget(providerCfg);
@@ -189,7 +147,7 @@ async function apiProviderRow(item, { config, providers, preview, refreshFor, sn
189
147
  hasQuota = true;
190
148
  }
191
149
  }
192
- if (item.id !== 'opencode-go' && !row.includeInTotal && !hasQuota) {
150
+ if (!row.includeInTotal && !hasQuota) {
193
151
  applyApiUnavailable(row, item.id, apiUsageSnapshot);
194
152
  }
195
153
  }
@@ -2,11 +2,14 @@
2
2
  // the current runtime state: route, tool spec, ownership/lane, workflow pack,
3
3
  // memory context and compaction.
4
4
  import { normalizeCompactionConfig } from '../../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
5
- import { hasOwn } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
5
+ import { clean, hasOwn } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
6
6
  import { toolSpecForMode } from '../../runtime/agent/orchestrator/runtime-core/effort.mjs';
7
- import { pluginDataDir } from '../runtime-paths.mjs';
7
+ import { STANDALONE_ROOT, pluginDataDir } from '../runtime-paths.mjs';
8
+ import { readAgentFrontmatterPermission } from '../services/agent-tool/helpers.mjs';
8
9
  import { LEAD_DISALLOWED_TOOLS } from '../../runtime/agent/orchestrator/runtime-core/tool-defs.mjs';
9
10
  import { HEADLESS_TOOL_PROFILE } from '../../runtime/agent/orchestrator/runtime-core/tool-profile.mjs';
11
+ import { AGENT_MODE, resolveSessionMode } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
12
+ import { MIXY_AGENT_ID } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
10
13
 
11
14
  // Ownership and permission fields an agent-owned session inherits from its profile.
12
15
  function agentOwnedSessionFields(sessionProfile) {
@@ -31,14 +34,30 @@ export function sessionOptions(deps, coreMemoryContext) {
31
34
  // Load the active WORKFLOW.md pack once for both summary + context block.
32
35
  const {
33
36
  summary: workflow,
34
- context: leadWorkflowContext,
37
+ leadPromptParts,
35
38
  packContext,
36
39
  orchestrationMode,
37
40
  } = activeWorkflowContext(rt.config, dataDir);
38
41
  const sessionProfile = rt.sessionProfile && typeof rt.sessionProfile === 'object' ? rt.sessionProfile : null;
39
42
  const agentOwned = sessionProfile?.owner === 'agent' || sessionProfile?.visibility === 'agent-only';
40
- // Agent-owned sessions keep the Active Workflow block only.
41
- const workflowContext = agentOwned ? packContext : leadWorkflowContext;
43
+ // Agent or coding mode, from the one resolver (agent-mode.mjs).
44
+ const { mode: sessionMode, agentId: actingAgent } = resolveSessionMode({
45
+ sessionId: rt.reservedSessionId,
46
+ profile: sessionProfile,
47
+ });
48
+ // An agent's home thread: a user conversation that runs AS that agent (its
49
+ // AGENT.md role and permission); route comes with the create call.
50
+ const homeAgent = agentOwned ? '' : clean(sessionProfile?.homeAgent);
51
+ const homePermission = homeAgent ? readAgentFrontmatterPermission(homeAgent, dataDir, STANDALONE_ROOT) : null;
52
+ // A coding task session an agent created (session create): the user's own
53
+ // Lead, tagged with its origin; `sourceName` lets the Agents list file it.
54
+ const taskOrigin = agentOwned ? null : sessionProfile?.taskOrigin || null;
55
+ // Every session leads BP3 with the Active Workflow block; a Lead adds its
56
+ // orchestration and catalog slices (coding, agent mode or Mixy's).
57
+ const workflowContext = packContext;
58
+ const leadWorkflowParts = agentOwned
59
+ ? undefined
60
+ : leadPromptParts({ agentMode: sessionMode === AGENT_MODE, mixy: actingAgent === MIXY_AGENT_ID });
42
61
  const callerDisallowedTools = [
43
62
  ...(agentOwned ? [] : LEAD_DISALLOWED_TOOLS),
44
63
  ...(!agentOwned && rt.disallowDelegation ? ['agent'] : []),
@@ -51,7 +70,8 @@ export function sessionOptions(deps, coreMemoryContext) {
51
70
  tools: toolSpecForMode(rt.mode),
52
71
  ...(Array.isArray(schemaAllowedTools) ? { schemaAllowedTools } : {}),
53
72
  owner: agentOwned ? 'agent' : 'cli',
54
- agent: agentOwned ? sessionProfile?.agent || 'worker' : 'lead',
73
+ agent: agentOwned ? sessionProfile?.agent || 'worker' : homeAgent || 'lead',
74
+ ...(homePermission ? { permission: homePermission } : {}),
55
75
  lane: agentOwned ? 'agent' : 'cli',
56
76
  // One-shot `mixdog exec` runs carry their own source so session catalogs
57
77
  // can keep them out of the user's resumable list.
@@ -60,7 +80,12 @@ export function sessionOptions(deps, coreMemoryContext) {
60
80
  : rt.toolProfile === HEADLESS_TOOL_PROFILE
61
81
  ? 'exec'
62
82
  : 'lead',
63
- sourceName: agentOwned ? sessionProfile?.sourceName || sessionProfile?.agent || 'agent' : 'main',
83
+ sourceName: agentOwned
84
+ ? sessionProfile?.sourceName || sessionProfile?.agent || 'agent'
85
+ : taskOrigin
86
+ ? `agent:${taskOrigin.agentId}`
87
+ : 'main',
88
+ ...(taskOrigin ? { taskOrigin } : {}),
64
89
  ...(rt.approvalMode ? { approvalMode: rt.approvalMode } : {}),
65
90
  clientHostPid: sessionProfile?.clientHostPid || process.pid,
66
91
  mcpScopeId: rt.mcpScopeId,
@@ -71,6 +96,8 @@ export function sessionOptions(deps, coreMemoryContext) {
71
96
  coreMemoryContext,
72
97
  workflow,
73
98
  workflowContext,
99
+ ...(leadWorkflowParts ? { leadWorkflowParts } : {}),
100
+ sessionMode,
74
101
  orchestrationMode,
75
102
  fast: rt.route.fast === true,
76
103
  autoEffort: rt.route.autoEffort !== false,