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
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MailService — Central facade for mail conversation tracking.
|
|
3
|
+
*
|
|
4
|
+
* Provides conversation lifecycle management, turn recording,
|
|
5
|
+
* and participant tracking backed by EventStore materialized views.
|
|
6
|
+
*
|
|
7
|
+
* Since the MAP SDK server module is not importable, this implements
|
|
8
|
+
* the business logic directly rather than delegating to SDK managers.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { nanoid } from "nanoid";
|
|
12
|
+
import type { EventStore } from "../store/event-store.js";
|
|
13
|
+
import type {
|
|
14
|
+
Conversation,
|
|
15
|
+
ConversationTurn,
|
|
16
|
+
ConversationParticipant,
|
|
17
|
+
ConversationFilter,
|
|
18
|
+
TurnFilter,
|
|
19
|
+
ConversationType,
|
|
20
|
+
ConversationStatus,
|
|
21
|
+
ConversationChangeCallback,
|
|
22
|
+
TurnChangeCallback,
|
|
23
|
+
} from "../store/types/index.js";
|
|
24
|
+
import type { Unsubscribe } from "../store/event-store.js";
|
|
25
|
+
import {
|
|
26
|
+
EventStoreConversationStore,
|
|
27
|
+
EventStoreTurnStore,
|
|
28
|
+
EventStoreThreadStore,
|
|
29
|
+
EventStoreParticipantStore,
|
|
30
|
+
type ConversationStore,
|
|
31
|
+
type TurnStore,
|
|
32
|
+
type ThreadStore,
|
|
33
|
+
type ParticipantStore,
|
|
34
|
+
} from "./stores/index.js";
|
|
35
|
+
|
|
36
|
+
// =============================================================================
|
|
37
|
+
// Types
|
|
38
|
+
// =============================================================================
|
|
39
|
+
|
|
40
|
+
export interface CreateConversationOptions {
|
|
41
|
+
type: ConversationType;
|
|
42
|
+
subject?: string;
|
|
43
|
+
createdBy: string;
|
|
44
|
+
parentConversationId?: string;
|
|
45
|
+
metadata?: Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface RecordTurnOptions {
|
|
49
|
+
conversationId: string;
|
|
50
|
+
participant: string;
|
|
51
|
+
contentType: string;
|
|
52
|
+
content: unknown;
|
|
53
|
+
threadId?: string;
|
|
54
|
+
inReplyTo?: string;
|
|
55
|
+
sourceType?: "explicit" | "intercepted";
|
|
56
|
+
sourceMessageId?: string;
|
|
57
|
+
metadata?: Record<string, unknown>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface CloseConversationOptions {
|
|
61
|
+
conversationId: string;
|
|
62
|
+
closedBy: string;
|
|
63
|
+
reason?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface JoinConversationOptions {
|
|
67
|
+
conversationId: string;
|
|
68
|
+
participantId: string;
|
|
69
|
+
participantType?: "user" | "agent" | "system";
|
|
70
|
+
role?: string;
|
|
71
|
+
agentId?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface MailServiceConfig {
|
|
75
|
+
eventStore: EventStore;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// MailService Interface
|
|
80
|
+
// =============================================================================
|
|
81
|
+
|
|
82
|
+
export interface MailService {
|
|
83
|
+
/** Create a new conversation. */
|
|
84
|
+
createConversation(opts: CreateConversationOptions): { conversationId: string };
|
|
85
|
+
|
|
86
|
+
/** Record a turn in a conversation. */
|
|
87
|
+
recordTurn(opts: RecordTurnOptions): { turnId: string };
|
|
88
|
+
|
|
89
|
+
/** Close a conversation. */
|
|
90
|
+
closeConversation(opts: CloseConversationOptions): void;
|
|
91
|
+
|
|
92
|
+
/** Join a participant to a conversation. */
|
|
93
|
+
joinConversation(opts: JoinConversationOptions): void;
|
|
94
|
+
|
|
95
|
+
/** Remove a participant from a conversation. */
|
|
96
|
+
leaveConversation(conversationId: string, participantId: string): void;
|
|
97
|
+
|
|
98
|
+
/** Get a conversation by ID. */
|
|
99
|
+
getConversation(id: string): Conversation | null;
|
|
100
|
+
|
|
101
|
+
/** List conversations with optional filter. */
|
|
102
|
+
listConversations(filter?: ConversationFilter): Conversation[];
|
|
103
|
+
|
|
104
|
+
/** List turns for a conversation. */
|
|
105
|
+
listTurns(filter: TurnFilter): ConversationTurn[];
|
|
106
|
+
|
|
107
|
+
/** List participants for a conversation. */
|
|
108
|
+
listParticipants(conversationId: string, active?: boolean): ConversationParticipant[];
|
|
109
|
+
|
|
110
|
+
/** Count turns in a conversation. */
|
|
111
|
+
countTurns(conversationId: string, threadId?: string): number;
|
|
112
|
+
|
|
113
|
+
/** Subscribe to conversation changes. */
|
|
114
|
+
onConversationChange(callback: ConversationChangeCallback): Unsubscribe;
|
|
115
|
+
|
|
116
|
+
/** Subscribe to turn changes. */
|
|
117
|
+
onTurnChange(callback: TurnChangeCallback): Unsubscribe;
|
|
118
|
+
|
|
119
|
+
/** Access to underlying stores for MAP handler integration. */
|
|
120
|
+
readonly stores: {
|
|
121
|
+
conversations: ConversationStore;
|
|
122
|
+
turns: TurnStore;
|
|
123
|
+
threads: ThreadStore;
|
|
124
|
+
participants: ParticipantStore;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// =============================================================================
|
|
129
|
+
// Implementation
|
|
130
|
+
// =============================================================================
|
|
131
|
+
|
|
132
|
+
export function createMailService(config: MailServiceConfig): MailService {
|
|
133
|
+
const { eventStore } = config;
|
|
134
|
+
|
|
135
|
+
// Create EventStore-backed stores
|
|
136
|
+
const conversationStore = new EventStoreConversationStore(eventStore);
|
|
137
|
+
const turnStore = new EventStoreTurnStore(eventStore);
|
|
138
|
+
const threadStore = new EventStoreThreadStore(eventStore);
|
|
139
|
+
const participantStore = new EventStoreParticipantStore(eventStore);
|
|
140
|
+
|
|
141
|
+
function createConversation(
|
|
142
|
+
opts: CreateConversationOptions
|
|
143
|
+
): { conversationId: string } {
|
|
144
|
+
const conversationId = `conv_${nanoid(12)}`;
|
|
145
|
+
|
|
146
|
+
eventStore.emit({
|
|
147
|
+
type: "conversation",
|
|
148
|
+
source: { agent_id: opts.createdBy },
|
|
149
|
+
payload: {
|
|
150
|
+
action: "created",
|
|
151
|
+
conversation_id: conversationId,
|
|
152
|
+
conversation_type: opts.type,
|
|
153
|
+
subject: opts.subject,
|
|
154
|
+
parent_conversation_id: opts.parentConversationId,
|
|
155
|
+
metadata: opts.metadata,
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return { conversationId };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function recordTurn(opts: RecordTurnOptions): { turnId: string } {
|
|
163
|
+
const conv = eventStore.getConversation(opts.conversationId);
|
|
164
|
+
if (!conv) {
|
|
165
|
+
throw new Error(`Cannot record turn: conversation not found: ${opts.conversationId}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const turnId = `turn_${nanoid(12)}`;
|
|
169
|
+
|
|
170
|
+
eventStore.emit({
|
|
171
|
+
type: "turn",
|
|
172
|
+
source: { agent_id: opts.participant },
|
|
173
|
+
payload: {
|
|
174
|
+
action: "recorded",
|
|
175
|
+
turn_id: turnId,
|
|
176
|
+
conversation_id: opts.conversationId,
|
|
177
|
+
participant: opts.participant,
|
|
178
|
+
content_type: opts.contentType,
|
|
179
|
+
content: opts.content,
|
|
180
|
+
thread_id: opts.threadId,
|
|
181
|
+
in_reply_to: opts.inReplyTo,
|
|
182
|
+
source_type: opts.sourceType ?? "explicit",
|
|
183
|
+
source_message_id: opts.sourceMessageId,
|
|
184
|
+
metadata: opts.metadata,
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return { turnId };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function closeConversation(opts: CloseConversationOptions): void {
|
|
192
|
+
eventStore.emit({
|
|
193
|
+
type: "conversation",
|
|
194
|
+
source: { agent_id: opts.closedBy },
|
|
195
|
+
payload: {
|
|
196
|
+
action: "closed",
|
|
197
|
+
conversation_id: opts.conversationId,
|
|
198
|
+
closed_by: opts.closedBy,
|
|
199
|
+
close_reason: opts.reason ?? "completed",
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function joinConversation(opts: JoinConversationOptions): void {
|
|
205
|
+
eventStore.emit({
|
|
206
|
+
type: "conversation",
|
|
207
|
+
source: { agent_id: opts.participantId },
|
|
208
|
+
payload: {
|
|
209
|
+
action: "participant_joined",
|
|
210
|
+
conversation_id: opts.conversationId,
|
|
211
|
+
participant_id: opts.participantId,
|
|
212
|
+
participant_type: opts.participantType ?? "agent",
|
|
213
|
+
participant_role: opts.role ?? "worker",
|
|
214
|
+
agent_id: opts.agentId,
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function leaveConversation(
|
|
220
|
+
conversationId: string,
|
|
221
|
+
participantId: string
|
|
222
|
+
): void {
|
|
223
|
+
eventStore.emit({
|
|
224
|
+
type: "conversation",
|
|
225
|
+
source: { agent_id: participantId },
|
|
226
|
+
payload: {
|
|
227
|
+
action: "participant_left",
|
|
228
|
+
conversation_id: conversationId,
|
|
229
|
+
participant_id: participantId,
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
createConversation,
|
|
236
|
+
recordTurn,
|
|
237
|
+
closeConversation,
|
|
238
|
+
joinConversation,
|
|
239
|
+
leaveConversation,
|
|
240
|
+
getConversation: (id) => eventStore.getConversation(id),
|
|
241
|
+
listConversations: (filter) => eventStore.listConversations(filter),
|
|
242
|
+
listTurns: (filter) => eventStore.listTurns(filter),
|
|
243
|
+
listParticipants: (conversationId, active) =>
|
|
244
|
+
eventStore.listParticipants(conversationId, active),
|
|
245
|
+
countTurns: (conversationId, threadId) =>
|
|
246
|
+
turnStore.count(conversationId, threadId),
|
|
247
|
+
onConversationChange: (callback) =>
|
|
248
|
+
eventStore.onConversationChange(callback),
|
|
249
|
+
onTurnChange: (callback) => eventStore.onTurnChange(callback),
|
|
250
|
+
stores: {
|
|
251
|
+
conversations: conversationStore,
|
|
252
|
+
turns: turnStore,
|
|
253
|
+
threads: threadStore,
|
|
254
|
+
participants: participantStore,
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventStore-backed ConversationStore adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements the MAP-compatible ConversationStore interface by:
|
|
5
|
+
* - save() → emits a `conversation` event with action `created` or `updated`
|
|
6
|
+
* - get()/list() → reads from EventStore materialized views
|
|
7
|
+
* - delete() → not supported (conversations are closed, not deleted)
|
|
8
|
+
*
|
|
9
|
+
* All state is derived from the EventStore event log — this adapter
|
|
10
|
+
* is a thin translation layer between MAP server types and EventStore.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { EventStore } from "../../store/event-store.js";
|
|
14
|
+
import type {
|
|
15
|
+
ConversationStore,
|
|
16
|
+
ServerConversation,
|
|
17
|
+
MAPConversationFilter,
|
|
18
|
+
} from "./types.js";
|
|
19
|
+
import type { Conversation, ConversationFilter } from "../../store/types/index.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Convert internal Conversation to MAP ServerConversation.
|
|
23
|
+
*/
|
|
24
|
+
function toServerConversation(conv: Conversation): ServerConversation {
|
|
25
|
+
return {
|
|
26
|
+
id: conv.id,
|
|
27
|
+
type: conv.type,
|
|
28
|
+
status: conv.status,
|
|
29
|
+
subject: conv.subject,
|
|
30
|
+
participantCount: conv.participantCount,
|
|
31
|
+
parentConversationId: conv.parentConversationId,
|
|
32
|
+
createdAt: conv.createdAt,
|
|
33
|
+
updatedAt: conv.updatedAt,
|
|
34
|
+
closedAt: conv.closedAt,
|
|
35
|
+
createdBy: conv.createdBy,
|
|
36
|
+
metadata: conv.metadata ?? {},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class EventStoreConversationStore implements ConversationStore {
|
|
41
|
+
constructor(private readonly eventStore: EventStore) {}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Save a conversation by emitting a conversation event.
|
|
45
|
+
* If the conversation already exists, emits an update.
|
|
46
|
+
*/
|
|
47
|
+
save(conversation: ServerConversation): void {
|
|
48
|
+
const existing = this.eventStore.getConversation(conversation.id);
|
|
49
|
+
|
|
50
|
+
if (existing) {
|
|
51
|
+
// Update: emit a conversation event with action "updated"
|
|
52
|
+
// For now we handle status changes (e.g., closing)
|
|
53
|
+
if (existing.status !== conversation.status && (conversation.status === "completed" || conversation.status === "failed")) {
|
|
54
|
+
this.eventStore.emit({
|
|
55
|
+
type: "conversation",
|
|
56
|
+
source: { agent_id: conversation.createdBy },
|
|
57
|
+
payload: {
|
|
58
|
+
action: "closed",
|
|
59
|
+
conversation_id: conversation.id,
|
|
60
|
+
closed_by: conversation.createdBy,
|
|
61
|
+
close_reason: conversation.status,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
// Create: emit conversation created event
|
|
67
|
+
this.eventStore.emit({
|
|
68
|
+
type: "conversation",
|
|
69
|
+
source: { agent_id: conversation.createdBy },
|
|
70
|
+
payload: {
|
|
71
|
+
action: "created",
|
|
72
|
+
conversation_id: conversation.id,
|
|
73
|
+
conversation_type: conversation.type,
|
|
74
|
+
subject: conversation.subject,
|
|
75
|
+
parent_conversation_id: conversation.parentConversationId,
|
|
76
|
+
metadata: conversation.metadata,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get a conversation by ID.
|
|
84
|
+
*/
|
|
85
|
+
get(id: string): ServerConversation | undefined {
|
|
86
|
+
const conv = this.eventStore.getConversation(id);
|
|
87
|
+
return conv ? toServerConversation(conv) : undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* List conversations matching filter criteria.
|
|
92
|
+
*/
|
|
93
|
+
list(filter?: MAPConversationFilter): ServerConversation[] {
|
|
94
|
+
// Translate MAP filter to internal filter
|
|
95
|
+
const internalFilter: ConversationFilter | undefined = filter
|
|
96
|
+
? {
|
|
97
|
+
// MAP uses arrays for type/status, internal uses single values
|
|
98
|
+
// Use first value if provided
|
|
99
|
+
type: filter.type?.[0] as Conversation["type"] | undefined,
|
|
100
|
+
status: filter.status?.[0] as Conversation["status"] | undefined,
|
|
101
|
+
participantId: filter.participantId,
|
|
102
|
+
parentConversationId: filter.parentConversationId,
|
|
103
|
+
}
|
|
104
|
+
: undefined;
|
|
105
|
+
|
|
106
|
+
const conversations = this.eventStore.listConversations(internalFilter);
|
|
107
|
+
|
|
108
|
+
// Apply additional MAP-specific filters not in internal filter
|
|
109
|
+
let results = conversations.map(toServerConversation);
|
|
110
|
+
|
|
111
|
+
if (filter) {
|
|
112
|
+
// Multi-value type filter
|
|
113
|
+
if (filter.type && filter.type.length > 1) {
|
|
114
|
+
results = results.filter((c) => filter.type!.includes(c.type));
|
|
115
|
+
}
|
|
116
|
+
// Multi-value status filter
|
|
117
|
+
if (filter.status && filter.status.length > 1) {
|
|
118
|
+
results = results.filter((c) => filter.status!.includes(c.status));
|
|
119
|
+
}
|
|
120
|
+
// Timestamp range filters
|
|
121
|
+
if (filter.createdAfter !== undefined) {
|
|
122
|
+
results = results.filter((c) => c.createdAt > filter.createdAfter!);
|
|
123
|
+
}
|
|
124
|
+
if (filter.createdBefore !== undefined) {
|
|
125
|
+
results = results.filter((c) => c.createdAt < filter.createdBefore!);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return results;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Delete a conversation. Not supported — conversations are closed, not deleted.
|
|
134
|
+
* Returns false as no deletion occurs.
|
|
135
|
+
*/
|
|
136
|
+
delete(_id: string): boolean {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Clear all conversations. Not supported — EventStore is append-only.
|
|
142
|
+
*/
|
|
143
|
+
clear(): void {
|
|
144
|
+
// No-op: EventStore is append-only, views are rebuilt on replay
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventStore-backed ParticipantStore adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements the MAP-compatible ParticipantStore interface by:
|
|
5
|
+
* - save() → emits conversation events with action `participant_joined`
|
|
6
|
+
* - get()/list() → reads from EventStore materialized views
|
|
7
|
+
* - Bidirectional lookup: conversation→participants and participant→conversations
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { EventStore } from "../../store/event-store.js";
|
|
11
|
+
import type {
|
|
12
|
+
ParticipantStore,
|
|
13
|
+
ServerParticipant,
|
|
14
|
+
MAPParticipantFilter,
|
|
15
|
+
} from "./types.js";
|
|
16
|
+
import type { ConversationParticipant } from "../../store/types/index.js";
|
|
17
|
+
|
|
18
|
+
/** Default permissions for participants. */
|
|
19
|
+
const DEFAULT_PERMISSIONS: ServerParticipant["permissions"] = {
|
|
20
|
+
canSend: true,
|
|
21
|
+
canObserve: true,
|
|
22
|
+
canInvite: false,
|
|
23
|
+
canRemove: false,
|
|
24
|
+
canCreateThreads: true,
|
|
25
|
+
historyAccess: "full",
|
|
26
|
+
canSeeInternal: false,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Convert internal ConversationParticipant to MAP ServerParticipant.
|
|
31
|
+
*/
|
|
32
|
+
function toServerParticipant(p: ConversationParticipant): ServerParticipant {
|
|
33
|
+
return {
|
|
34
|
+
id: p.id,
|
|
35
|
+
conversationId: p.conversationId,
|
|
36
|
+
type: p.type,
|
|
37
|
+
role: p.role,
|
|
38
|
+
joinedAt: p.joinedAt,
|
|
39
|
+
leftAt: p.leftAt,
|
|
40
|
+
permissions: DEFAULT_PERMISSIONS,
|
|
41
|
+
agentInfo: p.agentId ? { agentId: p.agentId } : undefined,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class EventStoreParticipantStore implements ParticipantStore {
|
|
46
|
+
constructor(private readonly eventStore: EventStore) {}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Save a participant by emitting a conversation participant_joined event.
|
|
50
|
+
*/
|
|
51
|
+
save(participant: ServerParticipant): void {
|
|
52
|
+
this.eventStore.emit({
|
|
53
|
+
type: "conversation",
|
|
54
|
+
source: { agent_id: participant.id },
|
|
55
|
+
payload: {
|
|
56
|
+
action: "participant_joined",
|
|
57
|
+
conversation_id: participant.conversationId,
|
|
58
|
+
participant_id: participant.id,
|
|
59
|
+
participant_type: participant.type,
|
|
60
|
+
participant_role: participant.role,
|
|
61
|
+
agent_id: participant.agentInfo?.agentId,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get a specific participant in a conversation.
|
|
68
|
+
*/
|
|
69
|
+
get(
|
|
70
|
+
conversationId: string,
|
|
71
|
+
participantId: string
|
|
72
|
+
): ServerParticipant | undefined {
|
|
73
|
+
const participants = this.eventStore.listParticipants(conversationId);
|
|
74
|
+
const found = participants.find((p) => p.id === participantId);
|
|
75
|
+
return found ? toServerParticipant(found) : undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* List participants matching filter criteria.
|
|
80
|
+
*/
|
|
81
|
+
list(filter: MAPParticipantFilter): ServerParticipant[] {
|
|
82
|
+
if (filter.conversationId) {
|
|
83
|
+
const participants = this.eventStore
|
|
84
|
+
.listParticipants(filter.conversationId, filter.active)
|
|
85
|
+
.map(toServerParticipant);
|
|
86
|
+
|
|
87
|
+
return participants.filter((p) => {
|
|
88
|
+
if (filter.participantId && p.id !== filter.participantId) return false;
|
|
89
|
+
if (filter.role && p.role !== filter.role) return false;
|
|
90
|
+
return true;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Without conversationId, we need to scan all conversations
|
|
95
|
+
if (filter.participantId) {
|
|
96
|
+
const convIds = this.getConversationsForParticipant(
|
|
97
|
+
filter.participantId,
|
|
98
|
+
filter.active
|
|
99
|
+
);
|
|
100
|
+
const results: ServerParticipant[] = [];
|
|
101
|
+
for (const convId of convIds) {
|
|
102
|
+
const participants = this.eventStore.listParticipants(convId);
|
|
103
|
+
const found = participants.find((p) => p.id === filter.participantId);
|
|
104
|
+
if (found) {
|
|
105
|
+
const sp = toServerParticipant(found);
|
|
106
|
+
if (!filter.role || sp.role === filter.role) {
|
|
107
|
+
results.push(sp);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return results;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// No conversationId and no participantId — return empty
|
|
115
|
+
// (listing all participants across all conversations is expensive and rarely needed)
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Remove a participant from a conversation by emitting a participant_left event.
|
|
121
|
+
*/
|
|
122
|
+
delete(conversationId: string, participantId: string): boolean {
|
|
123
|
+
const existing = this.get(conversationId, participantId);
|
|
124
|
+
if (!existing) return false;
|
|
125
|
+
|
|
126
|
+
this.eventStore.emit({
|
|
127
|
+
type: "conversation",
|
|
128
|
+
source: { agent_id: participantId },
|
|
129
|
+
payload: {
|
|
130
|
+
action: "participant_left",
|
|
131
|
+
conversation_id: conversationId,
|
|
132
|
+
participant_id: participantId,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Delete all participants for a conversation. Not supported.
|
|
141
|
+
*/
|
|
142
|
+
deleteByConversation(_conversationId: string): number {
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get all conversation IDs a participant belongs to.
|
|
148
|
+
*/
|
|
149
|
+
getConversationsForParticipant(
|
|
150
|
+
participantId: string,
|
|
151
|
+
active?: boolean
|
|
152
|
+
): string[] {
|
|
153
|
+
const conversations = this.eventStore.listConversations();
|
|
154
|
+
const result: string[] = [];
|
|
155
|
+
|
|
156
|
+
for (const conv of conversations) {
|
|
157
|
+
const participants = this.eventStore.listParticipants(conv.id, active);
|
|
158
|
+
if (participants.some((p) => p.id === participantId)) {
|
|
159
|
+
result.push(conv.id);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Clear all participants. Not supported — EventStore is append-only.
|
|
168
|
+
*/
|
|
169
|
+
clear(): void {
|
|
170
|
+
// No-op
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventStore-backed ThreadStore adapter.
|
|
3
|
+
*
|
|
4
|
+
* Minimal implementation — threads are a secondary feature.
|
|
5
|
+
* Implements the MAP-compatible ThreadStore interface by:
|
|
6
|
+
* - save() → emits a `thread` event with action `created`
|
|
7
|
+
* - get()/list() → reads from EventStore materialized views
|
|
8
|
+
* - turnCount computed from actual turns with matching threadId
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { EventStore } from "../../store/event-store.js";
|
|
12
|
+
import type { ThreadStore, ServerThread, MAPThreadFilter } from "./types.js";
|
|
13
|
+
|
|
14
|
+
export class EventStoreThreadStore implements ThreadStore {
|
|
15
|
+
constructor(private readonly eventStore: EventStore) {}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Save a thread by emitting a thread event.
|
|
19
|
+
*/
|
|
20
|
+
save(thread: ServerThread): void {
|
|
21
|
+
this.eventStore.emit({
|
|
22
|
+
type: "thread",
|
|
23
|
+
source: { agent_id: thread.createdBy },
|
|
24
|
+
payload: {
|
|
25
|
+
action: "created",
|
|
26
|
+
thread_id: thread.id,
|
|
27
|
+
conversation_id: thread.conversationId,
|
|
28
|
+
root_turn_id: thread.rootTurnId,
|
|
29
|
+
subject: thread.subject,
|
|
30
|
+
parent_thread_id: thread.parentThreadId,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get a thread by ID.
|
|
37
|
+
* Scans the EventStore events since threads don't have a dedicated
|
|
38
|
+
* lookup-by-ID query method on EventStore.
|
|
39
|
+
*/
|
|
40
|
+
get(id: string): ServerThread | undefined {
|
|
41
|
+
// Query thread events and find the matching one
|
|
42
|
+
const events = this.eventStore.query({ type: "thread" });
|
|
43
|
+
for (const event of events) {
|
|
44
|
+
if (event.payload.thread_id === id) {
|
|
45
|
+
const conversationId = event.payload.conversation_id as string;
|
|
46
|
+
const turnCount = this.countTurnsForThread(conversationId, id);
|
|
47
|
+
return {
|
|
48
|
+
id: event.payload.thread_id as string,
|
|
49
|
+
conversationId,
|
|
50
|
+
parentThreadId: event.payload.parent_thread_id as string | undefined,
|
|
51
|
+
subject: event.payload.subject as string | undefined,
|
|
52
|
+
rootTurnId: event.payload.root_turn_id as string,
|
|
53
|
+
turnCount,
|
|
54
|
+
participantCount: 0,
|
|
55
|
+
createdAt: event.timestamp,
|
|
56
|
+
updatedAt: event.timestamp,
|
|
57
|
+
createdBy: event.source.agent_id ?? "unknown",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* List threads matching filter criteria.
|
|
66
|
+
*/
|
|
67
|
+
list(filter: MAPThreadFilter): ServerThread[] {
|
|
68
|
+
const events = this.eventStore.query({ type: "thread" });
|
|
69
|
+
const threads: ServerThread[] = [];
|
|
70
|
+
|
|
71
|
+
for (const event of events) {
|
|
72
|
+
if (event.payload.action !== "created") continue;
|
|
73
|
+
if (event.payload.conversation_id !== filter.conversationId) continue;
|
|
74
|
+
if (
|
|
75
|
+
filter.parentThreadId !== undefined &&
|
|
76
|
+
event.payload.parent_thread_id !== filter.parentThreadId
|
|
77
|
+
)
|
|
78
|
+
continue;
|
|
79
|
+
|
|
80
|
+
const threadId = event.payload.thread_id as string;
|
|
81
|
+
const conversationId = event.payload.conversation_id as string;
|
|
82
|
+
const turnCount = this.countTurnsForThread(conversationId, threadId);
|
|
83
|
+
|
|
84
|
+
threads.push({
|
|
85
|
+
id: threadId,
|
|
86
|
+
conversationId,
|
|
87
|
+
parentThreadId: event.payload.parent_thread_id as string | undefined,
|
|
88
|
+
subject: event.payload.subject as string | undefined,
|
|
89
|
+
rootTurnId: event.payload.root_turn_id as string,
|
|
90
|
+
turnCount,
|
|
91
|
+
participantCount: 0,
|
|
92
|
+
createdAt: event.timestamp,
|
|
93
|
+
updatedAt: event.timestamp,
|
|
94
|
+
createdBy: event.source.agent_id ?? "unknown",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return threads;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Count turns that belong to a specific thread.
|
|
103
|
+
*/
|
|
104
|
+
private countTurnsForThread(conversationId: string, threadId: string): number {
|
|
105
|
+
const turns = this.eventStore.listTurns({ conversationId, threadId });
|
|
106
|
+
return turns.length;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Delete a thread. Not supported — EventStore is append-only.
|
|
111
|
+
*/
|
|
112
|
+
delete(_id: string): boolean {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Delete all threads for a conversation. Not supported.
|
|
118
|
+
*/
|
|
119
|
+
deleteByConversation(_conversationId: string): number {
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Clear all threads. Not supported.
|
|
125
|
+
*/
|
|
126
|
+
clear(): void {
|
|
127
|
+
// No-op
|
|
128
|
+
}
|
|
129
|
+
}
|