mixdog 1.2.6 → 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 (246) 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/isolated-test-env.mjs +16 -0
  7. package/src/agents/reviewer/AGENT.md +4 -2
  8. package/src/agents/reviewer/agent.json +1 -1
  9. package/src/defaults/shipped-history.json +7 -0
  10. package/src/defaults/skills/browser-use/SKILL.md +5 -0
  11. package/src/defaults/skills/memory-management/SKILL.md +4 -1
  12. package/src/defaults/skills/setup/references/actions.md +11 -4
  13. package/src/defaults/skills/setup-guide/SKILL.md +175 -0
  14. package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
  15. package/src/lib/rules-builder.cjs +55 -6
  16. package/src/rules/agent/AGENT.md +4 -0
  17. package/src/rules/agent-mode/AGENT_MODE.md +24 -0
  18. package/src/rules/agent-mode/MIXY.md +21 -0
  19. package/src/rules/agent-mode/ROUTINE.md +6 -0
  20. package/src/rules/lead/LEAD.md +7 -3
  21. package/src/rules/shared/70-delivery.md +3 -0
  22. package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
  23. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
  24. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +182 -13
  25. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +4 -2
  26. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +215 -0
  27. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -4
  28. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
  29. package/src/runtime/agent/orchestrator/mcp/client.mjs +115 -11
  30. package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
  31. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
  32. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
  33. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
  34. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
  35. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
  36. package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
  37. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  38. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +1 -0
  39. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +10 -3
  40. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
  41. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  42. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
  43. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
  44. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +96 -1
  45. package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
  46. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
  47. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +12 -0
  48. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
  49. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
  50. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
  51. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -4
  52. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +4 -1
  53. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +50 -20
  54. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
  55. package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
  56. package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
  57. package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
  58. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
  59. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
  60. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +162 -0
  61. package/src/runtime/agent/orchestrator/session/agent-room.mjs +641 -0
  62. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
  63. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
  64. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +165 -0
  66. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
  67. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
  68. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
  69. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
  70. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
  71. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
  72. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +16 -1
  73. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +74 -15
  74. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +9 -1
  75. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
  76. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
  77. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +7 -0
  78. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
  79. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -1
  80. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  81. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
  82. package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
  83. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
  84. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
  85. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
  86. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -5
  87. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +55 -8
  88. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
  89. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
  90. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
  91. package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
  92. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +24 -0
  93. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
  94. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +70 -0
  95. package/src/runtime/agent/orchestrator/session/routine-result.mjs +277 -0
  96. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
  97. package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +28 -9
  98. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
  99. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
  100. package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
  101. package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
  102. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +44 -1
  103. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
  104. package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
  105. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +4 -0
  106. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +25 -1
  107. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +8 -0
  108. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +6 -0
  109. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -0
  110. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +75 -57
  111. package/src/runtime/browser-bridge/client.mjs +24 -0
  112. package/src/runtime/channels/lib/scheduler.mjs +40 -12
  113. package/src/runtime/channels/lib/schedules-db.mjs +71 -12
  114. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
  115. package/src/runtime/channels/lib/webhook.mjs +0 -1
  116. package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
  117. package/src/runtime/channels/lib/worker-main.mjs +17 -20
  118. package/src/runtime/computer-bridge/client.mjs +28 -1
  119. package/src/runtime/connectors/gmail-app-password.mjs +690 -0
  120. package/src/runtime/connectors/google-mcp.mjs +446 -0
  121. package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
  122. package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
  123. package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
  124. package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
  125. package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
  126. package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
  127. package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
  128. package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
  129. package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
  130. package/src/runtime/memory/lib/memory.mjs +7 -1
  131. package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
  132. package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
  133. package/src/runtime/memory/lib/tool-call-handler.mjs +2 -0
  134. package/src/runtime/memory/tool-defs.mjs +5 -0
  135. package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
  136. package/src/runtime/shared/agent-avatar.d.mts +64 -0
  137. package/src/runtime/shared/agent-avatar.mjs +320 -0
  138. package/src/runtime/shared/agent-route-config.d.mts +3 -0
  139. package/src/runtime/shared/agent-route-config.mjs +16 -0
  140. package/src/runtime/shared/atomic-file.mjs +14 -1
  141. package/src/runtime/shared/config.mjs +8 -1
  142. package/src/runtime/shared/connector-accounts.mjs +15 -0
  143. package/src/runtime/shared/connector-catalog.d.mts +52 -0
  144. package/src/runtime/shared/connector-catalog.mjs +230 -0
  145. package/src/runtime/shared/connector-triggers.d.mts +3 -0
  146. package/src/runtime/shared/connector-triggers.mjs +43 -0
  147. package/src/runtime/shared/google-oauth-client.mjs +24 -0
  148. package/src/runtime/shared/held-request-host.d.mts +12 -0
  149. package/src/runtime/shared/held-request-host.mjs +71 -0
  150. package/src/runtime/shared/plain-preview.d.mts +1 -0
  151. package/src/runtime/shared/plain-preview.mjs +28 -0
  152. package/src/runtime/shared/routine-limits.d.mts +11 -0
  153. package/src/runtime/shared/routine-limits.mjs +21 -0
  154. package/src/runtime/shared/routine-trigger.d.mts +10 -0
  155. package/src/runtime/shared/routine-trigger.mjs +44 -0
  156. package/src/runtime/shared/schedule-model-ref.mjs +9 -10
  157. package/src/runtime/shared/slow-span.mjs +4 -12
  158. package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
  159. package/src/runtime/shared/transcript-metadata.mjs +10 -0
  160. package/src/runtime/shared/turn-changes.mjs +0 -8
  161. package/src/runtime/shared/usage-readout-totals.mjs +56 -0
  162. package/src/runtime/shared/user-data-guard.mjs +114 -36
  163. package/src/session-runtime/agent-home-delivery.mjs +459 -0
  164. package/src/session-runtime/agent-profile-changes.mjs +21 -0
  165. package/src/session-runtime/agent-room-delivery.mjs +92 -0
  166. package/src/session-runtime/agent-task-sessions.mjs +200 -0
  167. package/src/session-runtime/boot/apis.mjs +50 -18
  168. package/src/session-runtime/boot/facade.mjs +5 -8
  169. package/src/session-runtime/boot/infrastructure.mjs +28 -17
  170. package/src/session-runtime/boot/tools.mjs +3 -0
  171. package/src/session-runtime/channel-config-api.mjs +53 -5
  172. package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
  173. package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
  174. package/src/session-runtime/held-requests.mjs +228 -0
  175. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
  176. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
  177. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
  178. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +31 -2
  179. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  180. package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
  181. package/src/session-runtime/lifecycle/session-switch/resume.mjs +4 -0
  182. package/src/session-runtime/lifecycle/shared.mjs +6 -0
  183. package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
  184. package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
  185. package/src/session-runtime/mcp-oauth-login.mjs +112 -15
  186. package/src/session-runtime/model-route/set-route.mjs +14 -3
  187. package/src/session-runtime/owned-automation-run.mjs +229 -0
  188. package/src/session-runtime/resource-api.mjs +5 -0
  189. package/src/session-runtime/resource-mcp-api.mjs +107 -13
  190. package/src/session-runtime/resource-skills-api.mjs +12 -0
  191. package/src/session-runtime/room-member-gate.mjs +48 -0
  192. package/src/session-runtime/routine-home-turn.mjs +156 -0
  193. package/src/session-runtime/routine-owner.mjs +48 -0
  194. package/src/session-runtime/schedule-session-run.mjs +30 -64
  195. package/src/session-runtime/services/agent-tool/helpers.mjs +10 -0
  196. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
  197. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
  198. package/src/session-runtime/services/channel-admin.mjs +93 -24
  199. package/src/session-runtime/services/memory-access.mjs +37 -0
  200. package/src/session-runtime/services/provider-admin.mjs +74 -39
  201. package/src/session-runtime/services/schedule-access.mjs +91 -0
  202. package/src/session-runtime/session-create/session-options.mjs +34 -7
  203. package/src/session-runtime/session-hooks.mjs +16 -8
  204. package/src/session-runtime/setup-tool/executor.mjs +68 -6
  205. package/src/session-runtime/setup-tool/extended-actions.mjs +72 -14
  206. package/src/session-runtime/setup-tool/settings-contract.mjs +8 -6
  207. package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
  208. package/src/session-runtime/skills-api.mjs +16 -1
  209. package/src/session-runtime/tool-policy-refresh.mjs +238 -29
  210. package/src/session-runtime/turn/session-ops.mjs +8 -1
  211. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +10 -2
  212. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +3 -0
  213. package/src/session-runtime/webhook-session-run.mjs +49 -67
  214. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
  215. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +556 -22
  216. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
  217. package/src/session-runtime/workflow-agents-api.mjs +4 -1
  218. package/src/standalone/daemon-agent-control.mjs +1 -8
  219. package/src/standalone/daemon-session-control.mjs +11 -2
  220. package/src/standalone/daemon.mjs +18 -4
  221. package/src/standalone/session-protocol.mjs +27 -0
  222. package/src/standalone/session-service/session-calls/session-turns.mjs +9 -0
  223. package/src/standalone/session-service.mjs +19 -0
  224. package/src/tui/app/slash-commands.mjs +20 -0
  225. package/src/tui/dist/index.mjs +164 -86
  226. package/src/tui/session/context-state.mjs +6 -1
  227. package/src/tui/session/notice-surface.mjs +35 -4
  228. package/src/tui/session/queue-helpers.mjs +2 -1
  229. package/src/tui/session/session-api/extensions.mjs +4 -0
  230. package/src/tui/session/session-api/intake/submission.mjs +5 -0
  231. package/src/tui/session/session-api/integrations.mjs +8 -0
  232. package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
  233. package/src/tui/session/session-api/lifecycle.mjs +17 -1
  234. package/src/tui/session/session-api/routes.mjs +48 -3
  235. package/src/tui/session/session-flow/drain.mjs +12 -3
  236. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
  237. package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
  238. package/src/tui/session/session-flow/steering.mjs +58 -24
  239. package/src/tui/session/tool-approval.mjs +26 -5
  240. package/src/tui/session/transcript-intake.mjs +6 -2
  241. package/src/tui/session/transcript-spill.mjs +5 -1
  242. package/src/tui/session/tui-steering-persist.mjs +65 -42
  243. package/src/tui/session/turn-live-call.mjs +56 -0
  244. package/src/tui/session/turn.mjs +22 -6
  245. package/src/session-runtime/automation-agents.mjs +0 -94
  246. package/src/session-runtime/automation-workflow.mjs +0 -59
@@ -46,6 +46,7 @@ export function sessionTokenCounters(session) {
46
46
  totalOutputTokens: Number(session?.totalOutputTokens || 0),
47
47
  totalCachedReadTokens: Number(session?.totalCachedReadTokens || 0),
48
48
  totalCacheWriteTokens: Number(session?.totalCacheWriteTokens || 0),
49
+ usageReadout: session?.usageReadout || null,
49
50
  compactBoundaryTokens: Number(session?.compactBoundaryTokens || 0),
50
51
  };
51
52
  }
@@ -64,6 +65,9 @@ function sessionUsageCounters(session, lastContextTokens) {
64
65
  totalOutputTokens: Number(session?.totalOutputTokens || 0),
65
66
  totalCachedReadTokens: Number(session?.totalCachedReadTokens || 0),
66
67
  totalCacheWriteTokens: Number(session?.totalCacheWriteTokens || 0),
68
+ // Session-cumulative cache/speed totals behind the composer readout; null
69
+ // until the session has a call recorded.
70
+ usageReadout: session?.usageReadout || null,
67
71
  };
68
72
  }
69
73
 
@@ -48,12 +48,14 @@ export function filterMcpToolsForCwd(tools, scopes, cwd) {
48
48
  });
49
49
  }
50
50
 
51
- /** The MCP tools a session at `cwd` may see. No scopes configured → input
52
- * returned as-is, so the global-only fast path costs one config read. */
51
+ /** The MCP tools a session at `cwd` may see. No scopes configured → the input
52
+ * as-is, so the global-only fast path costs one config read. An agent's
53
+ * connectors never narrow this list: the schema and the BP2 manifest stay
54
+ * identical across agents (one shared cache prefix), and the connector policy
55
+ * is enforced at dispatch (pre-dispatch-deny / connector approval). */
53
56
  export function filterMcpToolsForSession(tools, cwd, config = null) {
54
57
  const list = Array.isArray(tools) ? tools : [];
55
58
  if (!list.length) return list;
56
59
  const scopes = extensionScopesFromConfig(config || loadConfig({ secrets: false }));
57
- if (!hasExtensionScopes(scopes)) return list;
58
- return filterMcpToolsForCwd(list, scopes, cwd);
60
+ return hasExtensionScopes(scopes) ? filterMcpToolsForCwd(list, scopes, cwd) : list;
59
61
  }
@@ -19,6 +19,18 @@ Lead executes all work directly and never delegates on its own judgment.
19
19
  Only when the user explicitly asks for delegation, load the deferred \`agent\`
20
20
  tool and brief each agent as the Lead rules describe.`;
21
21
 
22
+ /** Agent mode's fixed delegation block, in place of the orchestration mode. */
23
+ export const AGENT_MODE_DELEGATION = `# Delegation
24
+
25
+ Handle conversation yourself. Delegate specialised work to sub-agents. Hand
26
+ substantial coding to a new coding-mode task session (\`session create\`) with
27
+ a self-contained brief: start it when already requested, otherwise suggest it. Then relay the
28
+ result in your own words.`;
29
+
30
+ /** Mixy only: it also routes requests to the user's contact agents. */
31
+ export const MIXY_CONTACTS_INTRO = `You also coordinate the user's contact agents: route a request to the
32
+ contact best suited for it with the same kind of brief.`;
33
+
22
34
  export function orchestrationInstructions(value) {
23
35
  const mode = normalizeOrchestrationMode(value);
24
36
  if (mode === 'none') return SOLO;
@@ -23,6 +23,7 @@ const MCP_TRANSPORT_FIELDS = new Set([
23
23
  'env_http_headers',
24
24
  'env_vars',
25
25
  'autoDetect',
26
+ 'oauthClientId',
26
27
  ]);
27
28
 
28
29
  // Every spelling resolveMcpStartupTimeoutMs / resolveMcpCallTimeoutMs reads.
@@ -14,6 +14,7 @@ import {
14
14
  deferredCatalogUnion,
15
15
  filterSessionToolPolicy,
16
16
  isReadonlySelectable,
17
+ mcpServerSelection,
17
18
  toolSearchMatches,
18
19
  } from './tool-catalog.mjs';
19
20
  import { parseToolSelection, sortedCatalogByMeasuredUsage } from './tool-catalog-schema.mjs';
@@ -249,8 +250,9 @@ function describeNames(raw) {
249
250
  return names;
250
251
  }
251
252
 
252
- // Requested names → available tools; an alias that names no tool expands to
253
- // its members (existing load_tool alias compatibility).
253
+ // Requested names → available tools; an alias or `mcp__<server>` that names no
254
+ // tool expands to its members (existing load_tool alias compatibility).
255
+ // Definitions past the continuation target cap are listed as omitted.
254
256
  function resolveDescribeTargets(session, names, mode, available) {
255
257
  const eagerNames = eagerToolNames(session);
256
258
  const targets = [];
@@ -271,13 +273,15 @@ function resolveDescribeTargets(session, names, mode, available) {
271
273
  add(tool);
272
274
  continue;
273
275
  }
274
- const members = (DEFERRED_SELECT_ALIASES[requested.toLowerCase()] || [])
276
+ const aliased = (DEFERRED_SELECT_ALIASES[requested.toLowerCase()] || [])
275
277
  .map((member) => lookupByName(available, member))
276
278
  .filter(Boolean);
279
+ const members = aliased.length ? aliased : mcpServerSelection(available, requested);
277
280
  if (members.length) members.forEach(add);
278
281
  else missing.push(requested);
279
282
  }
280
- return { targets, missing, blocked };
283
+ const omitted = targets.splice(BRIDGE_LIMITS.continuationMaxTargets).map((tool) => clean(tool?.name));
284
+ return { targets, missing, blocked, omitted };
281
285
  }
282
286
 
283
287
  const SEARCH_MAX_MATCHES = 20;
@@ -367,6 +371,7 @@ export function describeBridgeTools(session, args = {}, { mode } = {}) {
367
371
  let missing = [];
368
372
  let blocked = [];
369
373
  let matches = [];
374
+ let omitted = [];
370
375
  if (continuation) {
371
376
  targets = continuationTargets(session, continuation.indexes, available, mode);
372
377
  if (!targets) return catalogChanged();
@@ -378,10 +383,11 @@ export function describeBridgeTools(session, args = {}, { mode } = {}) {
378
383
  `names must be 1-${BRIDGE_LIMITS.describeMaxNames} exact tool names of at most ${BRIDGE_LIMITS.nameMaxChars} characters.${syntaxHint}`
379
384
  );
380
385
  }
381
- ({ targets, missing, blocked } = resolveDescribeTargets(session, names, mode, available));
386
+ ({ targets, missing, blocked, omitted } = resolveDescribeTargets(session, names, mode, available));
382
387
  ({ matches, missing } = searchKeywords(session, missing, mode, available));
383
388
  }
384
- const found = matches.length ? { matches } : {};
389
+ // Omitted names are described by a later request naming them.
390
+ const found = { ...(matches.length ? { matches } : {}), ...(omitted.length ? { omitted } : {}) };
385
391
  const docs = targets.map((tool) => {
386
392
  const document = toolDocument(tool);
387
393
  return {
@@ -4,6 +4,8 @@
4
4
  import { clean } from './session-text.mjs';
5
5
  import { mergePendingDeferredToolDelta } from './deferred-tool-delta.mjs';
6
6
  import { applyInitialDeferredToolManifestToBp2 } from '../context/collect.mjs';
7
+ import { listedDeferredToolNames } from '../context/deferred-tools.mjs';
8
+ import { parseMcpToolName } from '../../../shared/tool-primitives.mjs';
7
9
  import { getMcpServerInstructionsMap, getMcpTools, getMcpToolGeneration } from '../mcp/client.mjs';
8
10
  import { filterMcpToolsForSession } from './extension-scopes.mjs';
9
11
  import { isDeferredToolAvailable, isToolPermittedBySessionPolicy } from './deferred-tool-availability.mjs';
@@ -259,6 +261,17 @@ function expandSelectionNames(names) {
259
261
  return [...new Set(out)];
260
262
  }
261
263
 
264
+ /**
265
+ * The tools of `tools` that `mcp__<server>` stands for (the deferred manifest
266
+ * lists MCP servers, not their tools); [] for any other name. Callers try an
267
+ * exact tool name first.
268
+ */
269
+ export function mcpServerSelection(tools, requested) {
270
+ const server = /^mcp__(.+)$/i.exec(clean(requested))?.[1]?.toLowerCase();
271
+ if (!server) return [];
272
+ return (tools || []).filter((tool) => String(parseMcpToolName(tool)?.server || '').toLowerCase() === server);
273
+ }
274
+
262
275
  function storedDeferredToolNames(session) {
263
276
  for (const source of [session?.deferredDiscoveredTools, session?.deferredSelectedTools]) {
264
277
  const names = parseToolSelection(source);
@@ -430,8 +443,11 @@ export function applyDeferredToolSurface(session, mode, extraTools = [], options
430
443
  // manifest, or the bridge roster + guidance. History stays as is.
431
444
  session.mcpServerInstructions = getMcpServerInstructionsMap(session.mcpScopeId);
432
445
  applyInitialDeferredToolManifestToBp2(session, deferredPoolToolNames(session), { rebuild: true });
433
- const rendered = renderedDeferredManifest(session);
434
- session.deferredAnnouncedTools = deferredPoolToolNames(session).filter((name) => rendered.includes(name));
446
+ session.deferredAnnouncedTools = listedDeferredToolNames(
447
+ session,
448
+ deferredPoolToolNames(session),
449
+ renderedDeferredManifest(session)
450
+ );
435
451
  }
436
452
  if (!session.deferredToolBp2Applied && session.messages?.some((m) => m?.role === 'system')) {
437
453
  if (!session.mcpServerInstructions || typeof session.mcpServerInstructions !== 'object') {
@@ -519,8 +535,11 @@ export function refreshInitialDeferredMcpSurface(session, liveMcpTools) {
519
535
  // Pre-mark ONLY the names that ACTUALLY landed in the rebuilt BP2 manifest as
520
536
  // announced; anything the manifest could not advertise stays un-announced so
521
537
  // the turn-boundary late reminder can still surface it.
522
- const rendered = renderedDeferredManifest(session);
523
- session.deferredAnnouncedTools = deferredPoolToolNames(session).filter((name) => rendered.includes(name));
538
+ session.deferredAnnouncedTools = listedDeferredToolNames(
539
+ session,
540
+ deferredPoolToolNames(session),
541
+ renderedDeferredManifest(session)
542
+ );
524
543
  session.updatedAt = Date.now();
525
544
  return true;
526
545
  }
@@ -726,7 +745,15 @@ export function selectDeferredTools(session, names, mode, { exact = false } = {}
726
745
  const already = [];
727
746
  const blocked = [];
728
747
  const missing = [];
729
- for (const rawName of exact ? [...new Set(names)] : expandSelectionNames(names)) {
748
+ const requested = exact
749
+ ? names
750
+ : expandSelectionNames(names).flatMap((raw) => {
751
+ const key = clean(raw);
752
+ if (byName.has(key) || byName.has(key.toLowerCase())) return [key];
753
+ const members = mcpServerSelection(catalog, key).map((tool) => clean(tool?.name));
754
+ return members.length ? members : [key];
755
+ });
756
+ for (const rawName of new Set(requested)) {
730
757
  const requestedName = clean(rawName);
731
758
  const tool = byName.get(requestedName) || byName.get(requestedName.toLowerCase());
732
759
  const name = clean(tool?.name);
@@ -17,7 +17,8 @@ export const TOOL_SEARCH_TOOL = {
17
17
  openWorldHint: false,
18
18
  agentHidden: true,
19
19
  },
20
- description: 'Load full schemas for missing deferred tool names/aliases; batch needed names in one call.',
20
+ description:
21
+ 'Load full schemas for missing deferred tool names/aliases; a connector name loads all its tools; batch needed names in one call.',
21
22
  inputSchema: {
22
23
  type: 'object',
23
24
  properties: {
@@ -72,7 +73,7 @@ export const SESSION_TOOL = {
72
73
  openWorldHint: false,
73
74
  agentHidden: true,
74
75
  },
75
- trigger: 'Session lookup/control, title, compact, fork, Project and worktrees.',
76
+ trigger: 'Session lookup/control, coding task sessions, title, compact, fork, Project and worktrees.',
76
77
  description:
77
78
  'Inspect sessions or control another by exact ID, never a guessed one. send acknowledges queue intake, not completion. Cancel/delete and worktree actions require the user’s request. Other actions affect only the current session.',
78
79
  inputSchema: {
@@ -87,6 +88,7 @@ export const SESSION_TOOL = {
87
88
  'send',
88
89
  'cancel',
89
90
  'delete',
91
+ 'create',
90
92
  'rename',
91
93
  'compact',
92
94
  'fork',
@@ -100,9 +102,9 @@ export const SESSION_TOOL = {
100
102
  'prune-worktrees',
101
103
  ],
102
104
  description:
103
- 'status defaults to current; list pages sessions; read returns latest items; send queues prompt; cancel stops the turn; delete removes the session. compact runs after this turn; fork copies it without switching. merge-worktree merges into the Project’s checked-out branch; remove-worktree returns to the Project (repeat on WORKTREE_REMOVAL_INCOMPLETE); list-worktrees includes retaining sessions; prune-worktrees removes only clean, merged, unretained worktrees.',
105
+ 'status defaults to current; list pages sessions; read returns latest items; send queues prompt; cancel stops the turn; delete removes the session. create (agent conversations) starts a visible coding task session from brief and reports its turns back; unknown Project: list-projects first, still ambiguous: ask the user. compact runs after this turn; fork copies it without switching. merge-worktree merges into the Project’s checked-out branch; remove-worktree returns to the Project (repeat on WORKTREE_REMOVAL_INCOMPLETE); list-worktrees includes retaining sessions; prune-worktrees removes only clean, merged, unretained worktrees.',
104
106
  },
105
- title: { type: 'string', description: 'rename: new current-session title.' },
107
+ title: { type: 'string', description: 'rename: new current-session title; create: task title.' },
106
108
  session_id: {
107
109
  type: 'string',
108
110
  description:
@@ -143,6 +145,10 @@ export const SESSION_TOOL = {
143
145
  description: 'remove-worktree: allow uncommitted/unmerged work only when explicitly requested.',
144
146
  },
145
147
  value: { type: 'boolean', description: 'favorite/archive: on or off.' },
148
+ brief: { type: 'string', description: 'create: self-contained instruction, the first message.' },
149
+ project: { type: 'string', description: 'create: registered Project name or existing directory.' },
150
+ model: { type: 'string', description: 'create: provider/model or preset; default route otherwise.' },
151
+ notify: { type: 'boolean', description: 'create: report results back, default true.' },
146
152
  },
147
153
  additionalProperties: false,
148
154
  },
@@ -29,7 +29,8 @@ function* scanCustomAgentIds(userRoot, shippedRoot) {
29
29
  for (const entry of entries) {
30
30
  if (!entry.isDirectory()) continue;
31
31
  const id = normalizeWorkflowId(entry.name);
32
- if (!id || AGENT_ROLE_IDS.has(id) || isHiddenAgent(id)) continue;
32
+ // `lead` is Mixy's own folder (PERSONA.md, AGENT.md), never an agent.
33
+ if (!id || id === 'lead' || AGENT_ROLE_IDS.has(id) || isHiddenAgent(id)) continue;
33
34
  if (root !== userRoot && (yield { op: 'exists', path: join(userRoot, id, AGENT_DELETED_MARKER) })) continue;
34
35
  if (!(yield { op: 'exists', path: join(root, entry.name, 'AGENT.md') })) continue;
35
36
  ids.add(id);
@@ -101,6 +102,8 @@ export function createWorkflowAgents({ rootDir, dataDir, readMarkdownDocument, n
101
102
  permission: normalizeAgentPermissionOrNone(doc.frontmatter.permission),
102
103
  frontmatter: doc.frontmatter,
103
104
  body,
105
+ // Optional PERSONA.md beside AGENT.md (same dir, same cache entry).
106
+ persona: (readTextSafe(join(d, 'PERSONA.md')) || '').trim(),
104
107
  };
105
108
  setAgentDefinitionCache(cacheKey, definition);
106
109
  return definition;
@@ -2,8 +2,8 @@
2
2
  // (active pack + orchestration instructions + delegatable agent catalog).
3
3
  import { clean } from '../session-text.mjs';
4
4
  import { configuredOrchestrationMode } from '../../../../shared/orchestration.mjs';
5
- import { orchestrationInstructions } from '../orchestration.mjs';
6
- import { DEFAULT_WORKFLOW_ID, normalizeWorkflowId } from '../workflow-ids.mjs';
5
+ import { AGENT_MODE_DELEGATION, MIXY_CONTACTS_INTRO, orchestrationInstructions } from '../orchestration.mjs';
6
+ import { DEFAULT_WORKFLOW_ID, isContactAgentId, normalizeWorkflowId } from '../workflow-ids.mjs';
7
7
 
8
8
  export function createWorkflowContext({ packs, agents }) {
9
9
  function workflowSummary(pack, { hasAgents = true } = {}) {
@@ -43,26 +43,53 @@ export function createWorkflowContext({ packs, agents }) {
43
43
  return lines.join('\n\n');
44
44
  }
45
45
 
46
- function orchestrationContextBlock(config, dir) {
46
+ // Name + description only: the AGENT.md body is the worker's own system
47
+ // prompt and rides in the worker session at spawn time — repeating it in
48
+ // the Lead prompt only bloats context. Lead picks agents by description
49
+ // (a when-to-use signal); orchestration carries the delegation rules.
50
+ function agentCatalog(dir, ids) {
51
+ return ids
52
+ .map((id) => agents.loadAgentDefinition(dir, id))
53
+ .filter(Boolean)
54
+ .map((agent) => `- ${agent.name} (${agent.id})${agent.description ? `: ${agent.description}` : ''}`)
55
+ .join('\n');
56
+ }
57
+
58
+ // A Lead's workflow slices for BP3 (composeSystemPrompt orders them):
59
+ // - coding: the orchestration mode block and the full agent catalog;
60
+ // - agent mode: the fixed delegation block (no per-agent setting) and the
61
+ // sub-agent catalog — identical for every agent, so their prompts share
62
+ // it — plus, for Mixy only, the contact-agent catalog.
63
+ function leadPromptParts(config, dir, { agentMode = false, mixy = false } = {}) {
47
64
  const mode = configuredOrchestrationMode(config);
48
- const agentIds = agents.delegatableAgentIds(config, dir);
49
- // Solo without agents has nothing to delegate to on request either.
50
- if (mode === 'none' && !agentIds.length) return '';
51
- const lines = [orchestrationInstructions(mode)];
52
- const agentBlocks = agentIds.map((id) => agents.loadAgentDefinition(dir, id)).filter(Boolean);
53
- if (agentBlocks.length) {
54
- lines.push('# Available Agents');
55
- // Name + description only: the AGENT.md body is the worker's own system
56
- // prompt and rides in the worker session at spawn time — repeating it in
57
- // the Lead prompt only bloats context. Lead picks agents by description
58
- // (a when-to-use signal); orchestration carries the delegation rules.
59
- lines.push(
60
- agentBlocks
61
- .map((agent) => `- ${agent.name} (${agent.id})${agent.description ? `: ${agent.description}` : ''}`)
62
- .join('\n')
63
- );
65
+ const ids = agents.delegatableAgentIds(config, dir);
66
+ if (!agentMode) {
67
+ const catalog = agentCatalog(dir, ids);
68
+ return {
69
+ // Solo without agents has nothing to delegate to on request either.
70
+ orchestrationContext: mode === 'none' && !ids.length ? '' : orchestrationInstructions(mode),
71
+ agentCatalogContext: catalog ? `# Available Agents\n\n${catalog}` : '',
72
+ contactCatalogContext: '',
73
+ };
64
74
  }
65
- return lines.join('\n\n');
75
+ const isContact = (id) => isContactAgentId(id, agents.loadAgentDefinition(dir, id)?.frontmatter?.kind);
76
+ const subAgents = agentCatalog(
77
+ dir,
78
+ ids.filter((id) => !isContact(id))
79
+ );
80
+ const contacts = mixy ? agentCatalog(dir, ids.filter(isContact)) : '';
81
+ return {
82
+ // An agent-mode Lead without agents has no one to delegate to at all.
83
+ orchestrationContext: subAgents || contacts ? AGENT_MODE_DELEGATION : '',
84
+ agentCatalogContext: subAgents ? `# Available Agents\n\n${subAgents}` : '',
85
+ contactCatalogContext: contacts ? `# Contact Agents\n\n${MIXY_CONTACTS_INTRO}\n\n${contacts}` : '',
86
+ };
87
+ }
88
+
89
+ // The coding Lead's combined block (orchestration + catalog), as before.
90
+ function orchestrationContextBlock(config, dir) {
91
+ const { orchestrationContext, agentCatalogContext } = leadPromptParts(config, dir);
92
+ return [orchestrationContext, agentCatalogContext].filter(Boolean).join('\n\n');
66
93
  }
67
94
 
68
95
  // Single-pass variant: loads the active WORKFLOW.md pack once and derives both
@@ -81,6 +108,9 @@ export function createWorkflowContext({ packs, agents }) {
81
108
  // orchestration instructions / agent catalog.
82
109
  packContext,
83
110
  context: [packContext, orchestrationContextBlock(config, dir)].filter(Boolean).join('\n\n'),
111
+ // A Lead's BP3 slices beside the pack: `{ agentMode, mixy }` picks the
112
+ // coding, agent or Mixy variant (session/agent-mode.mjs).
113
+ leadPromptParts: (options) => leadPromptParts(config, dir, options),
84
114
  };
85
115
  }
86
116
 
@@ -15,6 +15,8 @@ export const BUILTIN_SLOT_AGENT_IDS = new Set(
15
15
  FIXED_AGENT_SLOTS.filter((agent) => agent.workflowSlot).map((agent) => agent.id)
16
16
  );
17
17
  export const STARTER_AGENT_ORDER = new Map(DEFAULT_DISABLED_AGENT_IDS.map((id, index) => [id, index]));
18
+ // Only Mixy delegates to contacts (agent-route-config.mjs isContactAgentId).
19
+ export { isContactAgentId } from '../../../shared/agent-route-config.mjs';
18
20
  export const DEFAULT_WORKFLOW_ID = 'default';
19
21
 
20
22
  // Loaded AGENT.md definitions, keyed `${dir}\n${agentId}`.
@@ -0,0 +1,4 @@
1
+ export const MIXY_AGENT_ID: 'lead';
2
+ export function agentHomeSessionId(agentId: unknown): string;
3
+ export function agentIdOfHomeSession(sessionId: unknown): string;
4
+ export function isAgentHomeSessionId(sessionId: unknown): boolean;
@@ -0,0 +1,33 @@
1
+ // session/agent-home.mjs
2
+ // An agent's home thread: the ONE user conversation each agent contact owns.
3
+ // Its session id is a fixed key derived from the agent id, never a stored
4
+ // pointer, so every surface (PC, phone, a restarted host) resolves the same
5
+ // session, and two concurrent first opens can only ever name the same id.
6
+
7
+ /** The primary assistant's contact: the Lead configuration itself. */
8
+ export const MIXY_AGENT_ID = 'lead';
9
+
10
+ const HOME_PREFIX = 'sess_home_';
11
+ // A normalized agent id (workflow-ids normalizeWorkflowId): underscores are
12
+ // already folded to dashes, so mapping '.' to '_' stays reversible.
13
+ const AGENT_ID = /^[a-z0-9][a-z0-9.-]*$/;
14
+ const MAX_AGENT_ID_LENGTH = 200;
15
+
16
+ /** The home session id of `agentId`, or '' when it is not a normalized id. */
17
+ export function agentHomeSessionId(agentId) {
18
+ const id = typeof agentId === 'string' ? agentId : '';
19
+ if (id.length > MAX_AGENT_ID_LENGTH || !AGENT_ID.test(id)) return '';
20
+ return `${HOME_PREFIX}${id.replaceAll('.', '_')}`;
21
+ }
22
+
23
+ /** The agent id a home session belongs to, or '' for any other session. */
24
+ export function agentIdOfHomeSession(sessionId) {
25
+ const value = typeof sessionId === 'string' ? sessionId : '';
26
+ if (!value.startsWith(HOME_PREFIX)) return '';
27
+ const id = value.slice(HOME_PREFIX.length).replaceAll('_', '.');
28
+ return agentHomeSessionId(id) === value ? id : '';
29
+ }
30
+
31
+ export function isAgentHomeSessionId(sessionId) {
32
+ return agentIdOfHomeSession(sessionId) !== '';
33
+ }
@@ -0,0 +1,62 @@
1
+ // session/agent-mode.mjs
2
+ // Which mode a Lead session runs in, and the agent it acts as. ONE resolver,
3
+ // used at creation, resume and every refresh:
4
+ // - agent mode: a Lead created as an agent — Mixy's home (`sess_home_lead`),
5
+ // a contact agent's home (`sess_home_<id>`), a group-room member session
6
+ // (`sess_rmem_<room>_<id>`), and an agent's schedule/webhook run (stamped
7
+ // `ownerAgentId`);
8
+ // - coding mode: every other Lead (task sessions, new-task tabs) and every
9
+ // delegated worker. `owner:'agent'` marks a delegated worker, never an
10
+ // agent-mode Lead.
11
+ import { isAgentOwner } from '../agent-owner.mjs';
12
+ import { MIXY_AGENT_ID, agentHomeSessionId, agentIdOfHomeSession } from './agent-home.mjs';
13
+ import { roomMemberOfSession } from './agent-room.mjs';
14
+
15
+ export const AGENT_MODE = 'agent';
16
+ export const CODING_MODE = 'coding';
17
+
18
+ const validAgentId = (value) => {
19
+ const id = typeof value === 'string' ? value.trim() : '';
20
+ return id && agentHomeSessionId(id) ? id : '';
21
+ };
22
+
23
+ /**
24
+ * `{ mode, agentId }` of a session record (or create options), its reserved id
25
+ * and creation profile. `agentId` is the agent the session acts as: '' for a
26
+ * delegated worker, Mixy for a coding Lead.
27
+ */
28
+ export function resolveSessionMode({ session = null, sessionId = '', profile = null } = {}) {
29
+ if (
30
+ isAgentOwner(session) ||
31
+ session?.visibility === 'agent-only' ||
32
+ profile?.owner === 'agent' ||
33
+ profile?.visibility === 'agent-only'
34
+ ) {
35
+ return { mode: CODING_MODE, agentId: '' };
36
+ }
37
+ const id = String(session?.id || sessionId || '');
38
+ const agentId =
39
+ roomMemberOfSession(id)?.agentId ||
40
+ agentIdOfHomeSession(id) ||
41
+ validAgentId(session?.ownerAgentId) ||
42
+ validAgentId(profile?.ownerAgentId) ||
43
+ validAgentId(profile?.homeAgent);
44
+ return agentId ? { mode: AGENT_MODE, agentId } : { mode: CODING_MODE, agentId: MIXY_AGENT_ID };
45
+ }
46
+
47
+ /** The persisted mode of a session record; older records resolve it. */
48
+ export function sessionModeOf(session) {
49
+ const stored = session?.sessionMode;
50
+ if (stored === AGENT_MODE || stored === CODING_MODE) return stored;
51
+ return resolveSessionMode({ session }).mode;
52
+ }
53
+
54
+ /** A schedule or webhook run (a routine): no user is present in it. */
55
+ export function isRoutineSource(sourceType) {
56
+ const kind = String(sourceType || '').toLowerCase();
57
+ return kind === 'schedule' || kind === 'webhook';
58
+ }
59
+
60
+ export function isAgentModeSession(session) {
61
+ return sessionModeOf(session) === AGENT_MODE;
62
+ }
@@ -0,0 +1,31 @@
1
+ import type { RoomRow, RoomScene, RoomTurnResult } from './agent-room.mjs';
2
+
3
+ export interface RoomSupervisorMember {
4
+ id: string;
5
+ name: string;
6
+ /** One line about the member, when it has one. */
7
+ description?: string;
8
+ }
9
+ /** One supervisor step's decision, with its reading of the talk. */
10
+ export type RoomDecision =
11
+ | { action: 'speak'; agentId: string; scene: RoomScene; instruction?: string }
12
+ | { action: 'finish'; scene: RoomScene };
13
+ /** What a supervisor step reads (all of it data, never instructions). */
14
+ export interface RoomSupervisorInput {
15
+ roomName: string;
16
+ members: RoomSupervisorMember[];
17
+ rows: RoomRow[];
18
+ /** This exchange's turns so far, in order. */
19
+ turns: Array<{ id: string; result: RoomTurnResult }>;
20
+ /** Nobody has spoken yet: the step must pick a member. */
21
+ mustPick: boolean;
22
+ /** The member that took the last turn ('' for none). */
23
+ last: string;
24
+ remaining: { messages: number; steps: number };
25
+ }
26
+ export function roomSupervisorRows(rows: unknown): RoomRow[];
27
+ export function roomSupervisorPrompt(input?: Partial<RoomSupervisorInput>): { system: string; user: string };
28
+ export function parseRoomDecision(
29
+ reply: unknown,
30
+ members?: readonly { id: string; name?: string }[]
31
+ ): RoomDecision | null;