macro-agent 0.0.17 → 0.1.1
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.
- package/.claude/settings.local.json +3 -1
- package/.sudocode/specs.jsonl +4 -0
- package/CLAUDE.md +16 -14
- package/README.md +11 -29
- package/dist/acp/macro-agent.d.ts +17 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +183 -55
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/types.d.ts +32 -1
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js.map +1 -1
- package/dist/agent/agent-manager.d.ts +65 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +464 -183
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +1 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/api/server.d.ts +3 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +37 -6
- package/dist/api/server.js.map +1 -1
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/token.d.ts +41 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +73 -0
- package/dist/auth/token.js.map +1 -0
- package/dist/cli/acp.d.ts +2 -23
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +127 -61
- package/dist/cli/acp.js.map +1 -1
- package/dist/cli/index.js +147 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts +6 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +268 -181
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/parse-args.d.ts +20 -0
- package/dist/cli/parse-args.d.ts.map +1 -0
- package/dist/cli/parse-args.js +43 -0
- package/dist/cli/parse-args.js.map +1 -0
- package/dist/cli/stable-instance-id.d.ts +8 -0
- package/dist/cli/stable-instance-id.d.ts.map +1 -0
- package/dist/cli/stable-instance-id.js +14 -0
- package/dist/cli/stable-instance-id.js.map +1 -0
- package/dist/config/project-config.d.ts +74 -7
- package/dist/config/project-config.d.ts.map +1 -1
- package/dist/config/project-config.js +123 -20
- package/dist/config/project-config.js.map +1 -1
- package/dist/map/adapter/acp-over-map.d.ts +23 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +482 -55
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/adapter/connection-manager.d.ts.map +1 -1
- package/dist/map/adapter/connection-manager.js +3 -0
- package/dist/map/adapter/connection-manager.js.map +1 -1
- package/dist/map/adapter/event-log.d.ts +87 -0
- package/dist/map/adapter/event-log.d.ts.map +1 -0
- package/dist/map/adapter/event-log.js +122 -0
- package/dist/map/adapter/event-log.js.map +1 -0
- package/dist/map/adapter/event-translator.js +6 -6
- package/dist/map/adapter/event-translator.js.map +1 -1
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
- package/dist/map/adapter/extensions/index.d.ts +10 -1
- package/dist/map/adapter/extensions/index.d.ts.map +1 -1
- package/dist/map/adapter/extensions/index.js +34 -0
- package/dist/map/adapter/extensions/index.js.map +1 -1
- package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
- package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
- package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
- package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
- package/dist/map/adapter/extensions/rename.d.ts +29 -0
- package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
- package/dist/map/adapter/extensions/rename.js +49 -0
- package/dist/map/adapter/extensions/rename.js.map +1 -0
- package/dist/map/adapter/extensions/task.d.ts.map +1 -1
- package/dist/map/adapter/extensions/task.js +10 -0
- package/dist/map/adapter/extensions/task.js.map +1 -1
- package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
- package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
- package/dist/map/adapter/extensions/update-metadata.js +67 -0
- package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
- package/dist/map/adapter/index.d.ts +2 -1
- package/dist/map/adapter/index.d.ts.map +1 -1
- package/dist/map/adapter/index.js +8 -2
- package/dist/map/adapter/index.js.map +1 -1
- package/dist/map/adapter/interface.d.ts +2 -0
- package/dist/map/adapter/interface.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.d.ts +4 -0
- package/dist/map/adapter/map-adapter.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.js +302 -30
- package/dist/map/adapter/map-adapter.js.map +1 -1
- package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
- package/dist/map/adapter/subscription-manager.js +5 -1
- package/dist/map/adapter/subscription-manager.js.map +1 -1
- package/dist/map/adapter/types.d.ts +2 -0
- package/dist/map/adapter/types.d.ts.map +1 -1
- package/dist/mcp/map-client.d.ts +39 -0
- package/dist/mcp/map-client.d.ts.map +1 -0
- package/dist/mcp/map-client.js +129 -0
- package/dist/mcp/map-client.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +14 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +113 -85
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/types.d.ts +9 -1
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/metrics/metrics.js +1 -1
- package/dist/metrics/metrics.js.map +1 -1
- package/dist/roles/capabilities.d.ts +3 -1
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +17 -7
- package/dist/roles/capabilities.js.map +1 -1
- package/dist/roles/config-loader.d.ts +6 -6
- package/dist/roles/config-loader.d.ts.map +1 -1
- package/dist/roles/config-loader.js +6 -6
- package/dist/roles/config-loader.js.map +1 -1
- package/dist/roles/registry.d.ts +2 -2
- package/dist/roles/registry.js +2 -2
- package/dist/server/combined-server.d.ts +20 -0
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +107 -8
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.d.ts +7 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +91 -8
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +23 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/dist/store/types/events.d.ts +1 -1
- package/dist/store/types/events.d.ts.map +1 -1
- package/dist/task/backend/index.d.ts +47 -29
- package/dist/task/backend/index.d.ts.map +1 -1
- package/dist/task/backend/index.js +109 -71
- package/dist/task/backend/index.js.map +1 -1
- package/dist/task/backend/memory.d.ts +1 -0
- package/dist/task/backend/memory.d.ts.map +1 -1
- package/dist/task/backend/memory.js +3 -0
- package/dist/task/backend/memory.js.map +1 -1
- package/dist/task/backend/opentasks/backend.d.ts +140 -0
- package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
- package/dist/task/backend/opentasks/backend.js +1023 -0
- package/dist/task/backend/opentasks/backend.js.map +1 -0
- package/dist/task/backend/opentasks/client.d.ts +337 -0
- package/dist/task/backend/opentasks/client.d.ts.map +1 -0
- package/dist/task/backend/opentasks/client.js +225 -0
- package/dist/task/backend/opentasks/client.js.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.js +195 -0
- package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
- package/dist/task/backend/opentasks/index.d.ts +21 -0
- package/dist/task/backend/opentasks/index.d.ts.map +1 -0
- package/dist/task/backend/opentasks/index.js +21 -0
- package/dist/task/backend/opentasks/index.js.map +1 -0
- package/dist/task/backend/opentasks/mapping.d.ts +48 -0
- package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
- package/dist/task/backend/opentasks/mapping.js +77 -0
- package/dist/task/backend/opentasks/mapping.js.map +1 -0
- package/dist/task/backend/types.d.ts +33 -53
- package/dist/task/backend/types.d.ts.map +1 -1
- package/dist/task/backend/types.js +7 -11
- package/dist/task/backend/types.js.map +1 -1
- package/dist/task/backend/unified-tool-provider.d.ts +57 -0
- package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
- package/dist/task/backend/unified-tool-provider.js +623 -0
- package/dist/task/backend/unified-tool-provider.js.map +1 -0
- package/dist/teams/team-loader.d.ts +2 -2
- package/dist/teams/team-loader.js +3 -3
- package/dist/teams/team-loader.js.map +1 -1
- package/dist/teams/team-runtime.d.ts.map +1 -1
- package/dist/teams/team-runtime.js +2 -0
- package/dist/teams/team-runtime.js.map +1 -1
- package/docs/architecture.md +7 -6
- package/docs/configuration.md +26 -62
- package/docs/implementation-details.md +5 -5
- package/docs/implementation-summary.md +17 -17
- package/docs/plan-self-driving-support.md +4 -4
- package/docs/spec-self-driving-support.md +10 -10
- package/docs/team-templates.md +2 -2
- package/docs/teams.md +3 -3
- package/docs/troubleshooting.md +10 -11
- package/package.json +6 -4
- package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
- package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
- package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
- package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
- package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
- package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
- package/src/acp/__tests__/history.test.ts +8 -4
- package/src/acp/__tests__/integration.test.ts +56 -31
- package/src/acp/__tests__/macro-agent.test.ts +16 -7
- package/src/acp/macro-agent.ts +230 -62
- package/src/acp/types.ts +46 -1
- package/src/agent/__tests__/agent-manager.test.ts +228 -2
- package/src/agent/agent-manager.ts +714 -261
- package/src/agent/types.ts +3 -1
- package/src/api/server.ts +41 -7
- package/src/auth/__tests__/token.test.ts +100 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/token.ts +82 -0
- package/src/cli/__tests__/acp.test.ts +1 -1
- package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
- package/src/cli/acp.ts +130 -72
- package/src/cli/index.ts +120 -14
- package/src/cli/mcp.ts +311 -207
- package/src/cli/parse-args.ts +54 -0
- package/src/cli/stable-instance-id.ts +14 -0
- package/src/config/project-config.ts +190 -27
- package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
- package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +820 -0
- package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
- package/src/map/adapter/__tests__/acp-over-map-history.test.ts +724 -2
- package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
- package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
- package/src/map/adapter/__tests__/event-log.test.ts +527 -0
- package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
- package/src/map/adapter/__tests__/extensions.test.ts +408 -0
- package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
- package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
- package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
- package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
- package/src/map/adapter/acp-over-map.ts +777 -92
- package/src/map/adapter/connection-manager.ts +3 -0
- package/src/map/adapter/event-log.ts +208 -0
- package/src/map/adapter/event-translator.ts +6 -6
- package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
- package/src/map/adapter/extensions/index.ts +60 -0
- package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
- package/src/map/adapter/extensions/task.ts +11 -0
- package/src/map/adapter/extensions/update-metadata.ts +126 -0
- package/src/map/adapter/index.ts +28 -0
- package/src/map/adapter/interface.ts +2 -0
- package/src/map/adapter/map-adapter.ts +373 -38
- package/src/map/adapter/subscription-manager.ts +5 -1
- package/src/map/adapter/types.ts +2 -0
- package/src/mcp/__tests__/map-client.test.ts +386 -0
- package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
- package/src/mcp/__tests__/mcp-server.test.ts +100 -1
- package/src/mcp/map-client.ts +177 -0
- package/src/mcp/mcp-server.ts +191 -100
- package/src/mcp/types.ts +6 -1
- package/src/metrics/metrics.ts +1 -1
- package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
- package/src/roles/__tests__/config-loader.test.ts +7 -7
- package/src/roles/capabilities.ts +17 -7
- package/src/roles/config-loader.ts +6 -6
- package/src/roles/registry.ts +2 -2
- package/src/server/__tests__/combined-server.test.ts +94 -21
- package/src/server/combined-server.ts +189 -33
- package/src/steering/__tests__/steering-integration.test.ts +1 -1
- package/src/store/__tests__/event-store.test.ts +236 -1
- package/src/store/__tests__/instance.test.ts +3 -3
- package/src/store/event-store.ts +109 -8
- package/src/store/types/agents.ts +16 -0
- package/src/store/types/events.ts +1 -1
- package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
- package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
- package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
- package/src/task/backend/index.ts +156 -106
- package/src/task/backend/memory.ts +4 -0
- package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
- package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
- package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
- package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
- package/src/task/backend/opentasks/backend.ts +1323 -0
- package/src/task/backend/opentasks/client.ts +652 -0
- package/src/task/backend/opentasks/daemon-manager.ts +253 -0
- package/src/task/backend/opentasks/index.ts +69 -0
- package/src/task/backend/opentasks/mapping.ts +94 -0
- package/src/task/backend/types.ts +42 -66
- package/src/task/backend/unified-tool-provider.ts +779 -0
- package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
- package/src/teams/team-loader.ts +3 -3
- package/src/teams/team-runtime.ts +2 -0
- package/test_fixtures/README.md +2 -3
- package/test_fixtures/fixtures/index.ts +0 -3
- package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
- package/test_fixtures/fixtures/repos/index.ts +1 -3
- package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
- package/test_fixtures/fixtures/repos/types.ts +0 -11
- package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
- package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
- package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
- package/vitest.config.ts +1 -1
- package/vitest.e2e.config.ts +1 -1
- package/vitest.setup.ts +1 -30
- package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
- package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
- package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
- package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
- package/.macro-agent/teams/self-driving/team.yaml +0 -103
- package/.macro-agent/teams/structured/prompts/developer.md +0 -26
- package/.macro-agent/teams/structured/prompts/lead.md +0 -25
- package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
- package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
- package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
- package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
- package/.macro-agent/teams/structured/team.yaml +0 -89
- package/docs/sudocode-integration.md +0 -383
- package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
- package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
- package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
- package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
- package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
- package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
- package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
- package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
- package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
- package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
- package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
- package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
- package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
- package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
- package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
- package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
- package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
- package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
- package/src/task/backend/sudocode/backend.ts +0 -1237
- package/src/task/backend/sudocode/client.ts +0 -515
- package/src/task/backend/sudocode/index.ts +0 -120
- package/src/task/backend/sudocode/mapping.ts +0 -93
- package/src/task/backend/sudocode/server-client.ts +0 -522
- package/src/task/backend/sudocode/standalone-client.ts +0 -623
- package/src/task/backend/sudocode/sync-policy.ts +0 -387
- package/src/task/backend/sudocode/tools.ts +0 -896
- package/src/task/backend/tool-provider.ts +0 -506
- package/test_fixtures/fixtures/sudocode/index.ts +0 -29
- package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
- package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin MAP Client
|
|
3
|
+
*
|
|
4
|
+
* Ephemeral WebSocket client for MCP subprocesses to call MAP extension
|
|
5
|
+
* methods on the main server. Each call opens a connection, performs the
|
|
6
|
+
* MAP handshake, sends a single RPC, and disconnects.
|
|
7
|
+
*
|
|
8
|
+
* Uses raw WebSocket + JSON-RPC — not the full MAP ClientConnection SDK,
|
|
9
|
+
* since the SDK's capability negotiation and subscription management
|
|
10
|
+
* overhead is unnecessary for single-RPC ephemeral calls.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import WebSocket from "ws";
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Types
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
interface JsonRpcRequest {
|
|
20
|
+
jsonrpc: "2.0";
|
|
21
|
+
id: number;
|
|
22
|
+
method: string;
|
|
23
|
+
params?: unknown;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface JsonRpcResponse {
|
|
27
|
+
jsonrpc: "2.0";
|
|
28
|
+
id: number;
|
|
29
|
+
result?: unknown;
|
|
30
|
+
error?: {
|
|
31
|
+
code: number;
|
|
32
|
+
message: string;
|
|
33
|
+
data?: unknown;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface MapCallOptions {
|
|
38
|
+
/** Timeout in milliseconds (default: 30000) */
|
|
39
|
+
timeoutMs?: number;
|
|
40
|
+
/** Server token for authentication (appended as query param on WebSocket URL) */
|
|
41
|
+
serverToken?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class MapCallError extends Error {
|
|
45
|
+
readonly code: number;
|
|
46
|
+
readonly data?: unknown;
|
|
47
|
+
|
|
48
|
+
constructor(code: number, message: string, data?: unknown) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.name = "MapCallError";
|
|
51
|
+
this.code = code;
|
|
52
|
+
this.data = data;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// =============================================================================
|
|
57
|
+
// Implementation
|
|
58
|
+
// =============================================================================
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Make a single MAP extension RPC call via ephemeral WebSocket.
|
|
62
|
+
*
|
|
63
|
+
* 1. Opens WebSocket to the MAP endpoint
|
|
64
|
+
* 2. Sends `map/connect` handshake
|
|
65
|
+
* 3. Sends the RPC request
|
|
66
|
+
* 4. Awaits the response
|
|
67
|
+
* 5. Closes the WebSocket
|
|
68
|
+
*
|
|
69
|
+
* @param serverUrl - HTTP URL of the macro-agent server (e.g., "http://localhost:3001")
|
|
70
|
+
* @param method - MAP extension method (e.g., "_macro/mcp/spawn_agent")
|
|
71
|
+
* @param params - Method parameters (includes context)
|
|
72
|
+
* @param options - Timeout and other options
|
|
73
|
+
* @returns The RPC result
|
|
74
|
+
*/
|
|
75
|
+
export async function mapCall<T = unknown>(
|
|
76
|
+
serverUrl: string,
|
|
77
|
+
method: string,
|
|
78
|
+
params?: unknown,
|
|
79
|
+
options?: MapCallOptions
|
|
80
|
+
): Promise<T> {
|
|
81
|
+
const timeoutMs = options?.timeoutMs ?? 30000;
|
|
82
|
+
let wsUrl = serverUrl.replace(/^http/, "ws") + "/map";
|
|
83
|
+
if (options?.serverToken) {
|
|
84
|
+
wsUrl += `?token=${encodeURIComponent(options.serverToken)}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return new Promise<T>((resolve, reject) => {
|
|
88
|
+
let settled = false;
|
|
89
|
+
let nextId = 1;
|
|
90
|
+
let handshakeCompleted = false;
|
|
91
|
+
|
|
92
|
+
const timeout = setTimeout(() => {
|
|
93
|
+
if (!settled) {
|
|
94
|
+
settled = true;
|
|
95
|
+
ws.close();
|
|
96
|
+
reject(new MapCallError(-32000, `MAP call timed out after ${timeoutMs}ms: ${method}`));
|
|
97
|
+
}
|
|
98
|
+
}, timeoutMs);
|
|
99
|
+
|
|
100
|
+
const ws = new WebSocket(wsUrl);
|
|
101
|
+
|
|
102
|
+
ws.on("open", () => {
|
|
103
|
+
// Step 1: Send MAP handshake
|
|
104
|
+
const connectRequest: JsonRpcRequest = {
|
|
105
|
+
jsonrpc: "2.0",
|
|
106
|
+
id: nextId++,
|
|
107
|
+
method: "map/connect",
|
|
108
|
+
params: {
|
|
109
|
+
participantType: "client",
|
|
110
|
+
identity: `mcp-bridge-${Date.now()}`,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
ws.send(JSON.stringify(connectRequest));
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
ws.on("message", (data) => {
|
|
117
|
+
if (settled) return;
|
|
118
|
+
|
|
119
|
+
let msg: JsonRpcResponse;
|
|
120
|
+
try {
|
|
121
|
+
msg = JSON.parse(data.toString());
|
|
122
|
+
} catch {
|
|
123
|
+
return; // Ignore non-JSON messages
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!handshakeCompleted) {
|
|
127
|
+
// This should be the map/connect response
|
|
128
|
+
if (msg.error) {
|
|
129
|
+
settled = true;
|
|
130
|
+
clearTimeout(timeout);
|
|
131
|
+
ws.close();
|
|
132
|
+
reject(new MapCallError(msg.error.code, `MAP handshake failed: ${msg.error.message}`, msg.error.data));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
handshakeCompleted = true;
|
|
137
|
+
|
|
138
|
+
// Step 2: Send the actual RPC request
|
|
139
|
+
const rpcRequest: JsonRpcRequest = {
|
|
140
|
+
jsonrpc: "2.0",
|
|
141
|
+
id: nextId++,
|
|
142
|
+
method,
|
|
143
|
+
params,
|
|
144
|
+
};
|
|
145
|
+
ws.send(JSON.stringify(rpcRequest));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// This is the RPC response
|
|
150
|
+
settled = true;
|
|
151
|
+
clearTimeout(timeout);
|
|
152
|
+
ws.close();
|
|
153
|
+
|
|
154
|
+
if (msg.error) {
|
|
155
|
+
reject(new MapCallError(msg.error.code, msg.error.message, msg.error.data));
|
|
156
|
+
} else {
|
|
157
|
+
resolve(msg.result as T);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
ws.on("error", (err) => {
|
|
162
|
+
if (!settled) {
|
|
163
|
+
settled = true;
|
|
164
|
+
clearTimeout(timeout);
|
|
165
|
+
reject(new MapCallError(-32000, `MAP WebSocket error: ${err.message}`));
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
ws.on("close", () => {
|
|
170
|
+
if (!settled) {
|
|
171
|
+
settled = true;
|
|
172
|
+
clearTimeout(timeout);
|
|
173
|
+
reject(new MapCallError(-32000, "MAP WebSocket closed unexpectedly"));
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
}
|
package/src/mcp/mcp-server.ts
CHANGED
|
@@ -224,16 +224,6 @@ const StopAgentSchema = {
|
|
|
224
224
|
.describe("Reason for stopping"),
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
const CreateTaskSchema = {
|
|
228
|
-
description: z.string().describe("Task description"),
|
|
229
|
-
parent_task: z.string().optional().describe("Parent task ID for subtasks"),
|
|
230
|
-
inputs: z.record(z.string(), z.unknown()).optional().describe("Initial inputs for the task"),
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
const GetTaskSchema = {
|
|
234
|
-
task_id: z.string().describe("Task ID to look up"),
|
|
235
|
-
};
|
|
236
|
-
|
|
237
227
|
// ─────────────────────────────────────────────────────────────────
|
|
238
228
|
// Peer Communication Schemas
|
|
239
229
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -351,6 +341,12 @@ export function createMCPServer(
|
|
|
351
341
|
debugLog(`[MCP spawn_agent] Agent IDs: ${allAgents.map(a => a.id).join(', ')}`);
|
|
352
342
|
}
|
|
353
343
|
|
|
344
|
+
// Inherit the parent's permission mode so sub-agents respect
|
|
345
|
+
// the same mode (e.g., "interactive") set during initialization.
|
|
346
|
+
// Read from env var since the MCP server is a separate process
|
|
347
|
+
// without access to the macro-agent server's in-memory state.
|
|
348
|
+
const parentPermissionMode = process.env.MACRO_PERMISSION_MODE;
|
|
349
|
+
|
|
354
350
|
const spawned = await agentManager.spawn({
|
|
355
351
|
task: args.task,
|
|
356
352
|
parent: context.agent_id,
|
|
@@ -358,6 +354,7 @@ export function createMCPServer(
|
|
|
358
354
|
topics: args.topics ?? [],
|
|
359
355
|
config: args.config,
|
|
360
356
|
cwd: args.cwd ?? context.cwd,
|
|
357
|
+
permissionMode: (parentPermissionMode || undefined) as import("acp-factory").PermissionMode | undefined,
|
|
361
358
|
});
|
|
362
359
|
|
|
363
360
|
return {
|
|
@@ -366,6 +363,7 @@ export function createMCPServer(
|
|
|
366
363
|
type: "text" as const,
|
|
367
364
|
text: JSON.stringify({
|
|
368
365
|
agent_id: spawned.id,
|
|
366
|
+
name: spawned.agent.name,
|
|
369
367
|
task_id: spawned.agent.task_id,
|
|
370
368
|
session_id: spawned.session_id,
|
|
371
369
|
}),
|
|
@@ -511,14 +509,18 @@ export function createMCPServer(
|
|
|
511
509
|
includeAcknowledged: args.include_acknowledged ?? false,
|
|
512
510
|
});
|
|
513
511
|
|
|
514
|
-
const formattedInternalMessages = internalMessages.map((msg) =>
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
512
|
+
const formattedInternalMessages = internalMessages.map((msg) => {
|
|
513
|
+
const fromAgent = msg.from.agent_id ? agentManager.get(msg.from.agent_id) : undefined;
|
|
514
|
+
return {
|
|
515
|
+
id: msg.id,
|
|
516
|
+
from: `agent:${msg.from.agent_id}`,
|
|
517
|
+
from_name: fromAgent?.name,
|
|
518
|
+
content: msg.content.length > 500 ? msg.content.substring(0, 500) : msg.content,
|
|
519
|
+
timestamp: msg.timestamp,
|
|
520
|
+
truncated: msg.truncated || msg.content.length > 500,
|
|
521
|
+
correlation_id: msg.correlation_id,
|
|
522
|
+
};
|
|
523
|
+
});
|
|
522
524
|
|
|
523
525
|
// Get peer messages if peerManager is available
|
|
524
526
|
let formattedPeerMessages: Array<{
|
|
@@ -586,6 +588,7 @@ export function createMCPServer(
|
|
|
586
588
|
const entries: Array<{
|
|
587
589
|
type: "agent" | "task";
|
|
588
590
|
id: string;
|
|
591
|
+
name?: string;
|
|
589
592
|
summary: string;
|
|
590
593
|
state?: string;
|
|
591
594
|
status?: string;
|
|
@@ -612,6 +615,7 @@ export function createMCPServer(
|
|
|
612
615
|
agents = agents.filter(
|
|
613
616
|
(a) =>
|
|
614
617
|
a.id.toLowerCase().includes(search) ||
|
|
618
|
+
a.name?.toLowerCase().includes(search) ||
|
|
615
619
|
a.task?.toLowerCase().includes(search)
|
|
616
620
|
);
|
|
617
621
|
}
|
|
@@ -620,6 +624,7 @@ export function createMCPServer(
|
|
|
620
624
|
entries.push({
|
|
621
625
|
type: "agent",
|
|
622
626
|
id: agent.id,
|
|
627
|
+
name: agent.name,
|
|
623
628
|
summary: agent.task ?? "No task description",
|
|
624
629
|
state: agent.state,
|
|
625
630
|
});
|
|
@@ -703,6 +708,7 @@ export function createMCPServer(
|
|
|
703
708
|
|
|
704
709
|
return {
|
|
705
710
|
agent_id: node.agent.id,
|
|
711
|
+
name: node.agent.name,
|
|
706
712
|
task: node.agent.task ?? "No task",
|
|
707
713
|
state: node.agent.state,
|
|
708
714
|
children: shouldIncludeChildren
|
|
@@ -772,6 +778,7 @@ export function createMCPServer(
|
|
|
772
778
|
type: "text" as const,
|
|
773
779
|
text: JSON.stringify({
|
|
774
780
|
id: agent.id,
|
|
781
|
+
name: agent.name,
|
|
775
782
|
session_id: agent.session_id,
|
|
776
783
|
task: agent.task ?? "No task",
|
|
777
784
|
state: agent.state,
|
|
@@ -817,7 +824,7 @@ export function createMCPServer(
|
|
|
817
824
|
}
|
|
818
825
|
|
|
819
826
|
// Collect all agents that will be stopped (target + descendants)
|
|
820
|
-
const stoppedAgents: AgentId
|
|
827
|
+
const stoppedAgents: Array<{ agent_id: AgentId; name?: string }> = [];
|
|
821
828
|
|
|
822
829
|
async function stopRecursive(agentId: AgentId): Promise<void> {
|
|
823
830
|
const agent = agentManager.get(agentId);
|
|
@@ -829,9 +836,10 @@ export function createMCPServer(
|
|
|
829
836
|
await stopRecursive(child.id);
|
|
830
837
|
}
|
|
831
838
|
|
|
832
|
-
//
|
|
839
|
+
// Capture name before stopping
|
|
840
|
+
const agentName = agent.name;
|
|
833
841
|
await agentManager.terminate(agentId, args.reason ?? "cancelled");
|
|
834
|
-
stoppedAgents.push(agentId);
|
|
842
|
+
stoppedAgents.push({ agent_id: agentId, name: agentName });
|
|
835
843
|
}
|
|
836
844
|
|
|
837
845
|
await stopRecursive(args.agent_id);
|
|
@@ -850,85 +858,6 @@ export function createMCPServer(
|
|
|
850
858
|
});
|
|
851
859
|
}
|
|
852
860
|
|
|
853
|
-
// ─────────────────────────────────────────────────────────────────
|
|
854
|
-
// Tool: create_task (requires task.create capability)
|
|
855
|
-
// ─────────────────────────────────────────────────────────────────
|
|
856
|
-
|
|
857
|
-
if (shouldRegisterTool("create_task")) {
|
|
858
|
-
server.registerTool("create_task", {
|
|
859
|
-
description: "Create a new task",
|
|
860
|
-
inputSchema: CreateTaskSchema,
|
|
861
|
-
}, async (args) => {
|
|
862
|
-
try {
|
|
863
|
-
const task = taskManager.create({
|
|
864
|
-
description: args.description,
|
|
865
|
-
created_by: context.agent_id,
|
|
866
|
-
parent_task: args.parent_task,
|
|
867
|
-
inputs: args.inputs,
|
|
868
|
-
});
|
|
869
|
-
|
|
870
|
-
return {
|
|
871
|
-
content: [
|
|
872
|
-
{
|
|
873
|
-
type: "text" as const,
|
|
874
|
-
text: JSON.stringify({
|
|
875
|
-
task_id: task.id,
|
|
876
|
-
}),
|
|
877
|
-
},
|
|
878
|
-
],
|
|
879
|
-
};
|
|
880
|
-
} catch (error) {
|
|
881
|
-
throw new MCPToolError(
|
|
882
|
-
`Failed to create task: ${error}`,
|
|
883
|
-
"INVALID_INPUT"
|
|
884
|
-
);
|
|
885
|
-
}
|
|
886
|
-
});
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
// ─────────────────────────────────────────────────────────────────
|
|
890
|
-
// Tool: get_task (always allowed - observability)
|
|
891
|
-
// ─────────────────────────────────────────────────────────────────
|
|
892
|
-
|
|
893
|
-
if (shouldRegisterTool("get_task")) {
|
|
894
|
-
server.registerTool("get_task", {
|
|
895
|
-
description: "Get details of a specific task",
|
|
896
|
-
inputSchema: GetTaskSchema,
|
|
897
|
-
}, async (args) => {
|
|
898
|
-
const task = taskManager.get(args.task_id);
|
|
899
|
-
if (!task) {
|
|
900
|
-
throw new MCPToolError(
|
|
901
|
-
`Task not found: ${args.task_id}`,
|
|
902
|
-
"TASK_NOT_FOUND"
|
|
903
|
-
);
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
// Use completed_at, started_at, or created_at as last update
|
|
907
|
-
const updatedAt = task.completed_at ?? task.started_at ?? task.created_at;
|
|
908
|
-
|
|
909
|
-
return {
|
|
910
|
-
content: [
|
|
911
|
-
{
|
|
912
|
-
type: "text" as const,
|
|
913
|
-
text: JSON.stringify({
|
|
914
|
-
id: task.id,
|
|
915
|
-
description: task.description,
|
|
916
|
-
status: task.status,
|
|
917
|
-
assigned_agent: task.assigned_agent,
|
|
918
|
-
parent_task: task.parent_task,
|
|
919
|
-
subtasks: task.subtasks ?? [],
|
|
920
|
-
inputs: task.inputs,
|
|
921
|
-
outputs: task.outputs,
|
|
922
|
-
artifacts: task.artifacts,
|
|
923
|
-
created_at: task.created_at,
|
|
924
|
-
updated_at: updatedAt,
|
|
925
|
-
}),
|
|
926
|
-
},
|
|
927
|
-
],
|
|
928
|
-
};
|
|
929
|
-
});
|
|
930
|
-
}
|
|
931
|
-
|
|
932
861
|
// ─────────────────────────────────────────────────────────────────
|
|
933
862
|
// Tool: send_peer_message (requires msg.send capability)
|
|
934
863
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -1302,3 +1231,165 @@ export function createMCPServer(
|
|
|
1302
1231
|
close,
|
|
1303
1232
|
};
|
|
1304
1233
|
}
|
|
1234
|
+
|
|
1235
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1236
|
+
// Thin-Client Factory (MAP WebSocket mode)
|
|
1237
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Type for the mapCall function used in thin-client mode.
|
|
1241
|
+
*/
|
|
1242
|
+
export type MapCallFn = <T = unknown>(
|
|
1243
|
+
method: string,
|
|
1244
|
+
params?: unknown,
|
|
1245
|
+
options?: { timeoutMs?: number }
|
|
1246
|
+
) => Promise<T>;
|
|
1247
|
+
|
|
1248
|
+
/**
|
|
1249
|
+
* Creates a thin-client MCP server where every tool handler calls
|
|
1250
|
+
* the main server via MAP WebSocket RPC instead of using local services.
|
|
1251
|
+
*
|
|
1252
|
+
* Tool schemas, descriptions, and role filtering remain the same.
|
|
1253
|
+
* Only the handler bodies change — they forward to `_macro/mcp/*` extensions.
|
|
1254
|
+
*/
|
|
1255
|
+
export function createMCPServerThinClient(
|
|
1256
|
+
context: ToolContext,
|
|
1257
|
+
mapCallFn: MapCallFn,
|
|
1258
|
+
config: MCPServerConfig = {}
|
|
1259
|
+
): MCPServerInstance {
|
|
1260
|
+
const { name = "macro-agent-mcp", version = "1.0.0" } = config;
|
|
1261
|
+
|
|
1262
|
+
const server = new McpServer(
|
|
1263
|
+
{ name, version },
|
|
1264
|
+
{ capabilities: { tools: {} } }
|
|
1265
|
+
);
|
|
1266
|
+
|
|
1267
|
+
/**
|
|
1268
|
+
* Helper: wrap args with agent context for the bridge handler.
|
|
1269
|
+
*/
|
|
1270
|
+
function withContext(args: Record<string, unknown>): Record<string, unknown> {
|
|
1271
|
+
return { ...args, context };
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
* Helper: create a tool handler that forwards to a MAP bridge extension.
|
|
1276
|
+
*/
|
|
1277
|
+
function bridgeTool(
|
|
1278
|
+
toolName: string,
|
|
1279
|
+
schema: Record<string, z.ZodTypeAny>,
|
|
1280
|
+
description: string,
|
|
1281
|
+
mapMethod: string,
|
|
1282
|
+
options?: { timeoutMs?: number }
|
|
1283
|
+
) {
|
|
1284
|
+
server.registerTool(toolName, { description, inputSchema: schema }, async (args) => {
|
|
1285
|
+
try {
|
|
1286
|
+
const result = await mapCallFn(mapMethod, withContext(args as Record<string, unknown>), options);
|
|
1287
|
+
return {
|
|
1288
|
+
content: [{ type: "text" as const, text: JSON.stringify(result) }],
|
|
1289
|
+
};
|
|
1290
|
+
} catch (error) {
|
|
1291
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1292
|
+
throw new MCPToolError(`${toolName} failed: ${message}`, "ROUTING_FAILED");
|
|
1293
|
+
}
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
// Register all tools pointing to their _macro/mcp/* bridge counterparts
|
|
1298
|
+
|
|
1299
|
+
bridgeTool("spawn_agent", SpawnAgentSchema, "Spawn a child agent to work on a subtask",
|
|
1300
|
+
"_macro/mcp/spawn_agent");
|
|
1301
|
+
|
|
1302
|
+
bridgeTool("emit_status", EmitStatusSchema, "Report a status milestone (started, checkpoint, completed, failed, blocked)",
|
|
1303
|
+
"_macro/mcp/emit_status");
|
|
1304
|
+
|
|
1305
|
+
bridgeTool("send_message", SendMessageSchema, "Send a message to another agent, task, or topic",
|
|
1306
|
+
"_macro/mcp/send_message");
|
|
1307
|
+
|
|
1308
|
+
bridgeTool("check_messages", CheckMessagesSchema, "Check pending messages in your inbox",
|
|
1309
|
+
"_macro/mcp/check_messages");
|
|
1310
|
+
|
|
1311
|
+
bridgeTool("query_index", QueryIndexSchema, "Search for agents and tasks",
|
|
1312
|
+
"_macro/mcp/query_index");
|
|
1313
|
+
|
|
1314
|
+
bridgeTool("get_hierarchy", GetHierarchySchema, "View the agent hierarchy tree",
|
|
1315
|
+
"_macro/mcp/get_hierarchy");
|
|
1316
|
+
|
|
1317
|
+
bridgeTool("get_agent_summary", GetAgentSummarySchema, "Get detailed summary of a specific agent",
|
|
1318
|
+
"_macro/mcp/get_agent_summary");
|
|
1319
|
+
|
|
1320
|
+
bridgeTool("stop_agent", StopAgentSchema, "Stop a child agent in your subtree",
|
|
1321
|
+
"_macro/mcp/stop_agent");
|
|
1322
|
+
|
|
1323
|
+
bridgeTool("done", DoneSchema, DONE_TOOL_INFO.description,
|
|
1324
|
+
"_macro/mcp/done");
|
|
1325
|
+
|
|
1326
|
+
bridgeTool("inject_context", InjectContextSchema, INJECT_CONTEXT_TOOL_INFO.description,
|
|
1327
|
+
"_macro/mcp/inject_context");
|
|
1328
|
+
|
|
1329
|
+
bridgeTool("wait_for_activity", WaitForActivitySchema, WAIT_FOR_ACTIVITY_TOOL_INFO.description,
|
|
1330
|
+
"_macro/mcp/wait_for_activity", { timeoutMs: 65000 }); // Extra buffer for long-poll
|
|
1331
|
+
|
|
1332
|
+
bridgeTool("claim_task", ClaimTaskSchema, CLAIM_TASK_TOOL_INFO.description,
|
|
1333
|
+
"_macro/mcp/claim_task");
|
|
1334
|
+
|
|
1335
|
+
bridgeTool("unclaim_task", UnclaimTaskSchema, UNCLAIM_TASK_TOOL_INFO.description,
|
|
1336
|
+
"_macro/mcp/unclaim_task");
|
|
1337
|
+
|
|
1338
|
+
bridgeTool("list_claimable_tasks", ListClaimableTasksSchema, LIST_CLAIMABLE_TASKS_TOOL_INFO.description,
|
|
1339
|
+
"_macro/mcp/list_claimable_tasks");
|
|
1340
|
+
|
|
1341
|
+
bridgeTool("send_peer_message", SendPeerMessageSchema, "Send a fire-and-forget message to another macro-agent (peer)",
|
|
1342
|
+
"_macro/mcp/send_peer_message");
|
|
1343
|
+
|
|
1344
|
+
bridgeTool("send_peer_request", SendPeerRequestSchema, "Send a request to another macro-agent (peer) and wait for response",
|
|
1345
|
+
"_macro/mcp/send_peer_request");
|
|
1346
|
+
|
|
1347
|
+
bridgeTool("respond_to_peer_request", RespondToPeerRequestSchema, "Respond to an incoming peer request",
|
|
1348
|
+
"_macro/mcp/respond_to_peer_request");
|
|
1349
|
+
|
|
1350
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1351
|
+
// Server Lifecycle
|
|
1352
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1353
|
+
|
|
1354
|
+
let transport: StdioServerTransport | null = null;
|
|
1355
|
+
|
|
1356
|
+
async function start(): Promise<void> {
|
|
1357
|
+
// Discover dynamic task tools from the server before connecting.
|
|
1358
|
+
// This ensures we only register tools the server actually supports
|
|
1359
|
+
// (e.g. memory backend = 4 tools, OpenTasks = 7 tools, none = 0).
|
|
1360
|
+
try {
|
|
1361
|
+
const result = await mapCallFn<{ tools: Array<{ name: string; description: string }> }>(
|
|
1362
|
+
"_macro/mcp/task_tools_list",
|
|
1363
|
+
withContext({})
|
|
1364
|
+
);
|
|
1365
|
+
|
|
1366
|
+
if (result?.tools?.length > 0) {
|
|
1367
|
+
const DynamicTaskParamsSchema = {
|
|
1368
|
+
params: z.record(z.string(), z.unknown()).optional()
|
|
1369
|
+
.describe("Tool parameters (validated by the server-side handler)"),
|
|
1370
|
+
};
|
|
1371
|
+
|
|
1372
|
+
for (const tool of result.tools) {
|
|
1373
|
+
bridgeTool(tool.name, DynamicTaskParamsSchema, tool.description,
|
|
1374
|
+
`_macro/mcp/task_tool/${tool.name}`);
|
|
1375
|
+
}
|
|
1376
|
+
debugLog(`[MCP] Registered ${result.tools.length} dynamic task tools from server`);
|
|
1377
|
+
}
|
|
1378
|
+
} catch (error) {
|
|
1379
|
+
// Server may not support task tools — continue without them
|
|
1380
|
+
debugLog(`[MCP] Failed to discover task tools: ${error instanceof Error ? error.message : error}`);
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
transport = new StdioServerTransport();
|
|
1384
|
+
await server.connect(transport);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
async function close(): Promise<void> {
|
|
1388
|
+
if (transport) {
|
|
1389
|
+
await server.close();
|
|
1390
|
+
transport = null;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
return { server, start, close };
|
|
1395
|
+
}
|
package/src/mcp/types.ts
CHANGED
|
@@ -196,6 +196,7 @@ export interface GetTaskInput {
|
|
|
196
196
|
*/
|
|
197
197
|
export interface SpawnAgentOutput {
|
|
198
198
|
agent_id: AgentId;
|
|
199
|
+
name?: string;
|
|
199
200
|
task_id: TaskId;
|
|
200
201
|
session_id: string;
|
|
201
202
|
}
|
|
@@ -223,6 +224,7 @@ export interface CheckMessagesOutput {
|
|
|
223
224
|
messages: Array<{
|
|
224
225
|
id: string;
|
|
225
226
|
from: AgentId;
|
|
227
|
+
from_name?: string;
|
|
226
228
|
content: string;
|
|
227
229
|
timestamp: number;
|
|
228
230
|
truncated: boolean;
|
|
@@ -239,6 +241,7 @@ export interface QueryIndexOutput {
|
|
|
239
241
|
entries: Array<{
|
|
240
242
|
type: "agent" | "task";
|
|
241
243
|
id: string;
|
|
244
|
+
name?: string;
|
|
242
245
|
summary: string;
|
|
243
246
|
state?: string;
|
|
244
247
|
status?: string;
|
|
@@ -258,6 +261,7 @@ export interface GetHierarchyOutput {
|
|
|
258
261
|
|
|
259
262
|
export interface HierarchyNode {
|
|
260
263
|
agent_id: AgentId;
|
|
264
|
+
name?: string;
|
|
261
265
|
task: string;
|
|
262
266
|
state: string;
|
|
263
267
|
children: HierarchyNode[];
|
|
@@ -268,6 +272,7 @@ export interface HierarchyNode {
|
|
|
268
272
|
*/
|
|
269
273
|
export interface GetAgentSummaryOutput {
|
|
270
274
|
id: AgentId;
|
|
275
|
+
name?: string;
|
|
271
276
|
session_id: string;
|
|
272
277
|
task: string;
|
|
273
278
|
state: string;
|
|
@@ -286,7 +291,7 @@ export interface GetAgentSummaryOutput {
|
|
|
286
291
|
*/
|
|
287
292
|
export interface StopAgentOutput {
|
|
288
293
|
success: boolean;
|
|
289
|
-
stopped_agents: AgentId
|
|
294
|
+
stopped_agents: Array<{ agent_id: AgentId; name?: string }>;
|
|
290
295
|
}
|
|
291
296
|
|
|
292
297
|
/**
|
package/src/metrics/metrics.ts
CHANGED
|
@@ -65,20 +65,20 @@ describe("Role Config Loader", () => {
|
|
|
65
65
|
it("CONFIG-PATH-01: getProjectConfigPath returns correct path", () => {
|
|
66
66
|
const projectPath = "/my/project";
|
|
67
67
|
const configPath = getProjectConfigPath(projectPath);
|
|
68
|
-
expect(configPath).toBe("/my/project/.
|
|
68
|
+
expect(configPath).toBe("/my/project/.multiagent/roles.json");
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
it("CONFIG-PATH-02: getProjectConfigPath uses cwd when no path provided", () => {
|
|
72
72
|
const configPath = getProjectConfigPath();
|
|
73
73
|
expect(configPath).toBe(
|
|
74
|
-
path.join(process.cwd(), ".
|
|
74
|
+
path.join(process.cwd(), ".multiagent", "roles.json")
|
|
75
75
|
);
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
it("CONFIG-PATH-03: getUserConfigPath returns path in home directory", () => {
|
|
79
79
|
const configPath = getUserConfigPath();
|
|
80
80
|
expect(configPath).toBe(
|
|
81
|
-
path.join(os.homedir(), ".
|
|
81
|
+
path.join(os.homedir(), ".multiagent", "roles.json")
|
|
82
82
|
);
|
|
83
83
|
});
|
|
84
84
|
});
|
|
@@ -260,7 +260,7 @@ describe("Role Config Loader", () => {
|
|
|
260
260
|
describe("Project/User Config Loading", () => {
|
|
261
261
|
it("CONFIG-PROJECT-01: loadProjectConfig uses correct path", () => {
|
|
262
262
|
const projectPath = tempDir;
|
|
263
|
-
const configDir = path.join(projectPath, ".
|
|
263
|
+
const configDir = path.join(projectPath, ".multiagent");
|
|
264
264
|
fs.mkdirSync(configDir, { recursive: true });
|
|
265
265
|
|
|
266
266
|
const configPath = path.join(configDir, "roles.json");
|
|
@@ -280,7 +280,7 @@ describe("Role Config Loader", () => {
|
|
|
280
280
|
|
|
281
281
|
it("CONFIG-ALL-01: loadAllConfigs combines user and project configs", () => {
|
|
282
282
|
// Create project config
|
|
283
|
-
const projectConfigDir = path.join(tempDir, "project", ".
|
|
283
|
+
const projectConfigDir = path.join(tempDir, "project", ".multiagent");
|
|
284
284
|
fs.mkdirSync(projectConfigDir, { recursive: true });
|
|
285
285
|
writeConfigFile(path.join(projectConfigDir, "roles.json"), {
|
|
286
286
|
roles: {
|
|
@@ -289,7 +289,7 @@ describe("Role Config Loader", () => {
|
|
|
289
289
|
});
|
|
290
290
|
|
|
291
291
|
// Create user config
|
|
292
|
-
const userConfigDir = path.join(tempDir, "user", ".
|
|
292
|
+
const userConfigDir = path.join(tempDir, "user", ".multiagent");
|
|
293
293
|
fs.mkdirSync(userConfigDir, { recursive: true });
|
|
294
294
|
writeConfigFile(path.join(userConfigDir, "roles.json"), {
|
|
295
295
|
roles: {
|
|
@@ -363,7 +363,7 @@ describe("Role Config Loader", () => {
|
|
|
363
363
|
|
|
364
364
|
it("CONFIG-REG-03: Registry with autoLoad loads configs on construction", () => {
|
|
365
365
|
// Create project config
|
|
366
|
-
const projectConfigDir = path.join(tempDir, ".
|
|
366
|
+
const projectConfigDir = path.join(tempDir, ".multiagent");
|
|
367
367
|
fs.mkdirSync(projectConfigDir, { recursive: true });
|
|
368
368
|
writeConfigFile(path.join(projectConfigDir, "roles.json"), {
|
|
369
369
|
roles: {
|