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
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
type ScopeId,
|
|
66
66
|
} from "../types.js";
|
|
67
67
|
import type { AgentId } from "../../store/types/index.js";
|
|
68
|
+
import type { AgentStopReason } from "../../agent/types.js";
|
|
68
69
|
import {
|
|
69
70
|
createConnectionManager,
|
|
70
71
|
type ConnectionManager,
|
|
@@ -92,6 +93,7 @@ import type {
|
|
|
92
93
|
} from "../federation/types.js";
|
|
93
94
|
import { ACPOverMAPHandler, type ACPEnvelope } from "./acp-over-map.js";
|
|
94
95
|
import { createMailHandlers } from "./mail-handler-adapter.js";
|
|
96
|
+
import { EventLog, dotToUnderscore } from "./event-log.js";
|
|
95
97
|
|
|
96
98
|
// =============================================================================
|
|
97
99
|
// Connection Session
|
|
@@ -227,7 +229,8 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
227
229
|
/** Sequence numbers per subscription for proper event ordering */
|
|
228
230
|
private readonly subscriptionSequences: Map<SubscriptionId, number> =
|
|
229
231
|
new Map();
|
|
230
|
-
|
|
232
|
+
/** In-memory event log for map/replay support */
|
|
233
|
+
private readonly eventLog: EventLog;
|
|
231
234
|
private running = false;
|
|
232
235
|
|
|
233
236
|
constructor(
|
|
@@ -248,10 +251,95 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
248
251
|
eventStore: services.eventStore,
|
|
249
252
|
taskManager: services.taskManager,
|
|
250
253
|
defaultCwd: services.defaultCwd,
|
|
254
|
+
// Note: agent_registered events are now emitted by the lifecycle
|
|
255
|
+
// listener below, which covers ALL spawn paths (ACP, MCP, etc.)
|
|
251
256
|
});
|
|
252
257
|
console.error("[MAPAdapter] ACP-over-MAP handler initialized");
|
|
253
258
|
}
|
|
254
259
|
|
|
260
|
+
// Listen for agent lifecycle events so spawns/stops happening in THIS
|
|
261
|
+
// process (main server) emit MAP events to subscribers immediately.
|
|
262
|
+
if (services.agentManager) {
|
|
263
|
+
services.agentManager.onLifecycleEvent((event) => {
|
|
264
|
+
if (event.type === "spawned" && event.agent) {
|
|
265
|
+
const agentId = event.agent.id as AgentId;
|
|
266
|
+
this.emitEvent({
|
|
267
|
+
eventId: ulid(),
|
|
268
|
+
type: "agent_registered" as MAPEventType,
|
|
269
|
+
timestamp: Date.now(),
|
|
270
|
+
agentId,
|
|
271
|
+
data: {
|
|
272
|
+
agentId: event.agent.id,
|
|
273
|
+
name: event.agent.name ?? "",
|
|
274
|
+
role: event.agent.role ?? "worker",
|
|
275
|
+
state: event.agent.state ?? "spawning",
|
|
276
|
+
parent: event.agent.parent ?? undefined,
|
|
277
|
+
metadata: event.agent.metadata ?? {},
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
} else if (event.type === "stopped" && event.agent) {
|
|
281
|
+
const agentId = event.agent.id as AgentId;
|
|
282
|
+
this.emitEvent({
|
|
283
|
+
eventId: ulid(),
|
|
284
|
+
type: "agent_state_changed" as MAPEventType,
|
|
285
|
+
timestamp: Date.now(),
|
|
286
|
+
agentId,
|
|
287
|
+
data: {
|
|
288
|
+
agentId: event.agent.id,
|
|
289
|
+
current: "stopped",
|
|
290
|
+
previous: "running",
|
|
291
|
+
reason: event.reason,
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
this.emitEvent({
|
|
295
|
+
eventId: ulid(),
|
|
296
|
+
type: "agent_unregistered" as MAPEventType,
|
|
297
|
+
timestamp: Date.now(),
|
|
298
|
+
agentId,
|
|
299
|
+
data: {
|
|
300
|
+
agentId: event.agent.id,
|
|
301
|
+
reason: event.reason,
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Listen for EventStore task changes to emit MAP task events.
|
|
309
|
+
// Task mutations from MCP bridge handlers run in-process, so
|
|
310
|
+
// onTaskChange fires immediately when tasks are created/updated.
|
|
311
|
+
if (services.eventStore) {
|
|
312
|
+
services.eventStore.onTaskChange((taskId, task) => {
|
|
313
|
+
if (!task) return;
|
|
314
|
+
// Map task status to MAP event type
|
|
315
|
+
const eventTypeMap: Record<string, string> = {
|
|
316
|
+
pending: "task_created",
|
|
317
|
+
assigned: "task_assigned",
|
|
318
|
+
in_progress: "task_assigned",
|
|
319
|
+
completed: "task_completed",
|
|
320
|
+
failed: "task_failed",
|
|
321
|
+
// OpenTasks statuses (defensive — normally mapped before reaching here)
|
|
322
|
+
closed: "task_completed",
|
|
323
|
+
open: "task_created",
|
|
324
|
+
};
|
|
325
|
+
const mapEventType = eventTypeMap[task.status];
|
|
326
|
+
if (mapEventType) {
|
|
327
|
+
this.emitEvent({
|
|
328
|
+
eventId: ulid(),
|
|
329
|
+
type: mapEventType as MAPEventType,
|
|
330
|
+
timestamp: Date.now(),
|
|
331
|
+
agentId: (task.assigned_agent ?? undefined) as AgentId | undefined,
|
|
332
|
+
data: {
|
|
333
|
+
taskId,
|
|
334
|
+
description: task.description,
|
|
335
|
+
status: task.status,
|
|
336
|
+
assignee: task.assigned_agent,
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
255
343
|
// Initialize connection manager
|
|
256
344
|
this.connections = createConnectionManager({
|
|
257
345
|
limits: config.limits,
|
|
@@ -267,6 +355,11 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
267
355
|
getDescendants: services.getDescendants,
|
|
268
356
|
});
|
|
269
357
|
|
|
358
|
+
// Initialize event log for replay support
|
|
359
|
+
this.eventLog = new EventLog({
|
|
360
|
+
maxSize: config.limits?.maxReplayBufferSize ?? 10_000,
|
|
361
|
+
});
|
|
362
|
+
|
|
270
363
|
// Forward connection events
|
|
271
364
|
this.connections.onEvent((event) => {
|
|
272
365
|
if (event.type === "participant.connected") {
|
|
@@ -541,6 +634,17 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
541
634
|
// ===========================================================================
|
|
542
635
|
|
|
543
636
|
emitEvent(event: EventNotification): void {
|
|
637
|
+
// Log event for replay support
|
|
638
|
+
this.eventLog.append({
|
|
639
|
+
eventId: event.eventId,
|
|
640
|
+
timestamp: event.timestamp,
|
|
641
|
+
type: event.type,
|
|
642
|
+
data: event.data,
|
|
643
|
+
causedBy: event.causedBy,
|
|
644
|
+
agentId: event.agentId,
|
|
645
|
+
scopeId: event.scopeId,
|
|
646
|
+
});
|
|
647
|
+
|
|
544
648
|
// Match event against subscriptions
|
|
545
649
|
const { subscriptions: matchingSubs } = this.subscriptions.match(event);
|
|
546
650
|
|
|
@@ -702,6 +806,9 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
702
806
|
"map/unsubscribe": async (params) =>
|
|
703
807
|
this.handleUnsubscribe(participantId, params),
|
|
704
808
|
|
|
809
|
+
// Replay
|
|
810
|
+
"map/replay": async (params) => this.handleReplay(participantId, params),
|
|
811
|
+
|
|
705
812
|
// Messaging
|
|
706
813
|
"map/send": async (params, ctx) =>
|
|
707
814
|
this.handleSend(participantId, params, ctx),
|
|
@@ -712,6 +819,10 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
712
819
|
"map/agents/get": async (params) =>
|
|
713
820
|
this.handleGetAgent(participantId, params),
|
|
714
821
|
|
|
822
|
+
// Agent lifecycle
|
|
823
|
+
"map/agents/stop": async (params) =>
|
|
824
|
+
this.handleStopAgent(participantId, params),
|
|
825
|
+
|
|
715
826
|
// Scope queries
|
|
716
827
|
"map/scopes/list": async () => this.handleListScopes(participantId),
|
|
717
828
|
"map/scopes/get": async (params) =>
|
|
@@ -761,9 +872,11 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
761
872
|
keyof ConnectedParticipant["capabilities"]
|
|
762
873
|
> = {
|
|
763
874
|
"map/subscribe": "canSubscribe",
|
|
875
|
+
"map/replay": "canSubscribe",
|
|
764
876
|
"map/send": "canMessage",
|
|
765
877
|
"map/agents/list": "canQuery",
|
|
766
878
|
"map/agents/get": "canQuery",
|
|
879
|
+
"map/agents/stop": "canStop",
|
|
767
880
|
"map/scopes/list": "canQuery",
|
|
768
881
|
"map/scopes/get": "canQuery",
|
|
769
882
|
"map/scopes/create": "canManageScopes",
|
|
@@ -808,16 +921,27 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
808
921
|
break;
|
|
809
922
|
}
|
|
810
923
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
924
|
+
// Process messages concurrently (same pattern as toad reference).
|
|
925
|
+
// The message loop must not block on any handler, otherwise
|
|
926
|
+
// session/cancel can't be delivered while session/prompt is running.
|
|
927
|
+
// The stream writer queues writes safely, so concurrent responses
|
|
928
|
+
// don't interleave.
|
|
929
|
+
const processAndRespond = async () => {
|
|
930
|
+
const result = await session.rpcHandler.process(value, {
|
|
931
|
+
participantId: session.participantId,
|
|
932
|
+
capabilities: participant.capabilities,
|
|
933
|
+
signal: session.abortController.signal,
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
if (result.type === "response") {
|
|
937
|
+
await this.sendToSession(session, result.response);
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
processAndRespond().catch((err) => {
|
|
941
|
+
if (!session.abortController.signal.aborted) {
|
|
942
|
+
console.error(`[MAPAdapter] Error processing message:`, err);
|
|
943
|
+
}
|
|
815
944
|
});
|
|
816
|
-
|
|
817
|
-
// Send response if needed
|
|
818
|
-
if (result.type === "response") {
|
|
819
|
-
await this.sendToSession(session, result.response);
|
|
820
|
-
}
|
|
821
945
|
}
|
|
822
946
|
} catch (error) {
|
|
823
947
|
if (!session.abortController.signal.aborted) {
|
|
@@ -871,12 +995,20 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
871
995
|
const connectParams = params as
|
|
872
996
|
| {
|
|
873
997
|
type?: ParticipantType;
|
|
998
|
+
participantType?: ParticipantType;
|
|
874
999
|
name?: string;
|
|
875
1000
|
credentials?: AuthCredentials;
|
|
1001
|
+
capabilities?: {
|
|
1002
|
+
observation?: { canObserve?: boolean; canQuery?: boolean };
|
|
1003
|
+
messaging?: { canSend?: boolean; canReceive?: boolean; canBroadcast?: boolean };
|
|
1004
|
+
lifecycle?: { canSpawn?: boolean; canRegister?: boolean; canUnregister?: boolean; canSteer?: boolean; canStop?: boolean };
|
|
1005
|
+
scopes?: { canCreateScopes?: boolean; canManageScopes?: boolean };
|
|
1006
|
+
management?: { canManageTasks?: boolean; canManageLifecycle?: boolean };
|
|
1007
|
+
};
|
|
876
1008
|
}
|
|
877
1009
|
| undefined;
|
|
878
1010
|
|
|
879
|
-
const requestedType = connectParams?.type ?? participant.type;
|
|
1011
|
+
const requestedType = connectParams?.type ?? connectParams?.participantType ?? participant.type;
|
|
880
1012
|
const credentials = connectParams?.credentials;
|
|
881
1013
|
|
|
882
1014
|
// Handle authentication if handler is configured and credentials provided
|
|
@@ -905,15 +1037,41 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
905
1037
|
};
|
|
906
1038
|
}
|
|
907
1039
|
|
|
908
|
-
//
|
|
1040
|
+
// Start with default capabilities for the requested type
|
|
1041
|
+
const baseCapabilities = this.getDefaultCapabilities(requestedType);
|
|
1042
|
+
|
|
1043
|
+
// Merge client-requested capabilities (SDK nested format → flat format).
|
|
1044
|
+
// Clients can request additional capabilities; the server grants them
|
|
1045
|
+
// by merging with the type defaults.
|
|
1046
|
+
if (connectParams?.capabilities) {
|
|
1047
|
+
const req = connectParams.capabilities;
|
|
1048
|
+
const requested: Partial<ParticipantCapabilities> = {};
|
|
1049
|
+
if (req.observation?.canQuery !== undefined) requested.canQuery = req.observation.canQuery;
|
|
1050
|
+
if (req.observation?.canObserve !== undefined) requested.canSubscribe = req.observation.canObserve;
|
|
1051
|
+
if (req.messaging?.canSend !== undefined) requested.canMessage = req.messaging.canSend;
|
|
1052
|
+
if (req.lifecycle?.canSpawn !== undefined) requested.canSpawn = req.lifecycle.canSpawn;
|
|
1053
|
+
if (req.lifecycle?.canStop !== undefined) requested.canStop = req.lifecycle.canStop;
|
|
1054
|
+
if (req.scopes?.canManageScopes !== undefined) requested.canManageScopes = req.scopes.canManageScopes;
|
|
1055
|
+
if (req.management?.canManageTasks !== undefined) requested.canManageTasks = req.management.canManageTasks;
|
|
1056
|
+
if (req.management?.canManageLifecycle !== undefined) requested.canManageLifecycle = req.management.canManageLifecycle;
|
|
1057
|
+
const mergedCapabilities = { ...baseCapabilities, ...requested };
|
|
1058
|
+
this.connections.updateCapabilities(participantId, mergedCapabilities);
|
|
1059
|
+
|
|
1060
|
+
const updatedParticipant = this.connections.getParticipant(participantId);
|
|
1061
|
+
return {
|
|
1062
|
+
participantId: participant.id,
|
|
1063
|
+
capabilities: updatedParticipant?.capabilities ?? mergedCapabilities,
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// No client-requested capabilities — apply type defaults if type changed
|
|
909
1068
|
if (requestedType !== participant.type) {
|
|
910
|
-
|
|
911
|
-
this.connections.updateCapabilities(participantId, defaultCapabilities);
|
|
1069
|
+
this.connections.updateCapabilities(participantId, baseCapabilities);
|
|
912
1070
|
|
|
913
1071
|
const updatedParticipant = this.connections.getParticipant(participantId);
|
|
914
1072
|
return {
|
|
915
1073
|
participantId: participant.id,
|
|
916
|
-
capabilities: updatedParticipant?.capabilities ??
|
|
1074
|
+
capabilities: updatedParticipant?.capabilities ?? baseCapabilities,
|
|
917
1075
|
};
|
|
918
1076
|
}
|
|
919
1077
|
|
|
@@ -941,6 +1099,7 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
941
1099
|
canManageScopes: true,
|
|
942
1100
|
canManageTasks: true,
|
|
943
1101
|
canManageFederation: true,
|
|
1102
|
+
canManageLifecycle: true,
|
|
944
1103
|
}
|
|
945
1104
|
);
|
|
946
1105
|
case "gateway":
|
|
@@ -953,6 +1112,7 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
953
1112
|
canManageScopes: false,
|
|
954
1113
|
canManageTasks: false,
|
|
955
1114
|
canManageFederation: true,
|
|
1115
|
+
canManageLifecycle: false,
|
|
956
1116
|
};
|
|
957
1117
|
case "client":
|
|
958
1118
|
default:
|
|
@@ -965,6 +1125,7 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
965
1125
|
canStop: false,
|
|
966
1126
|
canManageScopes: false,
|
|
967
1127
|
canManageTasks: false,
|
|
1128
|
+
canManageLifecycle: false,
|
|
968
1129
|
}
|
|
969
1130
|
);
|
|
970
1131
|
}
|
|
@@ -1015,6 +1176,69 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
1015
1176
|
return { success: true };
|
|
1016
1177
|
}
|
|
1017
1178
|
|
|
1179
|
+
private async handleReplay(
|
|
1180
|
+
_participantId: ParticipantId,
|
|
1181
|
+
params: unknown,
|
|
1182
|
+
): Promise<{
|
|
1183
|
+
events: Array<{
|
|
1184
|
+
eventId: string;
|
|
1185
|
+
timestamp: number;
|
|
1186
|
+
causedBy?: string[];
|
|
1187
|
+
event: { id: string; type: string; timestamp: number; data: unknown };
|
|
1188
|
+
}>;
|
|
1189
|
+
hasMore: boolean;
|
|
1190
|
+
}> {
|
|
1191
|
+
const { afterEventId, fromTimestamp, toTimestamp, filter, limit } =
|
|
1192
|
+
(params ?? {}) as {
|
|
1193
|
+
afterEventId?: string;
|
|
1194
|
+
fromTimestamp?: number;
|
|
1195
|
+
toTimestamp?: number;
|
|
1196
|
+
filter?: {
|
|
1197
|
+
eventTypes?: string[];
|
|
1198
|
+
fromAgents?: string[];
|
|
1199
|
+
agents?: string[];
|
|
1200
|
+
scopes?: string[];
|
|
1201
|
+
};
|
|
1202
|
+
limit?: number;
|
|
1203
|
+
};
|
|
1204
|
+
|
|
1205
|
+
// Translate SDK filter field names to internal format
|
|
1206
|
+
// SDK uses 'fromAgents', macro-agent uses 'agents'
|
|
1207
|
+
const internalFilter = filter
|
|
1208
|
+
? {
|
|
1209
|
+
eventTypes: filter.eventTypes,
|
|
1210
|
+
agents: (filter.fromAgents ?? filter.agents) as string[] | undefined,
|
|
1211
|
+
scopes: filter.scopes,
|
|
1212
|
+
}
|
|
1213
|
+
: undefined;
|
|
1214
|
+
|
|
1215
|
+
const result = this.eventLog.query({
|
|
1216
|
+
afterEventId,
|
|
1217
|
+
fromTimestamp,
|
|
1218
|
+
toTimestamp,
|
|
1219
|
+
filter: internalFilter,
|
|
1220
|
+
limit,
|
|
1221
|
+
});
|
|
1222
|
+
|
|
1223
|
+
// Transform events to SDK response format
|
|
1224
|
+
const events = result.events.map((e) => ({
|
|
1225
|
+
eventId: e.eventId,
|
|
1226
|
+
timestamp: e.timestamp,
|
|
1227
|
+
...(e.causedBy && { causedBy: e.causedBy }),
|
|
1228
|
+
event: {
|
|
1229
|
+
id: e.eventId,
|
|
1230
|
+
type: dotToUnderscore(e.type),
|
|
1231
|
+
timestamp: e.timestamp,
|
|
1232
|
+
data: e.data,
|
|
1233
|
+
},
|
|
1234
|
+
}));
|
|
1235
|
+
|
|
1236
|
+
return {
|
|
1237
|
+
events,
|
|
1238
|
+
hasMore: result.hasMore,
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1018
1242
|
private async handleSend(
|
|
1019
1243
|
participantId: ParticipantId,
|
|
1020
1244
|
params: unknown,
|
|
@@ -1104,6 +1328,27 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
1104
1328
|
);
|
|
1105
1329
|
}
|
|
1106
1330
|
|
|
1331
|
+
// Emit client→agent ACP request as a message_sent event so other
|
|
1332
|
+
// TUI clients can observe user prompts and other ACP operations.
|
|
1333
|
+
// Include from/to at top level of data for extractACPFromMessageEvent()
|
|
1334
|
+
// which reads data.from/data.to for targetAgent resolution.
|
|
1335
|
+
this.emitEvent({
|
|
1336
|
+
eventId: ulid(),
|
|
1337
|
+
type: "message_sent" as MAPEventType,
|
|
1338
|
+
timestamp: Date.now(),
|
|
1339
|
+
agentId: targetAgentId,
|
|
1340
|
+
data: {
|
|
1341
|
+
from: participantId,
|
|
1342
|
+
to: targetAgentId,
|
|
1343
|
+
message: {
|
|
1344
|
+
id: `acp-req-${Date.now()}`,
|
|
1345
|
+
from: participantId,
|
|
1346
|
+
to: targetAgentId,
|
|
1347
|
+
payload: envelope,
|
|
1348
|
+
},
|
|
1349
|
+
},
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1107
1352
|
// Create notification emitter to stream session updates
|
|
1108
1353
|
const emitNotification = (notification: ACPEnvelope) => {
|
|
1109
1354
|
this.emitEvent({
|
|
@@ -1112,6 +1357,8 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
1112
1357
|
timestamp: Date.now(),
|
|
1113
1358
|
agentId: targetAgentId,
|
|
1114
1359
|
data: {
|
|
1360
|
+
from: targetAgentId,
|
|
1361
|
+
to: participantId,
|
|
1115
1362
|
message: {
|
|
1116
1363
|
id: `acp-notif-${Date.now()}`,
|
|
1117
1364
|
from: targetAgentId,
|
|
@@ -1126,32 +1373,77 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
1126
1373
|
acp: acp as ACPEnvelope["acp"],
|
|
1127
1374
|
acpContext: acpContext as ACPEnvelope["acpContext"],
|
|
1128
1375
|
};
|
|
1129
|
-
const responseEnvelope = await this.acpOverMapHandler.processRequest(
|
|
1130
|
-
targetAgentId,
|
|
1131
|
-
acpEnvelope,
|
|
1132
|
-
emitNotification,
|
|
1133
|
-
);
|
|
1134
1376
|
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
timestamp: Date.now(),
|
|
1146
|
-
agentId: targetAgentId, // Must be at top level for subscription matching
|
|
1147
|
-
data: {
|
|
1148
|
-
message: {
|
|
1149
|
-
id: `acp-resp-${Date.now()}`,
|
|
1377
|
+
// Helper to emit the final ACP response to the participant via subscription
|
|
1378
|
+
const emitResponse = (responseEnvelope: ACPEnvelope) => {
|
|
1379
|
+
const participant = this.connections.getParticipant(participantId);
|
|
1380
|
+
if (participant) {
|
|
1381
|
+
this.emitEvent({
|
|
1382
|
+
eventId: ulid(),
|
|
1383
|
+
type: "message_delivered" as MAPEventType,
|
|
1384
|
+
timestamp: Date.now(),
|
|
1385
|
+
agentId: targetAgentId,
|
|
1386
|
+
data: {
|
|
1150
1387
|
from: targetAgentId,
|
|
1151
|
-
|
|
1388
|
+
to: participantId,
|
|
1389
|
+
message: {
|
|
1390
|
+
id: `acp-resp-${Date.now()}`,
|
|
1391
|
+
from: targetAgentId,
|
|
1392
|
+
payload: responseEnvelope,
|
|
1393
|
+
},
|
|
1152
1394
|
},
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
// session/prompt can run for minutes — process it asynchronously so the
|
|
1400
|
+
// map/send RPC returns immediately. The ACP response will arrive via
|
|
1401
|
+
// subscription (message_delivered event) when the prompt finishes.
|
|
1402
|
+
// Other ACP methods (initialize, session/new, session/load, etc.) are
|
|
1403
|
+
// fast and can be awaited normally.
|
|
1404
|
+
const isLongRunning = acp.method === "session/prompt";
|
|
1405
|
+
|
|
1406
|
+
if (isLongRunning) {
|
|
1407
|
+
this.acpOverMapHandler
|
|
1408
|
+
.processRequest(targetAgentId, acpEnvelope, emitNotification)
|
|
1409
|
+
.then((responseEnvelope) => {
|
|
1410
|
+
console.error(
|
|
1411
|
+
`[ACP-over-MAP] Async prompt completed - method=${acp.method}`,
|
|
1412
|
+
);
|
|
1413
|
+
emitResponse(responseEnvelope);
|
|
1414
|
+
})
|
|
1415
|
+
.catch((error) => {
|
|
1416
|
+
console.error(`[ACP-over-MAP] Async prompt error:`, error);
|
|
1417
|
+
// Emit error response so the client's ACP pending request resolves
|
|
1418
|
+
emitResponse({
|
|
1419
|
+
acp: {
|
|
1420
|
+
jsonrpc: "2.0",
|
|
1421
|
+
id: acp.id,
|
|
1422
|
+
error: {
|
|
1423
|
+
code: -32603,
|
|
1424
|
+
message:
|
|
1425
|
+
error instanceof Error ? error.message : String(error),
|
|
1426
|
+
},
|
|
1427
|
+
},
|
|
1428
|
+
acpContext: {
|
|
1429
|
+
streamId: acpContext.streamId,
|
|
1430
|
+
sessionId: acpContext.sessionId ?? null,
|
|
1431
|
+
direction: "agent-to-client",
|
|
1432
|
+
},
|
|
1433
|
+
} as ACPEnvelope);
|
|
1434
|
+
});
|
|
1435
|
+
} else {
|
|
1436
|
+
const responseEnvelope =
|
|
1437
|
+
await this.acpOverMapHandler.processRequest(
|
|
1438
|
+
targetAgentId,
|
|
1439
|
+
acpEnvelope,
|
|
1440
|
+
emitNotification,
|
|
1441
|
+
);
|
|
1442
|
+
|
|
1443
|
+
console.error(
|
|
1444
|
+
`[ACP-over-MAP] Request processed - method=${acp.method}`,
|
|
1445
|
+
);
|
|
1446
|
+
emitResponse(responseEnvelope);
|
|
1155
1447
|
}
|
|
1156
1448
|
|
|
1157
1449
|
return {
|
|
@@ -1181,6 +1473,49 @@ export class MAPAdapterImpl implements MAPAdapter {
|
|
|
1181
1473
|
return { agent: agent ?? null };
|
|
1182
1474
|
}
|
|
1183
1475
|
|
|
1476
|
+
private async handleStopAgent(
|
|
1477
|
+
_participantId: ParticipantId,
|
|
1478
|
+
params: unknown,
|
|
1479
|
+
): Promise<{ stopping: boolean; agent?: AgentInfo }> {
|
|
1480
|
+
const { agentId, reason, force } =
|
|
1481
|
+
(params as {
|
|
1482
|
+
agentId?: AgentId;
|
|
1483
|
+
reason?: string;
|
|
1484
|
+
force?: boolean;
|
|
1485
|
+
}) ?? {};
|
|
1486
|
+
|
|
1487
|
+
if (!agentId) {
|
|
1488
|
+
throw RPCError.invalidParams("agentId required");
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
if (!this.services.agentManager) {
|
|
1492
|
+
throw RPCError.internalError("Agent manager not available");
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
// Abort any active ACP streams for this agent
|
|
1496
|
+
if (this.acpOverMapHandler) {
|
|
1497
|
+
this.acpOverMapHandler.abortStreamsForAgent(agentId);
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// Terminate the agent
|
|
1501
|
+
try {
|
|
1502
|
+
await this.services.agentManager.terminate(
|
|
1503
|
+
agentId,
|
|
1504
|
+
(reason ?? "cancelled") as AgentStopReason,
|
|
1505
|
+
);
|
|
1506
|
+
} catch (error) {
|
|
1507
|
+
console.error(`[MAPAdapter] Error stopping agent ${agentId}:`, error);
|
|
1508
|
+
throw RPCError.internalError(
|
|
1509
|
+
`Failed to stop agent: ${error instanceof Error ? error.message : String(error)}`,
|
|
1510
|
+
);
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
// Note: agent_state_changed and agent_unregistered events are now
|
|
1514
|
+
// emitted by the lifecycle listener (covers all stop paths).
|
|
1515
|
+
|
|
1516
|
+
return { stopping: true };
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1184
1519
|
private async handleListScopes(
|
|
1185
1520
|
participantId: ParticipantId,
|
|
1186
1521
|
): Promise<{ scopes: ScopeInfo[] }> {
|
|
@@ -400,8 +400,12 @@ export class SubscriptionManagerImpl implements SubscriptionManager {
|
|
|
400
400
|
}
|
|
401
401
|
|
|
402
402
|
// Event type filter (OR within array)
|
|
403
|
+
// Normalize between underscore format (SDK: "agent_registered") and
|
|
404
|
+
// dot format (internal: "agent.registered") so subscriptions match
|
|
405
|
+
// regardless of which convention the client uses.
|
|
403
406
|
if (filter.eventTypes && filter.eventTypes.length > 0) {
|
|
404
|
-
|
|
407
|
+
const normalizedEventType = event.type.replace(/\./g, "_");
|
|
408
|
+
if (!filter.eventTypes.some((ft) => ft.replace(/\./g, "_") === normalizedEventType)) {
|
|
405
409
|
return false;
|
|
406
410
|
}
|
|
407
411
|
}
|
package/src/map/adapter/types.ts
CHANGED
|
@@ -88,6 +88,8 @@ export interface ParticipantCapabilities {
|
|
|
88
88
|
canManageTasks?: boolean;
|
|
89
89
|
/** Can manage federation connections (connect/disconnect peers) */
|
|
90
90
|
canManageFederation?: boolean;
|
|
91
|
+
/** Can manage agent lifecycle (resume, spawn, fork, permissions) */
|
|
92
|
+
canManageLifecycle?: boolean;
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
/**
|