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
@@ -1,5 +1,6 @@
1
1
  // Agent-scoped role markdown and 4-BP system prompt composition.
2
2
 
3
+ import { createHash } from 'node:crypto';
3
4
  import { existsSync, readdirSync } from 'node:fs';
4
5
  import { join } from 'node:path';
5
6
  import { compareCodePoints } from '../../../shared/code-point-order.mjs';
@@ -7,6 +8,7 @@ import { mixdogRoot } from '../../../shared/plugin-paths.mjs';
7
8
  import { readMarkdownDocument } from '../../../shared/markdown-frontmatter.mjs';
8
9
  import { listHiddenAgentsByKind, getAgentCatalogShareAgents } from '../internal-agents.mjs';
9
10
  import { mixdogGlobalDir, mtimeWithTtl, readSafe } from './skill-catalog.mjs';
11
+ import { mixyDisplayName } from '../session/mixy-name.mjs';
10
12
 
11
13
  // --- Agent-scoped instruction loader ---
12
14
  // Emits a BP2 agent/system block scoped to the calling agent:
@@ -45,6 +47,12 @@ const _scopedRoleInstructionsCache = new Map();
45
47
  const _scopedRoleInstructionsMtimeCache = new Map();
46
48
  const _ROLE_INSTRUCTIONS_MTIME_TTL_MS = 2000;
47
49
 
50
+ /** A saved AGENT.md applies to the next composition, even inside the mtime TTL. */
51
+ export function invalidateRoleInstructionsCache() {
52
+ _scopedRoleInstructionsCache.clear();
53
+ _scopedRoleInstructionsMtimeCache.clear();
54
+ }
55
+
48
56
  function loadHiddenAgentSnippets(pluginRoot) {
49
57
  try {
50
58
  const agentRulesDir = join(pluginRoot, 'rules', 'agent');
@@ -106,7 +114,9 @@ function loadAgentSections(pluginRoot) {
106
114
  name = entry.name.replace(/\.md$/, '');
107
115
  raw = readSafe(join(agentsDir, entry.name));
108
116
  }
109
- if (!name || !raw) continue;
117
+ // Mixy's own AGENT.md (agents/lead/) rides only Mixy's agent-mode
118
+ // prompt (loadMixyRoleSection), never another role catalog.
119
+ if (!name || !raw || name === 'lead') continue;
110
120
  const { body } = readMarkdownDocument(raw);
111
121
  if (!body) continue;
112
122
  byName.set(name, roleSection(name, body));
@@ -225,6 +235,144 @@ export function loadScopedRoleInstructions(agent, provider = null) {
225
235
  }
226
236
  }
227
237
 
238
+ // --- Agent persona (agents/<id>/PERSONA.md) ---
239
+ // Optional tone/addressing/personality guide, rendered right after the
240
+ // agent's role section. Read from the same directory that supplies the
241
+ // agent's AGENT.md (user data dir first, then shipped); the Lead (`lead`,
242
+ // Mixy) has no AGENT.md, so its persona is the first PERSONA.md found.
243
+ // The text depends only on the file, so the BP3 prefix is stable until the
244
+ // file changes; it is re-read per composition, so an edit applies next turn.
245
+ export const PERSONA_MAX_CHARS = 4000;
246
+ export const PERSONA_TRUNCATION_MARKER = '\n\n[persona truncated]';
247
+ const PERSONA_AGENT_ID = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
248
+
249
+ export function truncatePersona(text, max = PERSONA_MAX_CHARS) {
250
+ const value = typeof text === 'string' ? text.trim() : '';
251
+ if (value.length <= max) return value;
252
+ return value.slice(0, max).trimEnd() + PERSONA_TRUNCATION_MARKER;
253
+ }
254
+
255
+ export function loadAgentPersonaSection(agent) {
256
+ if (typeof agent !== 'string' || !PERSONA_AGENT_ID.test(agent) || agent.includes('..')) return '';
257
+ const isLead = agent === 'lead';
258
+ const pluginRoot = mixdogRoot();
259
+ const roots = [];
260
+ try {
261
+ const userDir = mixdogGlobalDir('agents');
262
+ if (userDir) roots.push(userDir);
263
+ } catch {
264
+ /* unresolvable data dir — shipped persona still loads */
265
+ }
266
+ if (pluginRoot) roots.push(join(pluginRoot, 'agents'));
267
+ for (const root of roots) {
268
+ const dir = join(root, agent);
269
+ if (!isLead && !existsSync(join(dir, 'AGENT.md'))) continue;
270
+ const persona = truncatePersona(readSafe(join(dir, 'PERSONA.md')) || '');
271
+ if (!persona) {
272
+ if (isLead) continue;
273
+ return '';
274
+ }
275
+ return [
276
+ '## Persona',
277
+ '',
278
+ 'Tone and style guide for how you speak, address the user and carry yourself. It never overrides tool, safety or role rules; those always win.',
279
+ '',
280
+ persona,
281
+ ].join('\n');
282
+ }
283
+ return '';
284
+ }
285
+
286
+ // --- Mixy's working style (agents/lead/AGENT.md, user data dir) ---
287
+ // The user-editable 일하는 방식 of Mixy, framed like any agent's role section.
288
+ // Agent mode only; empty or missing means no section. Re-read per
289
+ // composition, so an edit applies to the next prompt build.
290
+ export function loadMixyRoleSection() {
291
+ let raw = '';
292
+ try {
293
+ const userDir = mixdogGlobalDir('agents');
294
+ raw = userDir ? readSafe(join(userDir, 'lead', 'AGENT.md')) || '' : '';
295
+ } catch {
296
+ return '';
297
+ }
298
+ const { body } = readMarkdownDocument(raw);
299
+ const text = String(body || '').trim();
300
+ return text ? `# Agent Role Catalog\n\n${roleSection('lead', text)}` : '';
301
+ }
302
+
303
+ // --- Agent-mode identity (LEAD.md first line) ---
304
+ // "You are <name>, <what it does>." from the agent's manifest (agent.json, the
305
+ // name/description the editor writes), user copy first, then shipped. Mixy
306
+ // (the Lead configuration, id `lead`) has its own line, under the display name
307
+ // the user gave it (session/mixy-name.mjs), Mixy by default.
308
+ function agentManifest(agent) {
309
+ const roots = [];
310
+ try {
311
+ const userDir = mixdogGlobalDir('agents');
312
+ if (userDir) roots.push(userDir);
313
+ } catch {
314
+ /* unresolvable data dir — shipped manifest still loads */
315
+ }
316
+ const pluginRoot = mixdogRoot();
317
+ if (pluginRoot) roots.push(join(pluginRoot, 'agents'));
318
+ for (const root of roots) {
319
+ const dir = join(root, agent);
320
+ if (!existsSync(join(dir, 'AGENT.md'))) continue;
321
+ try {
322
+ const value = JSON.parse(readSafe(join(dir, 'agent.json')) || '{}');
323
+ return value && typeof value === 'object' ? value : {};
324
+ } catch {
325
+ return {};
326
+ }
327
+ }
328
+ return {};
329
+ }
330
+
331
+ export function agentModeIdentityLine(agent) {
332
+ if (agent === 'lead') return `You are ${mixyDisplayName()}, the user's assistant in Mixdog.`;
333
+ if (typeof agent !== 'string' || !PERSONA_AGENT_ID.test(agent) || agent.includes('..')) return '';
334
+ const oneLine = (value) => (typeof value === 'string' ? value.replace(/\s+/g, ' ').trim() : '');
335
+ const manifest = agentManifest(agent);
336
+ const name = oneLine(manifest.name) || agent;
337
+ const role = oneLine(manifest.description).replace(/[.。]+$/, '');
338
+ return role ? `You are ${name}. Your role: ${role}.` : `You are ${name}.`;
339
+ }
340
+
341
+ // --- Agent profile revision ---
342
+ // The files an agent's prompt sections (identity line, role, persona) are
343
+ // read from — its agent.json, AGENT.md and PERSONA.md in the user data dir and
344
+ // the shipped tree — as one hash. A session stamps it when its prompt is
345
+ // composed; another value means the profile was edited since
346
+ // (session-runtime/tool-policy-refresh.mjs refreshAgentProfile). '' for an
347
+ // invalid id.
348
+ export function agentProfileRevision(agent) {
349
+ if (typeof agent !== 'string' || !PERSONA_AGENT_ID.test(agent) || agent.includes('..')) return '';
350
+ const roots = [mixdogGlobalDir('agents')];
351
+ const pluginRoot = mixdogRoot();
352
+ if (pluginRoot) roots.push(join(pluginRoot, 'agents'));
353
+ const hash = createHash('sha256');
354
+ for (const root of roots) {
355
+ for (const file of ['agent.json', 'AGENT.md', 'PERSONA.md']) {
356
+ hash.update(`${root}\0${file}\0${readSafe(join(root, agent, file)) ?? '\u0001'}\0`);
357
+ }
358
+ }
359
+ return hash.digest('hex').slice(0, 24);
360
+ }
361
+
362
+ // --- Lead roster revision ---
363
+ // The bot roster a Lead's prompt lists (workflow/context.mjs leadPromptParts:
364
+ // the agent catalog and Mixy's contact catalog — never the orchestration
365
+ // mode, a setting that applies to new sessions), as one hash, stamped beside
366
+ // agentProfileRevision. A bot created, renamed, archived or restored changes
367
+ // it for every Lead whose prompt lists that bot.
368
+ export function leadRosterRevision(parts) {
369
+ const hash = createHash('sha256');
370
+ for (const slice of [parts?.agentCatalogContext, parts?.contactCatalogContext]) {
371
+ hash.update(`${slice || ''}\0`);
372
+ }
373
+ return hash.digest('hex').slice(0, 24);
374
+ }
375
+
228
376
  // --- Compose system prompt — 4-BP cache layout ---
229
377
  // Returns the three stable system blocks and the BP3 core used for refreshes.
230
378
  // They map directly to the breakpoint plan:
@@ -262,32 +410,53 @@ export function composeSystemPrompt(opts) {
262
410
  ]);
263
411
 
264
412
  // ── BP3: workflow/role + session environment layer ─────────────────
265
- const roleInstructionContext = opts.skipRoleCatalog
266
- ? ''
267
- : loadScopedRoleInstructions(opts.agent || null, opts.provider || null);
268
- // Keep the active workflow first within BP3 so it leads the role and
269
- // environment material that varies with the session.
413
+ let roleInstructionContext = '';
414
+ if (!opts.skipRoleCatalog) {
415
+ roleInstructionContext =
416
+ opts.agent === 'lead'
417
+ ? loadMixyRoleSection()
418
+ : loadScopedRoleInstructions(opts.agent || null, opts.provider || null);
419
+ }
420
+ // Persona follows the role; the Lead has no role section but may own a
421
+ // persona through agents/lead/PERSONA.md.
422
+ const personaContext = opts.agent && !opts.skipPersona ? loadAgentPersonaSection(opts.agent) : '';
270
423
  const coreMemory = skip.memory ? '' : trimmedPromptSlice(opts.coreMemoryContext);
271
424
  // User AGENTS.md / CLAUDE.md block (context/instruction-files.mjs), already
272
- // headed `# Instruction Files`; rides right after core memory.
425
+ // headed `# Instruction Files`; rides right before core memory.
273
426
  const instructionFiles = skip.claudemd ? '' : trimmedPromptSlice(opts.instructionFilesContext);
427
+ // Ordered for the longest shared prefix (session-prompt-composition.mjs):
428
+ // 1. shared by every Lead — the workflow pack and LEAD.md's common lines;
429
+ // 2. the mode block — coding: orchestration mode, LEAD.md's two passages,
430
+ // the full agent catalog; agent mode: the delegation block, their
431
+ // variants, AGENT_MODE.md, the sub-agent catalog (the same for every
432
+ // agent other than Mixy);
433
+ // 3. Mixy only — MIXY.md and its contact-agent catalog;
434
+ // 4. per session or agent, last — routine line, identity, caller prompt,
435
+ // role, persona, instruction files and core memory (changes most).
274
436
  const sessionMarkerCore = joinPromptSlices([
275
437
  trimmedPromptSlice(opts.workflowContext),
276
438
  opts.roleRules || '',
439
+ trimmedPromptSlice(opts.orchestrationContext),
440
+ opts.leadModeRules || '',
441
+ opts.agentModeRules || '',
442
+ trimmedPromptSlice(opts.agentCatalogContext),
443
+ opts.mixyRules || '',
444
+ trimmedPromptSlice(opts.contactCatalogContext),
445
+ opts.routineRules || '',
446
+ opts.identityContext || '',
277
447
  opts.userPrompt || '',
278
448
  roleInstructionContext,
279
- coreMemory ? `# Core Memory\n${coreMemory}` : '',
449
+ personaContext,
280
450
  instructionFiles,
451
+ coreMemory ? `# Core Memory\n${coreMemory}` : '',
281
452
  ]);
282
453
  // Response language is the LAST system text before the conversation. It
283
454
  // rides the environment block (not the tier3 core) because the `# Session`
284
455
  // / shell / git lines are English and would otherwise trail it, pulling the
285
456
  // pre-tool preamble toward English.
286
- const environmentParts = [
287
- opts.sessionStartContext,
288
- opts.environmentContext,
289
- opts.languageContext,
290
- ].map(trimmedPromptSlice);
457
+ const environmentParts = [opts.sessionStartContext, opts.environmentContext, opts.languageContext].map(
458
+ trimmedPromptSlice
459
+ );
291
460
  // Volatile session/project environment. Kept OUT of sessionMarkerCore so
292
461
  // Anthropic providers can leave it as an UNMARKED system block (covered by
293
462
  // the messages-tail breakpoint) while prefix-order providers still see it
@@ -174,8 +174,10 @@ export function collectSkills(cwd) {
174
174
  } catch {
175
175
  continue;
176
176
  }
177
- // Agent Skills requires the manifest name to match its folder.
178
- if (basename(dirname(filePath)) !== skill.name) continue;
177
+ // Agent Skills requires the manifest name to match its folder. Plugins
178
+ // are exempt: they ship nested layouts (skills/<plugin>/<topic>/) and
179
+ // load by their declared name; `seen` still settles collisions.
180
+ if (source !== 'plugin' && basename(dirname(filePath)) !== skill.name) continue;
179
181
  if (seen.has(skill.name)) continue;
180
182
  seen.add(skill.name);
181
183
  skills.push({
@@ -495,7 +497,7 @@ export function buildSkillResultEnvelope(name, content, skillDir) {
495
497
  body = body.replace(/\$\{MIXDOG_SKILL_NODE\}/g, SKILL_LAUNCHER_COMMAND);
496
498
  if (skillDir) {
497
499
  const normDir = String(skillDir).replace(/\\/g, '/');
498
- body = body.replace(/\$\{MIXDOG_SKILL_DIR\}/g, normDir);
500
+ body = body.replace(/\$\{MIXDOG_SKILL_DIR\}/g, () => normDir);
499
501
  const escapedDir = escapeSkillXmlText(normDir);
500
502
  dirLine = `<base-dir>${escapedDir}</base-dir>\n`;
501
503
  }
@@ -121,16 +121,26 @@ function _loadHiddenAgents() {
121
121
  * by an agents.json modification (tracked via maxMtimeRecursive in
122
122
  * collect.mjs) consume fresh metadata in the same process.
123
123
  */
124
+ // The agent-status pulse resolves a watchdog policy per worker row, and each
125
+ // lookup re-stat'ed every dependency file synchronously. The mtime probe runs
126
+ // at most once per interval; an edit is picked up by the next probe.
127
+ const HIDDEN_AGENTS_RECHECK_MS = 1000;
128
+ let _hiddenAgentsCheckedAt = 0;
129
+
124
130
  function _getHiddenAgents() {
131
+ const now = Date.now();
132
+ if (_hiddenAgentsCache && now - _hiddenAgentsCheckedAt < HIDDEN_AGENTS_RECHECK_MS) return _hiddenAgentsCache.map;
125
133
  // The mtime probe never throws; a load failure surfaces with the message
126
134
  // _loadHiddenAgents already gave it, and the stale cache is not reused.
127
135
  if (_hiddenAgentsCache && _maxMtime(_hiddenAgentsCache.files) <= _hiddenAgentsCache.mtime) {
136
+ _hiddenAgentsCheckedAt = now;
128
137
  return _hiddenAgentsCache.map;
129
138
  }
130
139
  const files = _hiddenAgentsDependencyFiles();
131
140
  const mtime = _maxMtime(files);
132
141
  const map = _loadHiddenAgents();
133
142
  _hiddenAgentsCache = { mtime, files, map };
143
+ _hiddenAgentsCheckedAt = now;
134
144
  return map;
135
145
  }
136
146
 
@@ -0,0 +1,215 @@
1
+ // Connector policy: which globally installed MCP servers (connectors) an agent
2
+ // or a project may use. Every installed connector is on by default for every
3
+ // agent and project, existing and future ones; a policy only switches some off:
4
+ // agents/<id>/agent.json connectors: { off: [serverId…], tools?: { [serverId]: { [tool]: permission } } }
5
+ // <data>/project-connectors.json { projects: { [projectRoot]: { off: [serverId…] } } }
6
+ // `tools` keeps per-tool overrides (auto | needs_approval | disabled); a tool
7
+ // without one is auto, except a catalog connector's high-risk tools, which
8
+ // ask (connectorToolDefault). A legacy agent list (an array: only its enabled
9
+ // entries were mounted) is enforced as written until the host converts it
10
+ // (migrateLegacyConnectorPolicy). A policy that cannot be read, or has neither
11
+ // shape, mounts nothing. Enforced at dispatch only: every session lists every
12
+ // connected tool, so the schema and the BP2 manifest stay shared.
13
+ import { readFileSync, statSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { cwdWithinProjects } from '../../../shared/extension-scopes.mjs';
16
+ import { resolvePluginData } from '../../../shared/plugin-paths.mjs';
17
+ import { isSelfMcpToolName, parseMcpToolName } from '../../../shared/tool-primitives.mjs';
18
+ import { connectorToolDefault } from '../../../shared/connector-catalog.mjs';
19
+ import { serverConnector } from './server-connectors.mjs';
20
+
21
+ export const CONNECTOR_PERMISSIONS = Object.freeze(['auto', 'needs_approval', 'disabled']);
22
+ export const PROJECT_CONNECTORS_FILE = 'project-connectors.json';
23
+
24
+ /** What an unreadable or malformed policy means: no connector is on. */
25
+ export const DENY_ALL_CONNECTORS = Object.freeze({
26
+ allow: Object.freeze([]),
27
+ off: Object.freeze([]),
28
+ tools: Object.freeze({}),
29
+ });
30
+
31
+ const AGENT_DIR_ID = /^[a-z0-9][a-z0-9._-]*$/i;
32
+ const POLICY_KEYS = new Set(['off', 'tools']);
33
+
34
+ const isPlainObject = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
35
+ const clean = (value) => (typeof value === 'string' ? value.trim() : '');
36
+ const uniqueIds = (list) => [...new Set((Array.isArray(list) ? list : []).map(clean).filter(Boolean))].sort();
37
+
38
+ function toolOverrides(value) {
39
+ const out = {};
40
+ for (const [server, tools] of Object.entries(isPlainObject(value) ? value : {})) {
41
+ const own = {};
42
+ for (const [tool, permission] of Object.entries(isPlainObject(tools) ? tools : {})) {
43
+ if (clean(tool) && CONNECTOR_PERMISSIONS.includes(permission)) own[clean(tool)] = permission;
44
+ }
45
+ if (clean(server) && Object.keys(own).length) out[clean(server)] = own;
46
+ }
47
+ return out;
48
+ }
49
+
50
+ /** A stored `connectors` field → `{ off, tools }`, or `{ allow, off, tools }`
51
+ * for a legacy list; null when absent. Throws on any other shape. */
52
+ export function parseConnectorPolicy(value) {
53
+ if (value == null) return null;
54
+ if (Array.isArray(value)) {
55
+ const allow = [];
56
+ const tools = {};
57
+ for (const item of value) {
58
+ const id = clean(item?.id);
59
+ if (!id) continue;
60
+ if (item.enabled === true) allow.push(id);
61
+ const own = toolOverrides({ [id]: item.tools })[id];
62
+ if (own) tools[id] = { ...tools[id], ...own };
63
+ }
64
+ return { allow: uniqueIds(allow), off: [], tools };
65
+ }
66
+ if (!isPlainObject(value) || Object.keys(value).some((key) => !POLICY_KEYS.has(key))) {
67
+ throw new Error('connectors must be { off: [connector id…], tools? }');
68
+ }
69
+ if (value.off != null && !Array.isArray(value.off)) throw new Error('connectors.off must be a list');
70
+ if (value.tools != null && !isPlainObject(value.tools)) throw new Error('connectors.tools must be an object');
71
+ return { off: uniqueIds(value.off), tools: toolOverrides(value.tools) };
72
+ }
73
+
74
+ /** The form a deny-list policy is saved in; null when it switches nothing off
75
+ * (the same as no policy). A legacy list must be migrated first. */
76
+ export function storedConnectorPolicy(policy) {
77
+ if (!policy) return null;
78
+ if (policy.allow) throw new Error('a legacy connector list must be migrated before it is saved');
79
+ const off = uniqueIds(policy.off);
80
+ const tools = toolOverrides(policy.tools);
81
+ if (!off.length && !Object.keys(tools).length) return null;
82
+ return { off, ...(Object.keys(tools).length ? { tools } : {}) };
83
+ }
84
+
85
+ /** A legacy list (or an unreadable policy) as the equivalent deny list over
86
+ * the installed connectors `installedIds`: each one it did not enable is off.
87
+ * A deny-list policy (or none) passes through. */
88
+ export function migrateLegacyConnectorPolicy(policy, installedIds) {
89
+ if (!policy?.allow) return policy;
90
+ const allow = new Set(policy.allow);
91
+ const missing = uniqueIds(installedIds).filter((id) => !allow.has(id));
92
+ return { off: uniqueIds([...policy.off, ...missing]), tools: toolOverrides(policy.tools) };
93
+ }
94
+
95
+ /** Whether connector `serverId` is on under `policy` (null: every one is). */
96
+ export function connectorEnabled(policy, serverId) {
97
+ if (!policy) return true;
98
+ if (policy.allow && !policy.allow.includes(serverId)) return false;
99
+ return !policy.off.includes(serverId);
100
+ }
101
+
102
+ // Policy files are stat-checked on every read (tiny files), so a save from
103
+ // any process applies to the next dispatch without an explicit flush.
104
+ const fileCache = new Map();
105
+
106
+ function cachedRead(path, read) {
107
+ let stat;
108
+ try {
109
+ stat = statSync(path);
110
+ } catch (error) {
111
+ // No file is the "no policy" state; any other fault means it cannot be read.
112
+ return error?.code === 'ENOENT' || error?.code === 'ENOTDIR' ? null : unreadable(path, error);
113
+ }
114
+ const cached = fileCache.get(path);
115
+ if (cached && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) return cached.value;
116
+ const value = read(path);
117
+ fileCache.set(path, { mtimeMs: stat.mtimeMs, size: stat.size, value });
118
+ return value;
119
+ }
120
+
121
+ function readJson(path, parse) {
122
+ let text;
123
+ try {
124
+ text = readFileSync(path, 'utf8');
125
+ } catch (error) {
126
+ return error?.code === 'ENOENT' || error?.code === 'ENOTDIR' ? null : unreadable(path, error);
127
+ }
128
+ try {
129
+ return parse(JSON.parse(text));
130
+ } catch (error) {
131
+ return unreadable(path, error);
132
+ }
133
+ }
134
+
135
+ // A policy that exists but cannot be trusted mounts nothing.
136
+ function unreadable(path, error) {
137
+ process.stderr.write(`[connectors] ${path} is unreadable (${error?.message || error}); denying all connectors\n`);
138
+ return DENY_ALL_CONNECTORS;
139
+ }
140
+
141
+ /** Uncached: the policy in the agent.json at `path` (see parseConnectorPolicy);
142
+ * null without a file or field, DENY_ALL_CONNECTORS when it cannot be
143
+ * trusted. The agent editor reads the policy through this too. */
144
+ export function readConnectorsFile(path) {
145
+ return readJson(path, (manifest) => parseConnectorPolicy(manifest?.connectors));
146
+ }
147
+
148
+ /** The agent's saved policy under `dataDir`, or null when it has none. */
149
+ export function agentConnectors(agentId, dataDir = resolvePluginData()) {
150
+ const id = clean(agentId);
151
+ if (!id || !AGENT_DIR_ID.test(id)) return null;
152
+ return cachedRead(join(dataDir, 'agents', id, 'agent.json'), readConnectorsFile);
153
+ }
154
+
155
+ /** Uncached: the project policy file → `[{ root, off }]`, null without one,
156
+ * DENY_ALL_CONNECTORS when it cannot be trusted. */
157
+ export function readProjectConnectorsFile(path) {
158
+ return readJson(path, (raw) => {
159
+ if (!isPlainObject(raw) || (raw.projects != null && !isPlainObject(raw.projects))) {
160
+ throw new Error('projects must be an object');
161
+ }
162
+ return Object.entries(raw.projects || {}).flatMap(([root, entry]) => {
163
+ if (!isPlainObject(entry) || (entry.off != null && !Array.isArray(entry.off))) {
164
+ throw new Error(`project "${root}" must be { off: [connector id…] }`);
165
+ }
166
+ const off = uniqueIds(entry.off);
167
+ return clean(root) && off.length ? [{ root: clean(root), off }] : [];
168
+ });
169
+ });
170
+ }
171
+
172
+ export function projectConnectorPolicies(dataDir = resolvePluginData()) {
173
+ return cachedRead(join(dataDir, PROJECT_CONNECTORS_FILE), readProjectConnectorsFile);
174
+ }
175
+
176
+ /** 'auto' | 'needs_approval' | 'disabled' for an MCP tool (definition or name)
177
+ * under an agent's policy. Non-MCP tools and Mixdog's own self server are
178
+ * not connectors: always 'auto'. */
179
+ export function connectorToolPermission(policy, toolOrName) {
180
+ const mcp = parseMcpToolName(toolOrName);
181
+ if (!mcp || isSelfMcpToolName(toolOrName)) return 'auto';
182
+ if (policy && !connectorEnabled(policy, mcp.server)) return 'disabled';
183
+ // An explicit per-tool entry decides; otherwise a catalog connector's
184
+ // high-risk tools ask (connectorToolDefault) and any other tool is auto.
185
+ return policy?.tools?.[mcp.server]?.[mcp.tool] || connectorToolDefault(serverConnector(mcp.server), mcp.tool);
186
+ }
187
+
188
+ /** The permission `agentId` has for the MCP tool `toolOrName`. */
189
+ export function agentMcpToolPermission(agentId, toolOrName) {
190
+ if (!parseMcpToolName(toolOrName)) return 'auto';
191
+ return connectorToolPermission(agentConnectors(agentId), toolOrName);
192
+ }
193
+
194
+ /** Where a session runs: its registered Project (a worktree Lead's too), and
195
+ * its cwd (a delegated worker inside the project). */
196
+ function sessionProjectPaths(session) {
197
+ return [session?.desktopSession?.projectPath, session?.workspace?.projectPath, session?.cwd]
198
+ .map(clean)
199
+ .filter(Boolean);
200
+ }
201
+
202
+ /** True when the project `session` runs in switched the tool's connector off
203
+ * (or its policy file cannot be read). */
204
+ export function projectMcpToolDisabled(session, toolOrName, dataDir = resolvePluginData()) {
205
+ const mcp = parseMcpToolName(toolOrName);
206
+ if (!mcp || isSelfMcpToolName(toolOrName)) return false;
207
+ const paths = sessionProjectPaths(session);
208
+ if (!paths.length) return false;
209
+ const policies = projectConnectorPolicies(dataDir);
210
+ if (!policies) return false;
211
+ if (policies === DENY_ALL_CONNECTORS) return true;
212
+ return policies.some(
213
+ ({ root, off }) => off.includes(mcp.server) && paths.some((path) => cwdWithinProjects(path, [root]))
214
+ );
215
+ }