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
|
@@ -117,10 +117,20 @@ export const ALL_CAPABILITIES: Set<Capability> = new Set([
|
|
|
117
117
|
]);
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
|
-
* Check if a capability string is known
|
|
120
|
+
* Check if a capability string is known.
|
|
121
|
+
* Accepts exact matches from ALL_CAPABILITIES, plus dynamic `agent.spawn.*`
|
|
122
|
+
* patterns generated by team-defined spawn rules (e.g., "agent.spawn.grinder").
|
|
121
123
|
*/
|
|
122
124
|
export function isKnownCapability(capability: string): capability is Capability {
|
|
123
|
-
|
|
125
|
+
if (ALL_CAPABILITIES.has(capability as Capability)) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
// Team-defined roles generate dynamic agent.spawn.<role> capabilities
|
|
129
|
+
// via TeamLoader spawn_rules translation (RD3). These are valid at runtime.
|
|
130
|
+
if (capability.startsWith("agent.spawn.")) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
124
134
|
}
|
|
125
135
|
|
|
126
136
|
// =============================================================================
|
|
@@ -156,11 +166,11 @@ export const CAPABILITY_TOOL_MAP: CapabilityToolMap = {
|
|
|
156
166
|
// Lifecycle operations
|
|
157
167
|
[LIFECYCLE_CAPABILITIES.DONE]: ["done"],
|
|
158
168
|
|
|
159
|
-
// Task operations (via
|
|
160
|
-
[TASK_CAPABILITIES.CREATE]: ["
|
|
161
|
-
[TASK_CAPABILITIES.ASSIGN]: ["
|
|
162
|
-
[TASK_CAPABILITIES.UPDATE]: ["
|
|
163
|
-
[TASK_CAPABILITIES.CLOSE]: ["
|
|
169
|
+
// Task operations (via TaskBackend + OpenTasks tools)
|
|
170
|
+
[TASK_CAPABILITIES.CREATE]: ["create_task"],
|
|
171
|
+
[TASK_CAPABILITIES.ASSIGN]: ["assign_task", "task"],
|
|
172
|
+
[TASK_CAPABILITIES.UPDATE]: ["update_task", "task", "link", "annotate"],
|
|
173
|
+
[TASK_CAPABILITIES.CLOSE]: ["close_task", "task"],
|
|
164
174
|
[TASK_CAPABILITIES.CLAIM]: ["claim_task", "unclaim_task", "list_claimable_tasks"],
|
|
165
175
|
|
|
166
176
|
// Execution operations
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Role Configuration File Loader
|
|
3
3
|
*
|
|
4
4
|
* Loads role configurations from:
|
|
5
|
-
* - Project-level: .
|
|
6
|
-
* - User-level: ~/.
|
|
5
|
+
* - Project-level: .multiagent/roles.json
|
|
6
|
+
* - User-level: ~/.multiagent/roles.json
|
|
7
7
|
*
|
|
8
8
|
* Supports layered override with project > user > built-in precedence.
|
|
9
9
|
*
|
|
@@ -103,10 +103,10 @@ export interface LoadResult {
|
|
|
103
103
|
export const CONFIG_FILE_NAME = "roles.json";
|
|
104
104
|
|
|
105
105
|
/** Project-level config directory */
|
|
106
|
-
export const PROJECT_CONFIG_DIR = ".
|
|
106
|
+
export const PROJECT_CONFIG_DIR = ".multiagent";
|
|
107
107
|
|
|
108
108
|
/** User-level config directory */
|
|
109
|
-
export const USER_CONFIG_DIR = ".
|
|
109
|
+
export const USER_CONFIG_DIR = ".multiagent";
|
|
110
110
|
|
|
111
111
|
// =============================================================================
|
|
112
112
|
// Path Resolution
|
|
@@ -116,7 +116,7 @@ export const USER_CONFIG_DIR = ".macro-agent";
|
|
|
116
116
|
* Get the project-level config file path
|
|
117
117
|
*
|
|
118
118
|
* @param projectPath - Project root directory (default: process.cwd())
|
|
119
|
-
* @returns Path to .
|
|
119
|
+
* @returns Path to .multiagent/roles.json
|
|
120
120
|
*/
|
|
121
121
|
export function getProjectConfigPath(projectPath?: string): string {
|
|
122
122
|
const root = projectPath ?? process.cwd();
|
|
@@ -126,7 +126,7 @@ export function getProjectConfigPath(projectPath?: string): string {
|
|
|
126
126
|
/**
|
|
127
127
|
* Get the user-level config file path
|
|
128
128
|
*
|
|
129
|
-
* @returns Path to ~/.
|
|
129
|
+
* @returns Path to ~/.multiagent/roles.json
|
|
130
130
|
*/
|
|
131
131
|
export function getUserConfigPath(): string {
|
|
132
132
|
return path.join(os.homedir(), USER_CONFIG_DIR, CONFIG_FILE_NAME);
|
package/src/roles/registry.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Role Registry Implementation
|
|
3
3
|
*
|
|
4
4
|
* Manages role definitions with layered resolution:
|
|
5
|
-
* - Project-level (.
|
|
6
|
-
* - User-level (~/.
|
|
5
|
+
* - Project-level (.multiagent/roles)
|
|
6
|
+
* - User-level (~/.multiagent/roles)
|
|
7
7
|
* - Built-in (framework)
|
|
8
8
|
*/
|
|
9
9
|
|
|
@@ -19,6 +19,13 @@ function getRandomPort(): number {
|
|
|
19
19
|
return 10000 + Math.floor(Math.random() * 50000);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
const TEST_TOKEN = "test-server-token-for-unit-tests";
|
|
23
|
+
|
|
24
|
+
/** Build a WebSocket URL with auth token query param */
|
|
25
|
+
function wsUrl(port: number, path: string): string {
|
|
26
|
+
return `ws://localhost:${port}${path}?token=${TEST_TOKEN}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
describe("createCombinedServer with MAP", () => {
|
|
23
30
|
let server: CombinedServer;
|
|
24
31
|
let services: CombinedServerServices;
|
|
@@ -33,6 +40,7 @@ describe("createCombinedServer with MAP", () => {
|
|
|
33
40
|
get: vi.fn().mockReturnValue(null),
|
|
34
41
|
list: vi.fn().mockReturnValue([]),
|
|
35
42
|
getChildren: vi.fn().mockReturnValue([]),
|
|
43
|
+
onLifecycleEvent: vi.fn(),
|
|
36
44
|
} as unknown as AgentManager,
|
|
37
45
|
eventStore: {
|
|
38
46
|
append: vi.fn(),
|
|
@@ -64,7 +72,7 @@ describe("createCombinedServer with MAP", () => {
|
|
|
64
72
|
|
|
65
73
|
describe("MAP protocol integration", () => {
|
|
66
74
|
it("starts with MAP adapter enabled by default", async () => {
|
|
67
|
-
server = createCombinedServer(services, { port });
|
|
75
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
68
76
|
await server.start();
|
|
69
77
|
|
|
70
78
|
expect(server.mapAdapter).toBeDefined();
|
|
@@ -72,10 +80,10 @@ describe("createCombinedServer with MAP", () => {
|
|
|
72
80
|
});
|
|
73
81
|
|
|
74
82
|
it("accepts MAP connections on /map", async () => {
|
|
75
|
-
server = createCombinedServer(services, { port });
|
|
83
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
76
84
|
await server.start();
|
|
77
85
|
|
|
78
|
-
const ws = new WebSocket(
|
|
86
|
+
const ws = new WebSocket(wsUrl(port, "/map"));
|
|
79
87
|
|
|
80
88
|
await new Promise<void>((resolve, reject) => {
|
|
81
89
|
const timeout = setTimeout(() => reject(new Error("Connection timeout")), 2000);
|
|
@@ -98,10 +106,10 @@ describe("createCombinedServer with MAP", () => {
|
|
|
98
106
|
}, 5000);
|
|
99
107
|
|
|
100
108
|
it("uses custom MAP path", async () => {
|
|
101
|
-
server = createCombinedServer(services, { port, mapPath: "/custom-map" });
|
|
109
|
+
server = createCombinedServer(services, { port, mapPath: "/custom-map", serverToken: TEST_TOKEN });
|
|
102
110
|
await server.start();
|
|
103
111
|
|
|
104
|
-
const ws = new WebSocket(
|
|
112
|
+
const ws = new WebSocket(wsUrl(port, "/custom-map"));
|
|
105
113
|
|
|
106
114
|
await new Promise<void>((resolve, reject) => {
|
|
107
115
|
const timeout = setTimeout(() => reject(new Error("Connection timeout")), 2000);
|
|
@@ -124,14 +132,14 @@ describe("createCombinedServer with MAP", () => {
|
|
|
124
132
|
}, 5000);
|
|
125
133
|
|
|
126
134
|
it("can disable MAP protocol", async () => {
|
|
127
|
-
server = createCombinedServer(services, { port, disableMap: true });
|
|
135
|
+
server = createCombinedServer(services, { port, disableMap: true, serverToken: TEST_TOKEN });
|
|
128
136
|
await server.start();
|
|
129
137
|
|
|
130
138
|
expect(server.mapAdapter).toBeUndefined();
|
|
131
139
|
expect(server.getMAPConnectionCount()).toBe(0);
|
|
132
140
|
|
|
133
|
-
// Connection to /map should fail
|
|
134
|
-
const ws = new WebSocket(
|
|
141
|
+
// Connection to /map should fail (either 401 without token or 404)
|
|
142
|
+
const ws = new WebSocket(wsUrl(port, "/map"));
|
|
135
143
|
|
|
136
144
|
await new Promise<void>((resolve) => {
|
|
137
145
|
ws.on("error", () => resolve());
|
|
@@ -142,7 +150,7 @@ describe("createCombinedServer with MAP", () => {
|
|
|
142
150
|
}, 5000);
|
|
143
151
|
|
|
144
152
|
it("stops MAP adapter on shutdown", async () => {
|
|
145
|
-
server = createCombinedServer(services, { port });
|
|
153
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
146
154
|
await server.start();
|
|
147
155
|
|
|
148
156
|
expect(server.mapAdapter?.isRunning()).toBe(true);
|
|
@@ -155,7 +163,7 @@ describe("createCombinedServer with MAP", () => {
|
|
|
155
163
|
|
|
156
164
|
describe("health endpoint", () => {
|
|
157
165
|
it("includes map_connections in health response", async () => {
|
|
158
|
-
server = createCombinedServer(services, { port });
|
|
166
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
159
167
|
await server.start();
|
|
160
168
|
|
|
161
169
|
const response = await fetch(`http://localhost:${port}/health`);
|
|
@@ -169,7 +177,7 @@ describe("createCombinedServer with MAP", () => {
|
|
|
169
177
|
});
|
|
170
178
|
|
|
171
179
|
it("shows 0 map_connections when MAP is disabled", async () => {
|
|
172
|
-
server = createCombinedServer(services, { port, disableMap: true });
|
|
180
|
+
server = createCombinedServer(services, { port, disableMap: true, serverToken: TEST_TOKEN });
|
|
173
181
|
await server.start();
|
|
174
182
|
|
|
175
183
|
const response = await fetch(`http://localhost:${port}/health`);
|
|
@@ -179,16 +187,81 @@ describe("createCombinedServer with MAP", () => {
|
|
|
179
187
|
});
|
|
180
188
|
});
|
|
181
189
|
|
|
190
|
+
describe("authentication", () => {
|
|
191
|
+
it("rejects WebSocket connections without token", async () => {
|
|
192
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
193
|
+
await server.start();
|
|
194
|
+
|
|
195
|
+
const ws = new WebSocket(`ws://localhost:${port}/map`);
|
|
196
|
+
|
|
197
|
+
await new Promise<void>((resolve) => {
|
|
198
|
+
ws.on("error", () => resolve());
|
|
199
|
+
ws.on("close", () => resolve());
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
expect(server.getMAPConnectionCount()).toBe(0);
|
|
203
|
+
}, 5000);
|
|
204
|
+
|
|
205
|
+
it("rejects WebSocket connections with wrong token", async () => {
|
|
206
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
207
|
+
await server.start();
|
|
208
|
+
|
|
209
|
+
const ws = new WebSocket(`ws://localhost:${port}/map?token=wrong-token`);
|
|
210
|
+
|
|
211
|
+
await new Promise<void>((resolve) => {
|
|
212
|
+
ws.on("error", () => resolve());
|
|
213
|
+
ws.on("close", () => resolve());
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
expect(server.getMAPConnectionCount()).toBe(0);
|
|
217
|
+
}, 5000);
|
|
218
|
+
|
|
219
|
+
it("exposes serverToken on the server object", () => {
|
|
220
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
221
|
+
expect(server.serverToken).toBe(TEST_TOKEN);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("has no serverToken when not provided (auth disabled by default)", () => {
|
|
225
|
+
server = createCombinedServer(services, { port });
|
|
226
|
+
expect(server.serverToken).toBeUndefined();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it("allows connections without token when noAuth is true", async () => {
|
|
230
|
+
server = createCombinedServer(services, { port, noAuth: true });
|
|
231
|
+
await server.start();
|
|
232
|
+
|
|
233
|
+
expect(server.serverToken).toBeUndefined();
|
|
234
|
+
|
|
235
|
+
// Should connect without any token
|
|
236
|
+
const ws = new WebSocket(`ws://localhost:${port}/map`);
|
|
237
|
+
|
|
238
|
+
await new Promise<void>((resolve, reject) => {
|
|
239
|
+
const timeout = setTimeout(() => reject(new Error("Connection timeout")), 2000);
|
|
240
|
+
ws.on("open", () => {
|
|
241
|
+
clearTimeout(timeout);
|
|
242
|
+
resolve();
|
|
243
|
+
});
|
|
244
|
+
ws.on("error", (err) => {
|
|
245
|
+
clearTimeout(timeout);
|
|
246
|
+
reject(err);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
expect(server.getMAPConnectionCount()).toBe(1);
|
|
251
|
+
ws.close();
|
|
252
|
+
}, 5000);
|
|
253
|
+
});
|
|
254
|
+
|
|
182
255
|
describe("connection counts", () => {
|
|
183
256
|
it("tracks MAP connections separately", async () => {
|
|
184
|
-
server = createCombinedServer(services, { port });
|
|
257
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
185
258
|
await server.start();
|
|
186
259
|
|
|
187
260
|
expect(server.getACPConnectionCount()).toBe(0);
|
|
188
261
|
expect(server.getMAPConnectionCount()).toBe(0);
|
|
189
262
|
|
|
190
263
|
// Open MAP connection
|
|
191
|
-
const mapWs = new WebSocket(
|
|
264
|
+
const mapWs = new WebSocket(wsUrl(port, "/map"));
|
|
192
265
|
await new Promise<void>((resolve, reject) => {
|
|
193
266
|
const timeout = setTimeout(() => reject(new Error("Timeout")), 2000);
|
|
194
267
|
mapWs.on("open", () => {
|
|
@@ -212,10 +285,10 @@ describe("createCombinedServer with MAP", () => {
|
|
|
212
285
|
|
|
213
286
|
describe("existing functionality preserved", () => {
|
|
214
287
|
it("accepts ACP connections on /acp", async () => {
|
|
215
|
-
server = createCombinedServer(services, { port });
|
|
288
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
216
289
|
await server.start();
|
|
217
290
|
|
|
218
|
-
const ws = new WebSocket(
|
|
291
|
+
const ws = new WebSocket(wsUrl(port, "/acp"));
|
|
219
292
|
|
|
220
293
|
await new Promise<void>((resolve, reject) => {
|
|
221
294
|
const timeout = setTimeout(() => reject(new Error("Connection timeout")), 2000);
|
|
@@ -237,10 +310,10 @@ describe("createCombinedServer with MAP", () => {
|
|
|
237
310
|
}, 5000);
|
|
238
311
|
|
|
239
312
|
it("accepts API WebSocket connections on /api/ws", async () => {
|
|
240
|
-
server = createCombinedServer(services, { port });
|
|
313
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
241
314
|
await server.start();
|
|
242
315
|
|
|
243
|
-
const ws = new WebSocket(
|
|
316
|
+
const ws = new WebSocket(wsUrl(port, "/api/ws"));
|
|
244
317
|
|
|
245
318
|
await new Promise<void>((resolve, reject) => {
|
|
246
319
|
const timeout = setTimeout(() => reject(new Error("Connection timeout")), 2000);
|
|
@@ -258,10 +331,10 @@ describe("createCombinedServer with MAP", () => {
|
|
|
258
331
|
}, 5000);
|
|
259
332
|
|
|
260
333
|
it("rejects connections on unknown paths", async () => {
|
|
261
|
-
server = createCombinedServer(services, { port });
|
|
334
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
262
335
|
await server.start();
|
|
263
336
|
|
|
264
|
-
const ws = new WebSocket(
|
|
337
|
+
const ws = new WebSocket(wsUrl(port, "/unknown"));
|
|
265
338
|
|
|
266
339
|
await new Promise<void>((resolve) => {
|
|
267
340
|
ws.on("error", () => resolve());
|
|
@@ -275,12 +348,12 @@ describe("createCombinedServer with MAP", () => {
|
|
|
275
348
|
|
|
276
349
|
describe("server properties", () => {
|
|
277
350
|
it("exposes mapAdapter when enabled", () => {
|
|
278
|
-
server = createCombinedServer(services, { port });
|
|
351
|
+
server = createCombinedServer(services, { port, serverToken: TEST_TOKEN });
|
|
279
352
|
expect(server.mapAdapter).toBeDefined();
|
|
280
353
|
});
|
|
281
354
|
|
|
282
355
|
it("mapAdapter is undefined when disabled", () => {
|
|
283
|
-
server = createCombinedServer(services, { port, disableMap: true });
|
|
356
|
+
server = createCombinedServer(services, { port, disableMap: true, serverToken: TEST_TOKEN });
|
|
284
357
|
expect(server.mapAdapter).toBeUndefined();
|
|
285
358
|
});
|
|
286
359
|
});
|