macro-agent 0.0.10 → 0.0.12
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/.macro-agent/teams/self-driving/prompts/grinder.md +27 -0
- package/.macro-agent/teams/self-driving/prompts/judge.md +27 -0
- package/.macro-agent/teams/self-driving/prompts/planner.md +33 -0
- package/.macro-agent/teams/self-driving/roles/grinder.yaml +17 -0
- package/.macro-agent/teams/self-driving/roles/judge.yaml +24 -0
- package/.macro-agent/teams/self-driving/roles/planner.yaml +18 -0
- package/.macro-agent/teams/self-driving/team.yaml +103 -0
- package/.macro-agent/teams/structured/prompts/developer.md +26 -0
- package/.macro-agent/teams/structured/prompts/lead.md +25 -0
- package/.macro-agent/teams/structured/prompts/reviewer.md +24 -0
- package/.macro-agent/teams/structured/roles/developer.yaml +12 -0
- package/.macro-agent/teams/structured/roles/lead.yaml +11 -0
- package/.macro-agent/teams/structured/roles/reviewer.yaml +19 -0
- package/.macro-agent/teams/structured/team.yaml +89 -0
- package/.sudocode/issues.jsonl +56 -51
- package/.sudocode/specs.jsonl +8 -1
- package/CLAUDE.md +121 -30
- package/README.md +60 -3
- package/dist/acp/macro-agent.d.ts +4 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +50 -4
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/session-mapper.d.ts +20 -1
- package/dist/acp/session-mapper.d.ts.map +1 -1
- package/dist/acp/session-mapper.js +90 -1
- package/dist/acp/session-mapper.js.map +1 -1
- package/dist/acp/types.d.ts +24 -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 +40 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +172 -8
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +22 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/agent/wake.d.ts +15 -0
- package/dist/agent/wake.d.ts.map +1 -1
- package/dist/agent/wake.js +15 -0
- package/dist/agent/wake.js.map +1 -1
- package/dist/agent-detection/command-builder.d.ts +30 -0
- package/dist/agent-detection/command-builder.d.ts.map +1 -0
- package/dist/agent-detection/command-builder.js +71 -0
- package/dist/agent-detection/command-builder.js.map +1 -0
- package/dist/agent-detection/detector.d.ts +84 -0
- package/dist/agent-detection/detector.d.ts.map +1 -0
- package/dist/agent-detection/detector.js +240 -0
- package/dist/agent-detection/detector.js.map +1 -0
- package/dist/agent-detection/index.d.ts +12 -0
- package/dist/agent-detection/index.d.ts.map +1 -0
- package/dist/agent-detection/index.js +14 -0
- package/dist/agent-detection/index.js.map +1 -0
- package/dist/agent-detection/registry.d.ts +53 -0
- package/dist/agent-detection/registry.d.ts.map +1 -0
- package/dist/agent-detection/registry.js +177 -0
- package/dist/agent-detection/registry.js.map +1 -0
- package/dist/agent-detection/types.d.ts +121 -0
- package/dist/agent-detection/types.d.ts.map +1 -0
- package/dist/agent-detection/types.js +20 -0
- package/dist/agent-detection/types.js.map +1 -0
- package/dist/api/server.d.ts +5 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +362 -0
- package/dist/api/server.js.map +1 -1
- package/dist/api/types.d.ts +50 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/cli/acp.d.ts +2 -0
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +8 -1
- package/dist/cli/acp.js.map +1 -1
- package/dist/cli/index.js +29 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.js +38 -0
- package/dist/cli/mcp.js.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/project-config.d.ts +46 -0
- package/dist/config/project-config.d.ts.map +1 -0
- package/dist/config/project-config.js +68 -0
- package/dist/config/project-config.js.map +1 -0
- package/dist/lifecycle/cascade.d.ts +1 -1
- package/dist/lifecycle/cascade.d.ts.map +1 -1
- package/dist/lifecycle/handlers/index.d.ts +4 -0
- package/dist/lifecycle/handlers/index.d.ts.map +1 -1
- package/dist/lifecycle/handlers/index.js +2 -0
- package/dist/lifecycle/handlers/index.js.map +1 -1
- package/dist/lifecycle/handlers/worker.d.ts +4 -0
- package/dist/lifecycle/handlers/worker.d.ts.map +1 -1
- package/dist/lifecycle/handlers/worker.js +35 -3
- package/dist/lifecycle/handlers/worker.js.map +1 -1
- package/dist/mail/conversation-map.d.ts +33 -0
- package/dist/mail/conversation-map.d.ts.map +1 -0
- package/dist/mail/conversation-map.js +61 -0
- package/dist/mail/conversation-map.js.map +1 -0
- package/dist/mail/index.d.ts +11 -0
- package/dist/mail/index.d.ts.map +1 -0
- package/dist/mail/index.js +11 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/mail/mail-service.d.ts +85 -0
- package/dist/mail/mail-service.d.ts.map +1 -0
- package/dist/mail/mail-service.js +121 -0
- package/dist/mail/mail-service.js.map +1 -0
- package/dist/mail/stores/eventstore-conversation-store.d.ts +40 -0
- package/dist/mail/stores/eventstore-conversation-store.d.ts.map +1 -0
- package/dist/mail/stores/eventstore-conversation-store.js +131 -0
- package/dist/mail/stores/eventstore-conversation-store.js.map +1 -0
- package/dist/mail/stores/eventstore-participant-store.d.ts +43 -0
- package/dist/mail/stores/eventstore-participant-store.d.ts.map +1 -0
- package/dist/mail/stores/eventstore-participant-store.js +145 -0
- package/dist/mail/stores/eventstore-participant-store.js.map +1 -0
- package/dist/mail/stores/eventstore-thread-store.d.ts +46 -0
- package/dist/mail/stores/eventstore-thread-store.d.ts.map +1 -0
- package/dist/mail/stores/eventstore-thread-store.js +118 -0
- package/dist/mail/stores/eventstore-thread-store.js.map +1 -0
- package/dist/mail/stores/eventstore-turn-store.d.ts +47 -0
- package/dist/mail/stores/eventstore-turn-store.d.ts.map +1 -0
- package/dist/mail/stores/eventstore-turn-store.js +153 -0
- package/dist/mail/stores/eventstore-turn-store.js.map +1 -0
- package/dist/mail/stores/index.d.ts +12 -0
- package/dist/mail/stores/index.d.ts.map +1 -0
- package/dist/mail/stores/index.js +12 -0
- package/dist/mail/stores/index.js.map +1 -0
- package/dist/mail/stores/types.d.ts +146 -0
- package/dist/mail/stores/types.d.ts.map +1 -0
- package/dist/mail/stores/types.js +13 -0
- package/dist/mail/stores/types.js.map +1 -0
- package/dist/mail/turn-recorder.d.ts +30 -0
- package/dist/mail/turn-recorder.d.ts.map +1 -0
- package/dist/mail/turn-recorder.js +98 -0
- package/dist/mail/turn-recorder.js.map +1 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +32 -2
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/adapter/event-translator.d.ts.map +1 -1
- package/dist/map/adapter/event-translator.js +4 -0
- package/dist/map/adapter/event-translator.js.map +1 -1
- package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
- package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-detection.js +91 -0
- package/dist/map/adapter/extensions/agent-detection.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 +39 -0
- package/dist/map/adapter/extensions/index.js.map +1 -1
- package/dist/map/adapter/extensions/resume.d.ts +47 -0
- package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
- package/dist/map/adapter/extensions/resume.js +59 -0
- package/dist/map/adapter/extensions/resume.js.map +1 -0
- package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
- package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
- package/dist/map/adapter/extensions/workspace-files.js +338 -0
- package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
- package/dist/map/adapter/mail-handler-adapter.d.ts +27 -0
- package/dist/map/adapter/mail-handler-adapter.d.ts.map +1 -0
- package/dist/map/adapter/mail-handler-adapter.js +292 -0
- package/dist/map/adapter/mail-handler-adapter.js.map +1 -0
- package/dist/map/adapter/map-adapter.d.ts +34 -10
- package/dist/map/adapter/map-adapter.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.js +110 -14
- package/dist/map/adapter/map-adapter.js.map +1 -1
- package/dist/map/adapter/rpc-handler.d.ts +4 -1
- package/dist/map/adapter/rpc-handler.d.ts.map +1 -1
- package/dist/map/adapter/rpc-handler.js +6 -0
- package/dist/map/adapter/rpc-handler.js.map +1 -1
- package/dist/map/index.d.ts +1 -0
- package/dist/map/index.d.ts.map +1 -1
- package/dist/map/index.js +2 -0
- package/dist/map/index.js.map +1 -1
- package/dist/map/types.d.ts +3 -1
- package/dist/map/types.d.ts.map +1 -1
- package/dist/map/types.js.map +1 -1
- package/dist/mcp/mcp-server.d.ts +6 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +45 -0
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/tools/claim_task.d.ts +35 -0
- package/dist/mcp/tools/claim_task.d.ts.map +1 -0
- package/dist/mcp/tools/claim_task.js +58 -0
- package/dist/mcp/tools/claim_task.js.map +1 -0
- package/dist/mcp/tools/done.d.ts +15 -2
- package/dist/mcp/tools/done.d.ts.map +1 -1
- package/dist/mcp/tools/done.js +45 -10
- package/dist/mcp/tools/done.js.map +1 -1
- package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
- package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
- package/dist/mcp/tools/list_claimable_tasks.js +63 -0
- package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
- package/dist/mcp/tools/unclaim_task.d.ts +31 -0
- package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
- package/dist/mcp/tools/unclaim_task.js +47 -0
- package/dist/mcp/tools/unclaim_task.js.map +1 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +2 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/metrics.d.ts +79 -0
- package/dist/metrics/metrics.d.ts.map +1 -0
- package/dist/metrics/metrics.js +166 -0
- package/dist/metrics/metrics.js.map +1 -0
- package/dist/roles/capabilities.d.ts +1 -0
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +3 -0
- package/dist/roles/capabilities.js.map +1 -1
- package/dist/roles/types.d.ts +1 -1
- package/dist/roles/types.d.ts.map +1 -1
- package/dist/router/channels.d.ts +2 -4
- package/dist/router/channels.d.ts.map +1 -1
- package/dist/router/channels.js.map +1 -1
- package/dist/router/message-router.d.ts +85 -9
- package/dist/router/message-router.d.ts.map +1 -1
- package/dist/router/message-router.js +203 -14
- package/dist/router/message-router.js.map +1 -1
- package/dist/router/role-resolver.d.ts +10 -1
- package/dist/router/role-resolver.d.ts.map +1 -1
- package/dist/router/role-resolver.js +15 -1
- package/dist/router/role-resolver.js.map +1 -1
- package/dist/router/types.d.ts +30 -1
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/types.js.map +1 -1
- package/dist/server/combined-server.d.ts +6 -0
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +24 -2
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.d.ts +14 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +456 -4
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +1 -1
- package/dist/store/types/agents.d.ts.map +1 -1
- package/dist/store/types/conversations.d.ts +91 -0
- package/dist/store/types/conversations.d.ts.map +1 -0
- package/dist/store/types/conversations.js +8 -0
- package/dist/store/types/conversations.js.map +1 -0
- package/dist/store/types/events.d.ts +1 -1
- package/dist/store/types/events.d.ts.map +1 -1
- package/dist/store/types/events.js.map +1 -1
- package/dist/store/types/index.d.ts +2 -0
- package/dist/store/types/index.d.ts.map +1 -1
- package/dist/store/types/index.js +2 -0
- package/dist/store/types/index.js.map +1 -1
- package/dist/store/types/sessions.d.ts +44 -0
- package/dist/store/types/sessions.d.ts.map +1 -0
- package/dist/store/types/sessions.js +9 -0
- package/dist/store/types/sessions.js.map +1 -0
- package/dist/store/types/tasks.d.ts +2 -0
- package/dist/store/types/tasks.d.ts.map +1 -1
- package/dist/task/backend/memory.d.ts +4 -1
- package/dist/task/backend/memory.d.ts.map +1 -1
- package/dist/task/backend/memory.js +81 -0
- package/dist/task/backend/memory.js.map +1 -1
- package/dist/task/backend/types.d.ts +30 -0
- package/dist/task/backend/types.d.ts.map +1 -1
- package/dist/task/backend/types.js.map +1 -1
- package/dist/teams/index.d.ts +4 -0
- package/dist/teams/index.d.ts.map +1 -0
- package/dist/teams/index.js +4 -0
- package/dist/teams/index.js.map +1 -0
- package/dist/teams/team-loader.d.ts +20 -0
- package/dist/teams/team-loader.d.ts.map +1 -0
- package/dist/teams/team-loader.js +293 -0
- package/dist/teams/team-loader.js.map +1 -0
- package/dist/teams/team-runtime.d.ts +139 -0
- package/dist/teams/team-runtime.d.ts.map +1 -0
- package/dist/teams/team-runtime.js +613 -0
- package/dist/teams/team-runtime.js.map +1 -0
- package/dist/teams/types.d.ts +266 -0
- package/dist/teams/types.d.ts.map +1 -0
- package/dist/teams/types.js +20 -0
- package/dist/teams/types.js.map +1 -0
- package/dist/trigger/router/trigger-router.d.ts +30 -3
- package/dist/trigger/router/trigger-router.d.ts.map +1 -1
- package/dist/trigger/router/trigger-router.js +30 -3
- package/dist/trigger/router/trigger-router.js.map +1 -1
- package/dist/trigger/wake/types.d.ts +31 -5
- package/dist/trigger/wake/types.d.ts.map +1 -1
- package/dist/trigger/wake/types.js +19 -0
- package/dist/trigger/wake/types.js.map +1 -1
- package/dist/workspace/dataplane-adapter.d.ts +1 -1
- package/dist/workspace/dataplane-adapter.d.ts.map +1 -1
- package/dist/workspace/dataplane-adapter.js +1 -1
- package/dist/workspace/dataplane-adapter.js.map +1 -1
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/strategies/index.d.ts +6 -0
- package/dist/workspace/strategies/index.d.ts.map +1 -0
- package/dist/workspace/strategies/index.js +5 -0
- package/dist/workspace/strategies/index.js.map +1 -0
- package/dist/workspace/strategies/optimistic.d.ts +26 -0
- package/dist/workspace/strategies/optimistic.d.ts.map +1 -0
- package/dist/workspace/strategies/optimistic.js +121 -0
- package/dist/workspace/strategies/optimistic.js.map +1 -0
- package/dist/workspace/strategies/queue.d.ts +26 -0
- package/dist/workspace/strategies/queue.d.ts.map +1 -0
- package/dist/workspace/strategies/queue.js +67 -0
- package/dist/workspace/strategies/queue.js.map +1 -0
- package/dist/workspace/strategies/registry.d.ts +37 -0
- package/dist/workspace/strategies/registry.d.ts.map +1 -0
- package/dist/workspace/strategies/registry.js +63 -0
- package/dist/workspace/strategies/registry.js.map +1 -0
- package/dist/workspace/strategies/trunk.d.ts +20 -0
- package/dist/workspace/strategies/trunk.d.ts.map +1 -0
- package/dist/workspace/strategies/trunk.js +108 -0
- package/dist/workspace/strategies/trunk.js.map +1 -0
- package/dist/workspace/strategies/types.d.ts +104 -0
- package/dist/workspace/strategies/types.d.ts.map +1 -0
- package/dist/workspace/strategies/types.js +11 -0
- package/dist/workspace/strategies/types.js.map +1 -0
- package/dist/workspace/types.d.ts +1 -1
- package/dist/workspace/types.d.ts.map +1 -1
- package/dist/workspace/workspace-manager.d.ts +1 -1
- package/dist/workspace/workspace-manager.d.ts.map +1 -1
- package/docs/implementation-details.md +1127 -0
- package/docs/implementation-summary.md +448 -0
- package/docs/mail-integration.md +608 -0
- package/docs/plan-self-driving-support.md +433 -0
- package/docs/spec-self-driving-support.md +462 -0
- package/docs/team-templates.md +860 -0
- package/docs/teams.md +233 -0
- package/package.json +5 -3
- package/src/acp/__tests__/integration.test.ts +161 -1
- package/src/acp/__tests__/macro-agent.test.ts +95 -0
- package/src/acp/__tests__/session-persistence.test.ts +276 -0
- package/src/acp/macro-agent.ts +79 -7
- package/src/acp/session-mapper.ts +108 -1
- package/src/acp/types.ts +33 -1
- package/src/agent/agent-manager.ts +278 -6
- package/src/agent/types.ts +27 -0
- package/src/agent/wake.ts +15 -0
- package/src/agent-detection/__tests__/command-builder.test.ts +336 -0
- package/src/agent-detection/__tests__/detector.test.ts +768 -0
- package/src/agent-detection/__tests__/registry.test.ts +254 -0
- package/src/agent-detection/command-builder.ts +90 -0
- package/src/agent-detection/detector.ts +307 -0
- package/src/agent-detection/index.ts +36 -0
- package/src/agent-detection/registry.ts +200 -0
- package/src/agent-detection/types.ts +184 -0
- package/src/api/__tests__/conversation-api.test.ts +468 -0
- package/src/api/server.ts +425 -1
- package/src/api/types.ts +64 -1
- package/src/cli/acp.ts +9 -1
- package/src/cli/index.ts +44 -0
- package/src/cli/mcp.ts +47 -0
- package/src/config/index.ts +9 -0
- package/src/config/project-config.ts +107 -0
- package/src/lifecycle/cascade.ts +1 -1
- package/src/lifecycle/handlers/index.ts +8 -0
- package/src/lifecycle/handlers/worker.ts +48 -3
- package/src/mail/__tests__/conversation-lifecycle.test.ts +409 -0
- package/src/mail/__tests__/eventstore-stores.test.ts +1073 -0
- package/src/mail/__tests__/mail-full-agent.e2e.test.ts +575 -0
- package/src/mail/__tests__/mail-integration.test.ts +759 -0
- package/src/mail/__tests__/mail-map-protocol.e2e.test.ts +1068 -0
- package/src/mail/__tests__/mail-service.test.ts +506 -0
- package/src/mail/__tests__/turn-recorder.test.ts +328 -0
- package/src/mail/conversation-map.ts +107 -0
- package/src/mail/index.ts +25 -0
- package/src/mail/mail-service.ts +257 -0
- package/src/mail/stores/eventstore-conversation-store.ts +146 -0
- package/src/mail/stores/eventstore-participant-store.ts +172 -0
- package/src/mail/stores/eventstore-thread-store.ts +129 -0
- package/src/mail/stores/eventstore-turn-store.ts +173 -0
- package/src/mail/stores/index.ts +12 -0
- package/src/mail/stores/types.ts +160 -0
- package/src/mail/turn-recorder.ts +124 -0
- package/src/map/README.md +79 -0
- package/src/map/adapter/__tests__/extensions.test.ts +359 -0
- package/src/map/adapter/__tests__/map-adapter.test.ts +90 -0
- package/src/map/adapter/__tests__/workspace-files.test.ts +673 -0
- package/src/map/adapter/acp-over-map.ts +45 -2
- package/src/map/adapter/event-translator.ts +4 -0
- package/src/map/adapter/extensions/agent-detection.ts +201 -0
- package/src/map/adapter/extensions/index.ts +63 -0
- package/src/map/adapter/extensions/resume.ts +114 -0
- package/src/map/adapter/extensions/workspace-files.ts +449 -0
- package/src/map/adapter/mail-handler-adapter.ts +429 -0
- package/src/map/adapter/map-adapter.ts +173 -27
- package/src/map/adapter/rpc-handler.ts +8 -1
- package/src/map/index.ts +3 -0
- package/src/map/types.ts +3 -1
- package/src/mcp/mcp-server.ts +67 -0
- package/src/mcp/tools/claim_task.ts +86 -0
- package/src/mcp/tools/done.ts +59 -10
- package/src/mcp/tools/list_claimable_tasks.ts +93 -0
- package/src/mcp/tools/unclaim_task.ts +71 -0
- package/src/metrics/index.ts +9 -0
- package/src/metrics/metrics.ts +280 -0
- package/src/roles/capabilities.ts +3 -0
- package/src/roles/types.ts +2 -1
- package/src/router/README.md +120 -0
- package/src/router/__tests__/message-router.test.ts +561 -0
- package/src/router/channels.ts +3 -4
- package/src/router/message-router.ts +308 -22
- package/src/router/role-resolver.ts +22 -1
- package/src/router/types.ts +36 -1
- package/src/server/combined-server.ts +36 -2
- package/src/store/README.md +134 -0
- package/src/store/event-store.ts +546 -3
- package/src/store/types/agents.ts +1 -1
- package/src/store/types/conversations.ts +129 -0
- package/src/store/types/events.ts +5 -1
- package/src/store/types/index.ts +2 -0
- package/src/store/types/sessions.ts +53 -0
- package/src/store/types/tasks.ts +3 -0
- package/src/task/backend/memory.ts +116 -0
- package/src/task/backend/types.ts +43 -0
- package/src/teams/__tests__/cross-subsystem.integration.test.ts +983 -0
- package/src/teams/__tests__/e2e/team-runtime.e2e.test.ts +553 -0
- package/src/teams/__tests__/team-system.test.ts +1280 -0
- package/src/teams/index.ts +13 -0
- package/src/teams/team-loader.ts +434 -0
- package/src/teams/team-runtime.ts +727 -0
- package/src/teams/types.ts +377 -0
- package/src/trigger/router/trigger-router.ts +30 -3
- package/src/trigger/wake/types.ts +32 -5
- package/src/trigger/wake/wake-manager.ts +2 -2
- package/src/workspace/dataplane-adapter.ts +1 -1
- package/src/workspace/index.ts +1 -1
- package/src/workspace/strategies/index.ts +18 -0
- package/src/workspace/strategies/optimistic.ts +136 -0
- package/src/workspace/strategies/queue.ts +81 -0
- package/src/workspace/strategies/registry.ts +89 -0
- package/src/workspace/strategies/trunk.ts +123 -0
- package/src/workspace/strategies/types.ts +145 -0
- package/src/workspace/types.ts +1 -1
- package/src/workspace/workspace-manager.ts +1 -1
- package/.claude/settings.local.json +0 -59
- package/dist/map/utils/address-translation.d.ts +0 -99
- package/dist/map/utils/address-translation.d.ts.map +0 -1
- package/dist/map/utils/address-translation.js +0 -285
- package/dist/map/utils/address-translation.js.map +0 -1
- package/dist/map/utils/index.d.ts +0 -7
- package/dist/map/utils/index.d.ts.map +0 -1
- package/dist/map/utils/index.js +0 -7
- package/dist/map/utils/index.js.map +0 -1
- package/openspec/AGENTS.md +0 -456
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/design.md +0 -128
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/proposal.md +0 -49
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/agent-manager/spec.md +0 -150
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/cli-api/spec.md +0 -258
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/event-store/spec.md +0 -160
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/mcp-tools/spec.md +0 -224
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/message-router/spec.md +0 -153
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/task-manager/spec.md +0 -136
- package/openspec/changes/archive/2025-12-21-add-mvp-foundation/tasks.md +0 -147
- package/openspec/project.md +0 -31
- package/openspec/specs/agent-manager/spec.md +0 -154
- package/openspec/specs/cli-api/spec.md +0 -262
- package/openspec/specs/event-store/spec.md +0 -164
- package/openspec/specs/mcp-tools/spec.md +0 -228
- package/openspec/specs/message-router/spec.md +0 -157
- package/openspec/specs/task-manager/spec.md +0 -140
- package/references/acp-factory-ref/CHANGELOG.md +0 -33
- package/references/acp-factory-ref/LICENSE +0 -21
- package/references/acp-factory-ref/README.md +0 -341
- package/references/acp-factory-ref/package-lock.json +0 -3102
- package/references/acp-factory-ref/package.json +0 -96
- package/references/acp-factory-ref/python/CHANGELOG.md +0 -33
- package/references/acp-factory-ref/python/LICENSE +0 -21
- package/references/acp-factory-ref/python/Makefile +0 -57
- package/references/acp-factory-ref/python/README.md +0 -253
- package/references/acp-factory-ref/python/pyproject.toml +0 -73
- package/references/acp-factory-ref/python/tests/__init__.py +0 -0
- package/references/acp-factory-ref/python/tests/e2e/__init__.py +0 -1
- package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +0 -349
- package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +0 -165
- package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +0 -296
- package/references/acp-factory-ref/python/tests/test_client_handler.py +0 -543
- package/references/acp-factory-ref/python/tests/test_pushable.py +0 -199
- package/references/claude-code-acp/.github/workflows/ci.yml +0 -45
- package/references/claude-code-acp/.github/workflows/publish.yml +0 -34
- package/references/claude-code-acp/.prettierrc.json +0 -4
- package/references/claude-code-acp/CHANGELOG.md +0 -249
- package/references/claude-code-acp/LICENSE +0 -222
- package/references/claude-code-acp/README.md +0 -53
- package/references/claude-code-acp/docs/RELEASES.md +0 -24
- package/references/claude-code-acp/eslint.config.js +0 -48
- package/references/claude-code-acp/package-lock.json +0 -4570
- package/references/claude-code-acp/package.json +0 -88
- package/references/claude-code-acp/scripts/release.sh +0 -119
- package/references/claude-code-acp/src/acp-agent.ts +0 -2065
- package/references/claude-code-acp/src/index.ts +0 -26
- package/references/claude-code-acp/src/lib.ts +0 -38
- package/references/claude-code-acp/src/mcp-server.ts +0 -911
- package/references/claude-code-acp/src/settings.ts +0 -522
- package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +0 -5
- package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +0 -6
- package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +0 -479
- package/references/claude-code-acp/src/tests/acp-agent.test.ts +0 -1502
- package/references/claude-code-acp/src/tests/extract-lines.test.ts +0 -103
- package/references/claude-code-acp/src/tests/fork-session.test.ts +0 -335
- package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +0 -334
- package/references/claude-code-acp/src/tests/settings.test.ts +0 -617
- package/references/claude-code-acp/src/tests/skills-options.test.ts +0 -187
- package/references/claude-code-acp/src/tests/tools.test.ts +0 -318
- package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +0 -558
- package/references/claude-code-acp/src/tools.ts +0 -819
- package/references/claude-code-acp/src/utils.ts +0 -171
- package/references/claude-code-acp/tsconfig.json +0 -18
- package/references/claude-code-acp/vitest.config.ts +0 -19
- package/references/multi-agent-protocol/.sudocode/issues.jsonl +0 -82
- package/references/multi-agent-protocol/.sudocode/specs.jsonl +0 -9
- package/references/multi-agent-protocol/LICENSE +0 -21
- package/references/multi-agent-protocol/README.md +0 -113
- package/references/multi-agent-protocol/docs/00-design-specification.md +0 -460
- package/references/multi-agent-protocol/docs/01-open-questions.md +0 -1050
- package/references/multi-agent-protocol/docs/02-wire-protocol.md +0 -296
- package/references/multi-agent-protocol/docs/03-streaming-semantics.md +0 -252
- package/references/multi-agent-protocol/docs/04-error-handling.md +0 -231
- package/references/multi-agent-protocol/docs/05-connection-model.md +0 -244
- package/references/multi-agent-protocol/docs/06-visibility-permissions.md +0 -243
- package/references/multi-agent-protocol/docs/07-federation.md +0 -259
- package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +0 -253
- package/references/multi-agent-protocol/package-lock.json +0 -3239
- package/references/multi-agent-protocol/package.json +0 -56
- package/references/multi-agent-protocol/schema/meta.json +0 -337
- package/references/multi-agent-protocol/schema/schema.json +0 -1828
|
@@ -1,13 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MessageRouter -
|
|
2
|
+
* MessageRouter - Core Internal Message Routing Service
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* ## Routing Architecture
|
|
5
|
+
*
|
|
6
|
+
* MessageRouter is the **core internal routing authority** for macro-agent.
|
|
7
|
+
* It handles all message delivery between internal agents.
|
|
8
|
+
*
|
|
9
|
+
* ```
|
|
10
|
+
* External → MAPAdapter/TriggerRouter → MessageRouter → EventStore
|
|
11
|
+
* (protocol translation) (routing logic) (persistence)
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* **Three routing entry points exist:**
|
|
15
|
+
*
|
|
16
|
+
* 1. **MessageRouter** (this module)
|
|
17
|
+
* - Internal routing for agent-to-agent communication
|
|
18
|
+
* - Supports: send(), sendToAddress(), emitStatus()
|
|
19
|
+
* - Used by: AgentManager, MCP tools, internal components
|
|
20
|
+
*
|
|
21
|
+
* 2. **MAPAdapter** (src/map/adapter/)
|
|
22
|
+
* - External MAP protocol interface for clients/agents/gateways
|
|
23
|
+
* - Translates MAP protocol → internal routing
|
|
24
|
+
* - Delegates message delivery to MessageRouter
|
|
25
|
+
*
|
|
26
|
+
* 3. **TriggerRouter** (src/trigger/router/)
|
|
27
|
+
* - External event routing (webhooks, cron, system events)
|
|
28
|
+
* - Queues events for batch delivery
|
|
29
|
+
* - Uses WakeManager for delivery scheduling
|
|
30
|
+
*
|
|
31
|
+
* ## Supported Routing Methods
|
|
32
|
+
*
|
|
33
|
+
* **Legacy Channel-based** (send, sendMessage):
|
|
34
|
+
* - Direct agent, task, topic, lineage, subtree, broadcast
|
|
35
|
+
*
|
|
36
|
+
* **MAP Address-based** (sendToAddress):
|
|
37
|
+
* - Agent, agents, task, scope, role, broadcast, hierarchical, federated
|
|
38
|
+
*
|
|
39
|
+
* @module router/message-router
|
|
11
40
|
*/
|
|
12
41
|
|
|
13
42
|
import { nanoid } from "nanoid";
|
|
@@ -35,6 +64,7 @@ import type {
|
|
|
35
64
|
SendToAddressRequest,
|
|
36
65
|
AddressSendResult,
|
|
37
66
|
Address,
|
|
67
|
+
TurnRecorderCallback,
|
|
38
68
|
} from "./types.js";
|
|
39
69
|
import { RoutingError, AddressRoutingError, DEFAULT_TRUNCATION_CONFIG } from "./types.js";
|
|
40
70
|
import {
|
|
@@ -62,6 +92,7 @@ import {
|
|
|
62
92
|
isFederatedAddress,
|
|
63
93
|
describeAddress,
|
|
64
94
|
} from "../map/types.js";
|
|
95
|
+
import type { DeliveryHint, HierarchicalAddress } from "../map/types.js";
|
|
65
96
|
import type { FederationHandler } from "../map/federation/types.js";
|
|
66
97
|
import { getSystemFromAddress } from "../map/federation/federation-handler.js";
|
|
67
98
|
import {
|
|
@@ -166,8 +197,68 @@ export interface MessageRouter {
|
|
|
166
197
|
* - Optionally subscribes parent to agent's subtree
|
|
167
198
|
*/
|
|
168
199
|
setupDefaultSubscriptions(options: DefaultSubscriptionOptions): void;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Set turn recorder for conversation tracking.
|
|
203
|
+
* Called after direct message (agent/task address) delivery.
|
|
204
|
+
* Supports late binding since mail services may be created after router.
|
|
205
|
+
*/
|
|
206
|
+
setTurnRecorder(recorder: TurnRecorderCallback): void;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Set signal filter for status notification delivery.
|
|
210
|
+
* Called before delivering each status notification — return false to suppress.
|
|
211
|
+
* Supports late binding since TeamRuntime is created after router.
|
|
212
|
+
*/
|
|
213
|
+
setSignalFilter(filter: SignalFilter): void;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Set emission validator for outbound status events.
|
|
217
|
+
* Called before emitting a status event — can reject, warn, or audit.
|
|
218
|
+
* Supports late binding since TeamRuntime is created after router.
|
|
219
|
+
*/
|
|
220
|
+
setEmissionValidator(validator: EmissionValidator): void;
|
|
169
221
|
}
|
|
170
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Signal filter callback for status notification delivery.
|
|
225
|
+
* Return true to deliver, false to suppress.
|
|
226
|
+
*
|
|
227
|
+
* @param from - Agent emitting the status
|
|
228
|
+
* @param to - Agent that would receive the notification
|
|
229
|
+
* @param signal - Signal name from details.signal (undefined if not tagged)
|
|
230
|
+
*/
|
|
231
|
+
export type SignalFilter = (
|
|
232
|
+
from: AgentId,
|
|
233
|
+
to: AgentId,
|
|
234
|
+
signal: string | undefined
|
|
235
|
+
) => boolean;
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Emission validator result.
|
|
239
|
+
* - "allow": emit normally
|
|
240
|
+
* - "reject": block the emission (strict mode)
|
|
241
|
+
* - "warn": log warning but allow (permissive mode)
|
|
242
|
+
* - "audit": record audit event but allow (audit mode)
|
|
243
|
+
*/
|
|
244
|
+
export type EmissionValidatorResult = {
|
|
245
|
+
action: "allow" | "reject" | "warn" | "audit";
|
|
246
|
+
message?: string;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Emission validator callback for outbound status events.
|
|
251
|
+
* Called with the emitting agent's ID and the signal name.
|
|
252
|
+
* Returns an action to take (allow, reject, warn, audit).
|
|
253
|
+
*
|
|
254
|
+
* @param agentId - Agent emitting the status
|
|
255
|
+
* @param signal - Signal name from details.signal (undefined if not tagged)
|
|
256
|
+
*/
|
|
257
|
+
export type EmissionValidator = (
|
|
258
|
+
agentId: AgentId,
|
|
259
|
+
signal: string | undefined
|
|
260
|
+
) => EmissionValidatorResult;
|
|
261
|
+
|
|
171
262
|
/**
|
|
172
263
|
* Callback invoked when a message determines a wake action
|
|
173
264
|
*/
|
|
@@ -223,6 +314,15 @@ export function createMessageRouter(
|
|
|
223
314
|
const wakeHandler = config.wakeHandler;
|
|
224
315
|
const federationHandler = config.federationHandler;
|
|
225
316
|
|
|
317
|
+
// Turn recorder for conversation tracking (late-bound)
|
|
318
|
+
let turnRecorder: TurnRecorderCallback | undefined;
|
|
319
|
+
|
|
320
|
+
// Signal filter for status notification delivery (late-bound)
|
|
321
|
+
let signalFilter: SignalFilter | undefined;
|
|
322
|
+
|
|
323
|
+
// Emission validator for outbound status events (late-bound)
|
|
324
|
+
let emissionValidator: EmissionValidator | undefined;
|
|
325
|
+
|
|
226
326
|
// Track acknowledged messages: Map<agentId, Set<messageId>>
|
|
227
327
|
const acknowledgedMessages = new Map<AgentId, Set<EventId>>();
|
|
228
328
|
|
|
@@ -323,7 +423,7 @@ export function createMessageRouter(
|
|
|
323
423
|
if (sessionChecker && wakeHandler) {
|
|
324
424
|
const decision = getWakeDecisionWithHint(
|
|
325
425
|
to.agent,
|
|
326
|
-
{ priority: priority as MessagePriority, deliveryHint: delivery as
|
|
426
|
+
{ priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
|
|
327
427
|
sessionChecker
|
|
328
428
|
);
|
|
329
429
|
if (decision.shouldWake || decision.shouldInterrupt) {
|
|
@@ -333,6 +433,15 @@ export function createMessageRouter(
|
|
|
333
433
|
|
|
334
434
|
delivered.push(to.agent);
|
|
335
435
|
|
|
436
|
+
// Record turn for conversation tracking
|
|
437
|
+
if (turnRecorder) {
|
|
438
|
+
try {
|
|
439
|
+
turnRecorder({ from, toAgent: to.agent, content, messageId: event.id, addressType: "agent" });
|
|
440
|
+
} catch {
|
|
441
|
+
// Never fail delivery due to turn recording
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
336
445
|
return {
|
|
337
446
|
id: event.id,
|
|
338
447
|
from,
|
|
@@ -392,7 +501,7 @@ export function createMessageRouter(
|
|
|
392
501
|
if (sessionChecker && wakeHandler) {
|
|
393
502
|
const decision = getWakeDecisionWithHint(
|
|
394
503
|
targetAgentId,
|
|
395
|
-
{ priority: priority as MessagePriority, deliveryHint: delivery as
|
|
504
|
+
{ priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
|
|
396
505
|
sessionChecker
|
|
397
506
|
);
|
|
398
507
|
if (decision.shouldWake || decision.shouldInterrupt) {
|
|
@@ -402,6 +511,15 @@ export function createMessageRouter(
|
|
|
402
511
|
|
|
403
512
|
delivered.push(targetAgentId);
|
|
404
513
|
|
|
514
|
+
// Record turn for conversation tracking
|
|
515
|
+
if (turnRecorder) {
|
|
516
|
+
try {
|
|
517
|
+
turnRecorder({ from, toAgent: targetAgentId, content, messageId: event.id, addressType: "task" });
|
|
518
|
+
} catch {
|
|
519
|
+
// Never fail delivery due to turn recording
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
405
523
|
return {
|
|
406
524
|
id: event.id,
|
|
407
525
|
from,
|
|
@@ -451,7 +569,7 @@ export function createMessageRouter(
|
|
|
451
569
|
if (sessionChecker && wakeHandler) {
|
|
452
570
|
const decision = getWakeDecisionWithHint(
|
|
453
571
|
subscriberId,
|
|
454
|
-
{ priority: priority as MessagePriority, deliveryHint: delivery as
|
|
572
|
+
{ priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
|
|
455
573
|
sessionChecker
|
|
456
574
|
);
|
|
457
575
|
if (decision.shouldWake || decision.shouldInterrupt) {
|
|
@@ -478,11 +596,16 @@ export function createMessageRouter(
|
|
|
478
596
|
const agentSource: RoleAgentSource = {
|
|
479
597
|
listAgents: () => eventStore.listAgents(),
|
|
480
598
|
getAgent: (id) => eventStore.getAgent(id),
|
|
599
|
+
// Get agents subscribed to a scope/topic
|
|
600
|
+
getScopeMembers: (scope) => {
|
|
601
|
+
return eventStore.getSubscribers({ type: "topic", target: scope });
|
|
602
|
+
},
|
|
481
603
|
};
|
|
482
604
|
|
|
483
605
|
const recipientIds = resolveRoleTarget(agentSource, {
|
|
484
606
|
role: to.role,
|
|
485
|
-
|
|
607
|
+
// RoleAddress.within is a ScopeId (subscription-based), not a coordinatorId (hierarchy-based)
|
|
608
|
+
scope: to.within,
|
|
486
609
|
});
|
|
487
610
|
|
|
488
611
|
if (recipientIds.length === 0) {
|
|
@@ -537,7 +660,7 @@ export function createMessageRouter(
|
|
|
537
660
|
if (sessionChecker && wakeHandler) {
|
|
538
661
|
const decision = getWakeDecisionWithHint(
|
|
539
662
|
recipientId,
|
|
540
|
-
{ priority: priority as MessagePriority, deliveryHint: delivery as
|
|
663
|
+
{ priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
|
|
541
664
|
sessionChecker
|
|
542
665
|
);
|
|
543
666
|
if (decision.shouldWake || decision.shouldInterrupt) {
|
|
@@ -610,7 +733,7 @@ export function createMessageRouter(
|
|
|
610
733
|
if (sessionChecker && wakeHandler) {
|
|
611
734
|
const decision = getWakeDecisionWithHint(
|
|
612
735
|
recipientId,
|
|
613
|
-
{ priority: priority as MessagePriority, deliveryHint: delivery as
|
|
736
|
+
{ priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
|
|
614
737
|
sessionChecker
|
|
615
738
|
);
|
|
616
739
|
if (decision.shouldWake || decision.shouldInterrupt) {
|
|
@@ -676,7 +799,7 @@ export function createMessageRouter(
|
|
|
676
799
|
|
|
677
800
|
// Resolve the hierarchical address
|
|
678
801
|
const resolved = resolveHierarchicalAddress(
|
|
679
|
-
to as
|
|
802
|
+
to as HierarchicalAddress,
|
|
680
803
|
from,
|
|
681
804
|
hierarchySource
|
|
682
805
|
);
|
|
@@ -735,7 +858,7 @@ export function createMessageRouter(
|
|
|
735
858
|
recipientId,
|
|
736
859
|
{
|
|
737
860
|
priority: priority as MessagePriority,
|
|
738
|
-
deliveryHint: delivery as
|
|
861
|
+
deliveryHint: delivery as DeliveryHint | undefined,
|
|
739
862
|
},
|
|
740
863
|
sessionChecker
|
|
741
864
|
);
|
|
@@ -865,6 +988,36 @@ export function createMessageRouter(
|
|
|
865
988
|
function emitStatus(request: EmitStatusRequest): void {
|
|
866
989
|
const { from, status_type, summary, details } = request;
|
|
867
990
|
|
|
991
|
+
// Check emission restrictions if validator installed
|
|
992
|
+
if (emissionValidator) {
|
|
993
|
+
const signal = (details as Record<string, unknown> | undefined)?.signal as string | undefined;
|
|
994
|
+
const result = emissionValidator(from.agent_id, signal);
|
|
995
|
+
|
|
996
|
+
if (result.action === "reject") {
|
|
997
|
+
// Strict mode: block the emission entirely
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
if (result.action === "audit") {
|
|
1002
|
+
// Audit mode: record audit event, then continue with emission
|
|
1003
|
+
eventStore.emit({
|
|
1004
|
+
type: "status",
|
|
1005
|
+
source: { agent_id: "system" },
|
|
1006
|
+
payload: {
|
|
1007
|
+
status_type: "discovery",
|
|
1008
|
+
summary: result.message ?? `Emission audit: agent ${from.agent_id} emitted signal '${signal}'`,
|
|
1009
|
+
audit: {
|
|
1010
|
+
type: "emission_violation",
|
|
1011
|
+
agent_id: from.agent_id,
|
|
1012
|
+
signal,
|
|
1013
|
+
status_type,
|
|
1014
|
+
},
|
|
1015
|
+
},
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
// "warn" and "allow" proceed normally (warning is logged by the validator installer)
|
|
1019
|
+
}
|
|
1020
|
+
|
|
868
1021
|
// Emit status event to event store
|
|
869
1022
|
const event = eventStore.emit({
|
|
870
1023
|
type: "status",
|
|
@@ -879,15 +1032,20 @@ export function createMessageRouter(
|
|
|
879
1032
|
},
|
|
880
1033
|
});
|
|
881
1034
|
|
|
882
|
-
|
|
883
|
-
routeStatusToSubtreeSubscribers(from.agent_id, {
|
|
1035
|
+
const statusNotification: StatusNotification = {
|
|
884
1036
|
agent_id: from.agent_id,
|
|
885
1037
|
task_id: from.task_id,
|
|
886
1038
|
status_type,
|
|
887
1039
|
summary,
|
|
888
1040
|
details,
|
|
889
1041
|
timestamp: event.timestamp,
|
|
890
|
-
}
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
// Route to subtree subscribers (hierarchical: parents/ancestors)
|
|
1045
|
+
const subtreeRecipients = routeStatusToSubtreeSubscribers(from.agent_id, statusNotification);
|
|
1046
|
+
|
|
1047
|
+
// Route to topic co-subscribers (non-hierarchical: peers sharing topics)
|
|
1048
|
+
routeStatusToTopicSubscribers(from.agent_id, statusNotification, subtreeRecipients);
|
|
891
1049
|
}
|
|
892
1050
|
|
|
893
1051
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -1024,13 +1182,15 @@ export function createMessageRouter(
|
|
|
1024
1182
|
/**
|
|
1025
1183
|
* Route status event to subtree subscribers.
|
|
1026
1184
|
* Parents who have subscribed to an agent's subtree receive status notifications.
|
|
1185
|
+
* Returns the set of agents that were notified (for dedup with topic routing).
|
|
1027
1186
|
*/
|
|
1028
1187
|
function routeStatusToSubtreeSubscribers(
|
|
1029
1188
|
agentId: AgentId,
|
|
1030
1189
|
status: StatusNotification
|
|
1031
|
-
):
|
|
1190
|
+
): Set<AgentId> {
|
|
1191
|
+
const notified = new Set<AgentId>();
|
|
1032
1192
|
const agent = eventStore.getAgent(agentId);
|
|
1033
|
-
if (!agent) return;
|
|
1193
|
+
if (!agent) return notified;
|
|
1034
1194
|
|
|
1035
1195
|
// Find all agents with subtree subscription that includes this agent
|
|
1036
1196
|
// This includes:
|
|
@@ -1064,17 +1224,25 @@ export function createMessageRouter(
|
|
|
1064
1224
|
}
|
|
1065
1225
|
}
|
|
1066
1226
|
|
|
1227
|
+
// Extract signal name from details (if tagged)
|
|
1228
|
+
const statusSignal = (status.details as Record<string, unknown> | undefined)?.signal as string | undefined;
|
|
1229
|
+
|
|
1067
1230
|
// Send status notification to each subscriber
|
|
1068
1231
|
for (const subscriberId of agentsToNotify) {
|
|
1069
1232
|
// Skip self-notification
|
|
1070
1233
|
if (subscriberId === agentId) continue;
|
|
1071
1234
|
|
|
1235
|
+
// Apply signal filter if installed
|
|
1236
|
+
if (signalFilter && !signalFilter(agentId, subscriberId, statusSignal)) {
|
|
1237
|
+
continue;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1072
1240
|
const statusContent = JSON.stringify({
|
|
1073
1241
|
type: "status_notification",
|
|
1074
1242
|
...status,
|
|
1075
1243
|
});
|
|
1076
1244
|
|
|
1077
|
-
eventStore.emit({
|
|
1245
|
+
const event = eventStore.emit({
|
|
1078
1246
|
type: "message",
|
|
1079
1247
|
source: {
|
|
1080
1248
|
agent_id: agentId,
|
|
@@ -1087,7 +1255,122 @@ export function createMessageRouter(
|
|
|
1087
1255
|
via: "subtree",
|
|
1088
1256
|
},
|
|
1089
1257
|
});
|
|
1258
|
+
|
|
1259
|
+
// Wake sleeping agents on status notifications
|
|
1260
|
+
if (sessionChecker && wakeHandler) {
|
|
1261
|
+
try {
|
|
1262
|
+
const decision = getWakeDecisionWithHint(
|
|
1263
|
+
subscriberId,
|
|
1264
|
+
{ priority: "normal" as MessagePriority },
|
|
1265
|
+
sessionChecker
|
|
1266
|
+
);
|
|
1267
|
+
if (decision.shouldWake || decision.shouldInterrupt) {
|
|
1268
|
+
wakeHandler(subscriberId, decision, event.id);
|
|
1269
|
+
}
|
|
1270
|
+
} catch {
|
|
1271
|
+
// Never fail status delivery due to wake errors
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
notified.add(subscriberId);
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
return notified;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* Route status event to topic co-subscribers.
|
|
1283
|
+
* Agents sharing topic subscriptions with the emitting agent receive status notifications.
|
|
1284
|
+
* This enables non-hierarchical visibility: peers on the same topic see each other's status.
|
|
1285
|
+
* Skips agents already notified via subtree routing to avoid duplicates.
|
|
1286
|
+
*/
|
|
1287
|
+
function routeStatusToTopicSubscribers(
|
|
1288
|
+
agentId: AgentId,
|
|
1289
|
+
status: StatusNotification,
|
|
1290
|
+
alreadyNotified: Set<AgentId>
|
|
1291
|
+
): void {
|
|
1292
|
+
// Find all topics the emitting agent is subscribed to
|
|
1293
|
+
const subscriptions = eventStore.getSubscriptions(agentId);
|
|
1294
|
+
const topicSubscriptions = subscriptions.filter(
|
|
1295
|
+
(s) => s.type === "topic"
|
|
1296
|
+
);
|
|
1297
|
+
|
|
1298
|
+
if (topicSubscriptions.length === 0) return;
|
|
1299
|
+
|
|
1300
|
+
// Collect unique recipients across all shared topics
|
|
1301
|
+
const topicRecipients = new Set<AgentId>();
|
|
1302
|
+
for (const sub of topicSubscriptions) {
|
|
1303
|
+
const subscribers = eventStore.getSubscribers({
|
|
1304
|
+
type: "topic",
|
|
1305
|
+
target: sub.target,
|
|
1306
|
+
});
|
|
1307
|
+
for (const subscriberId of subscribers) {
|
|
1308
|
+
// Skip self and already-notified (from subtree routing)
|
|
1309
|
+
if (subscriberId !== agentId && !alreadyNotified.has(subscriberId)) {
|
|
1310
|
+
topicRecipients.add(subscriberId);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1090
1313
|
}
|
|
1314
|
+
|
|
1315
|
+
if (topicRecipients.size === 0) return;
|
|
1316
|
+
|
|
1317
|
+
// Extract signal name from details (if tagged)
|
|
1318
|
+
const statusSignal = (status.details as Record<string, unknown> | undefined)?.signal as string | undefined;
|
|
1319
|
+
|
|
1320
|
+
const statusContent = JSON.stringify({
|
|
1321
|
+
type: "status_notification",
|
|
1322
|
+
...status,
|
|
1323
|
+
});
|
|
1324
|
+
|
|
1325
|
+
// Deliver to each topic co-subscriber
|
|
1326
|
+
for (const recipientId of topicRecipients) {
|
|
1327
|
+
// Apply signal filter if installed
|
|
1328
|
+
if (signalFilter && !signalFilter(agentId, recipientId, statusSignal)) {
|
|
1329
|
+
continue;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
const event = eventStore.emit({
|
|
1333
|
+
type: "message",
|
|
1334
|
+
source: {
|
|
1335
|
+
agent_id: agentId,
|
|
1336
|
+
},
|
|
1337
|
+
target: {
|
|
1338
|
+
agent_id: recipientId,
|
|
1339
|
+
},
|
|
1340
|
+
payload: {
|
|
1341
|
+
content: statusContent,
|
|
1342
|
+
via: "topic",
|
|
1343
|
+
},
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
// Wake sleeping agents on status notifications
|
|
1347
|
+
if (sessionChecker && wakeHandler) {
|
|
1348
|
+
try {
|
|
1349
|
+
const decision = getWakeDecisionWithHint(
|
|
1350
|
+
recipientId,
|
|
1351
|
+
{ priority: "normal" as MessagePriority },
|
|
1352
|
+
sessionChecker
|
|
1353
|
+
);
|
|
1354
|
+
if (decision.shouldWake || decision.shouldInterrupt) {
|
|
1355
|
+
wakeHandler(recipientId, decision, event.id);
|
|
1356
|
+
}
|
|
1357
|
+
} catch {
|
|
1358
|
+
// Never fail status delivery due to wake errors
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
function setTurnRecorder(recorder: TurnRecorderCallback): void {
|
|
1365
|
+
turnRecorder = recorder;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
function setSignalFilter(filter: SignalFilter): void {
|
|
1369
|
+
signalFilter = filter;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
function setEmissionValidator(validator: EmissionValidator): void {
|
|
1373
|
+
emissionValidator = validator;
|
|
1091
1374
|
}
|
|
1092
1375
|
|
|
1093
1376
|
return {
|
|
@@ -1102,5 +1385,8 @@ export function createMessageRouter(
|
|
|
1102
1385
|
getSubscriptions,
|
|
1103
1386
|
getSubscribers,
|
|
1104
1387
|
setupDefaultSubscriptions,
|
|
1388
|
+
setTurnRecorder,
|
|
1389
|
+
setSignalFilter,
|
|
1390
|
+
setEmissionValidator,
|
|
1105
1391
|
};
|
|
1106
1392
|
}
|
|
@@ -31,6 +31,11 @@ export interface RoleAgentInfo {
|
|
|
31
31
|
export interface RoleAgentSource {
|
|
32
32
|
listAgents(): RoleAgentInfo[];
|
|
33
33
|
getAgent(agentId: AgentId): RoleAgentInfo | null;
|
|
34
|
+
/**
|
|
35
|
+
* Optional: Get agents subscribed to a scope/topic.
|
|
36
|
+
* Used when filtering by scope membership.
|
|
37
|
+
*/
|
|
38
|
+
getScopeMembers?(scope: string): AgentId[];
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
// =============================================================================
|
|
@@ -90,8 +95,12 @@ export function getSubtreeIds(
|
|
|
90
95
|
/**
|
|
91
96
|
* Resolve a role channel to recipient agent IDs.
|
|
92
97
|
*
|
|
98
|
+
* Supports two filtering mechanisms (can be combined):
|
|
99
|
+
* - coordinatorId: Filter to agents within a coordinator's subtree (hierarchy-based)
|
|
100
|
+
* - scope: Filter to agents that are members of a scope (subscription-based)
|
|
101
|
+
*
|
|
93
102
|
* @param agentSource - Source for listing/getting agents
|
|
94
|
-
* @param target - Role target with role name and optional
|
|
103
|
+
* @param target - Role target with role name and optional filters
|
|
95
104
|
* @returns Array of agent IDs for fan-out delivery
|
|
96
105
|
*/
|
|
97
106
|
export function resolveRoleTarget(
|
|
@@ -106,6 +115,13 @@ export function resolveRoleTarget(
|
|
|
106
115
|
subtreeIds = getSubtreeIds(target.coordinatorId, agentSource);
|
|
107
116
|
}
|
|
108
117
|
|
|
118
|
+
// Get scope member IDs if scope filtering is requested
|
|
119
|
+
let scopeMemberIds: Set<AgentId> | null = null;
|
|
120
|
+
if (target.scope && agentSource.getScopeMembers) {
|
|
121
|
+
const members = agentSource.getScopeMembers(target.scope);
|
|
122
|
+
scopeMemberIds = new Set(members);
|
|
123
|
+
}
|
|
124
|
+
|
|
109
125
|
return agents
|
|
110
126
|
.filter((agent) => {
|
|
111
127
|
// Only include running agents
|
|
@@ -123,6 +139,11 @@ export function resolveRoleTarget(
|
|
|
123
139
|
return false;
|
|
124
140
|
}
|
|
125
141
|
|
|
142
|
+
// If scope filtering, check if agent is a scope member
|
|
143
|
+
if (scopeMemberIds && !scopeMemberIds.has(agent.id)) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
126
147
|
return true;
|
|
127
148
|
})
|
|
128
149
|
.map((agent) => agent.id);
|
package/src/router/types.ts
CHANGED
|
@@ -39,8 +39,16 @@ export type BroadcastScope = "all" | "coordinators" | "workers" | "monitors";
|
|
|
39
39
|
export interface RoleTarget {
|
|
40
40
|
/** Role name to target (e.g., "worker", "integrator", "monitor") */
|
|
41
41
|
role: string;
|
|
42
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Optional: Filter to agents within a coordinator's subtree (hierarchy-based).
|
|
44
|
+
* Agents must be descendants of the specified coordinator.
|
|
45
|
+
*/
|
|
43
46
|
coordinatorId?: AgentId;
|
|
47
|
+
/**
|
|
48
|
+
* Optional: Filter to agents that are members of a scope (subscription-based).
|
|
49
|
+
* Requires EventStore scope/topic membership lookup.
|
|
50
|
+
*/
|
|
51
|
+
scope?: string;
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
// Message sender identification
|
|
@@ -266,6 +274,33 @@ export class AddressRoutingError extends Error {
|
|
|
266
274
|
}
|
|
267
275
|
}
|
|
268
276
|
|
|
277
|
+
// =============================================================================
|
|
278
|
+
// Turn Recording
|
|
279
|
+
// =============================================================================
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Information passed to a turn recorder callback.
|
|
283
|
+
* Only agent and task addresses produce turns.
|
|
284
|
+
*/
|
|
285
|
+
export interface TurnRecordInfo {
|
|
286
|
+
/** Sending agent ID */
|
|
287
|
+
from: AgentId;
|
|
288
|
+
/** Receiving agent ID (resolved for task addresses) */
|
|
289
|
+
toAgent: AgentId;
|
|
290
|
+
/** Message content */
|
|
291
|
+
content: string;
|
|
292
|
+
/** Event ID of the emitted message event */
|
|
293
|
+
messageId: EventId;
|
|
294
|
+
/** Type of address that was sent to */
|
|
295
|
+
addressType: "agent" | "task";
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Callback invoked when a direct message (agent or task address) is sent.
|
|
300
|
+
* Used to record the message as a conversation turn.
|
|
301
|
+
*/
|
|
302
|
+
export type TurnRecorderCallback = (info: TurnRecordInfo) => void;
|
|
303
|
+
|
|
269
304
|
// Re-export Address and related types for convenience
|
|
270
305
|
export type { Address, SendOptions, DeliveryHint };
|
|
271
306
|
export { MAPMessagePriority };
|
|
@@ -31,6 +31,9 @@ import {
|
|
|
31
31
|
} from "../map/adapter/index.js";
|
|
32
32
|
import type { Agent, AgentId } from "../store/types/index.js";
|
|
33
33
|
import type { Address, SendOptions } from "../map/types.js";
|
|
34
|
+
import { createMailService, type MailService } from "../mail/mail-service.js";
|
|
35
|
+
import { createConversationMap, type ConversationMap } from "../mail/conversation-map.js";
|
|
36
|
+
import { createTurnRecorder } from "../mail/turn-recorder.js";
|
|
34
37
|
|
|
35
38
|
// ─────────────────────────────────────────────────────────────────
|
|
36
39
|
// Types
|
|
@@ -91,6 +94,12 @@ export interface CombinedServer {
|
|
|
91
94
|
|
|
92
95
|
/** MAP adapter (for testing) */
|
|
93
96
|
readonly mapAdapter?: MAPAdapter;
|
|
97
|
+
|
|
98
|
+
/** Mail service (for conversation tracking) */
|
|
99
|
+
readonly mailService?: MailService;
|
|
100
|
+
|
|
101
|
+
/** Conversation map (for agent-to-conversation tracking) */
|
|
102
|
+
readonly conversationMap?: ConversationMap;
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -179,8 +188,30 @@ export function createCombinedServer(
|
|
|
179
188
|
disableMap = false,
|
|
180
189
|
} = config;
|
|
181
190
|
|
|
182
|
-
//
|
|
183
|
-
const
|
|
191
|
+
// Set up mail service and conversation map (always created, independent of MAP)
|
|
192
|
+
const mailService = createMailService({ eventStore: services.eventStore });
|
|
193
|
+
const conversationMap = createConversationMap();
|
|
194
|
+
|
|
195
|
+
// Wire mail services into AgentManager for conversation lifecycle
|
|
196
|
+
if (services.agentManager.setMailServices) {
|
|
197
|
+
services.agentManager.setMailServices(mailService, conversationMap);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Wire turn recorder into MessageRouter for automatic turn tracking
|
|
201
|
+
if (services.messageRouter.setTurnRecorder) {
|
|
202
|
+
const turnRecorder = createTurnRecorder({
|
|
203
|
+
mailService,
|
|
204
|
+
conversationMap,
|
|
205
|
+
eventStore: services.eventStore,
|
|
206
|
+
});
|
|
207
|
+
services.messageRouter.setTurnRecorder(turnRecorder);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Create Express app with API routes (include mail services)
|
|
211
|
+
const app = createAPIApp(
|
|
212
|
+
{ ...services, mailService, conversationMap },
|
|
213
|
+
{ cors }
|
|
214
|
+
);
|
|
184
215
|
|
|
185
216
|
// Create HTTP server with Express
|
|
186
217
|
const httpServer = http.createServer(app);
|
|
@@ -203,6 +234,7 @@ export function createCombinedServer(
|
|
|
203
234
|
const mapServices = {
|
|
204
235
|
...createMAPServices(services),
|
|
205
236
|
defaultCwd,
|
|
237
|
+
mailService,
|
|
206
238
|
};
|
|
207
239
|
mapAdapter = createMAPAdapter(
|
|
208
240
|
{ name: "macro-agent", version: "1.0.0" },
|
|
@@ -326,5 +358,7 @@ export function createCombinedServer(
|
|
|
326
358
|
httpServer,
|
|
327
359
|
app,
|
|
328
360
|
mapAdapter,
|
|
361
|
+
mailService,
|
|
362
|
+
conversationMap,
|
|
329
363
|
};
|
|
330
364
|
}
|