macro-agent 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +3 -1
- package/.sudocode/issues.jsonl +28 -0
- package/.sudocode/specs.jsonl +8 -0
- package/CLAUDE.md +25 -17
- package/README.md +11 -29
- package/dist/acp/macro-agent.d.ts +15 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +131 -35
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/types.d.ts +32 -1
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js.map +1 -1
- package/dist/agent/agent-manager.d.ts +65 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +544 -200
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +8 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/server.d.ts +8 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +136 -8
- package/dist/api/server.js.map +1 -1
- package/dist/api/types.d.ts +1 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/token.d.ts +41 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +73 -0
- package/dist/auth/token.js.map +1 -0
- package/dist/cli/acp.d.ts +2 -23
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +197 -61
- package/dist/cli/acp.js.map +1 -1
- package/dist/cli/index.js +152 -16
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts +6 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +279 -173
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/parse-args.d.ts +20 -0
- package/dist/cli/parse-args.d.ts.map +1 -0
- package/dist/cli/parse-args.js +43 -0
- package/dist/cli/parse-args.js.map +1 -0
- package/dist/cli/stable-instance-id.d.ts +8 -0
- package/dist/cli/stable-instance-id.d.ts.map +1 -0
- package/dist/cli/stable-instance-id.js +14 -0
- package/dist/cli/stable-instance-id.js.map +1 -0
- package/dist/config/project-config.d.ts +85 -7
- package/dist/config/project-config.d.ts.map +1 -1
- package/dist/config/project-config.js +133 -20
- package/dist/config/project-config.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/handlers/index.d.ts +7 -3
- package/dist/lifecycle/handlers/index.d.ts.map +1 -1
- package/dist/lifecycle/handlers/index.js +25 -8
- package/dist/lifecycle/handlers/index.js.map +1 -1
- package/dist/lifecycle/types.d.ts +2 -0
- package/dist/lifecycle/types.d.ts.map +1 -1
- package/dist/lifecycle/types.js.map +1 -1
- package/dist/map/adapter/acp-over-map.d.ts +17 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +384 -23
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/adapter/connection-manager.d.ts.map +1 -1
- package/dist/map/adapter/connection-manager.js +3 -0
- package/dist/map/adapter/connection-manager.js.map +1 -1
- package/dist/map/adapter/event-log.d.ts +87 -0
- package/dist/map/adapter/event-log.d.ts.map +1 -0
- package/dist/map/adapter/event-log.js +122 -0
- package/dist/map/adapter/event-log.js.map +1 -0
- package/dist/map/adapter/event-translator.js +6 -6
- package/dist/map/adapter/event-translator.js.map +1 -1
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
- package/dist/map/adapter/extensions/index.d.ts +13 -1
- package/dist/map/adapter/extensions/index.d.ts.map +1 -1
- package/dist/map/adapter/extensions/index.js +61 -0
- package/dist/map/adapter/extensions/index.js.map +1 -1
- package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
- package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
- package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
- package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
- package/dist/map/adapter/extensions/rename.d.ts +29 -0
- package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
- package/dist/map/adapter/extensions/rename.js +49 -0
- package/dist/map/adapter/extensions/rename.js.map +1 -0
- package/dist/map/adapter/extensions/streams.d.ts +95 -0
- package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
- package/dist/map/adapter/extensions/streams.js +515 -0
- package/dist/map/adapter/extensions/streams.js.map +1 -0
- package/dist/map/adapter/extensions/task.d.ts.map +1 -1
- package/dist/map/adapter/extensions/task.js +10 -0
- package/dist/map/adapter/extensions/task.js.map +1 -1
- package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
- package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
- package/dist/map/adapter/extensions/update-metadata.js +67 -0
- package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
- package/dist/map/adapter/index.d.ts +2 -1
- package/dist/map/adapter/index.d.ts.map +1 -1
- package/dist/map/adapter/index.js +10 -2
- package/dist/map/adapter/index.js.map +1 -1
- package/dist/map/adapter/interface.d.ts +2 -0
- package/dist/map/adapter/interface.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.d.ts +3 -0
- package/dist/map/adapter/map-adapter.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.js +258 -35
- package/dist/map/adapter/map-adapter.js.map +1 -1
- package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
- package/dist/map/adapter/subscription-manager.js +5 -1
- package/dist/map/adapter/subscription-manager.js.map +1 -1
- package/dist/map/adapter/types.d.ts +3 -1
- package/dist/map/adapter/types.d.ts.map +1 -1
- package/dist/mcp/map-client.d.ts +39 -0
- package/dist/mcp/map-client.d.ts.map +1 -0
- package/dist/mcp/map-client.js +129 -0
- package/dist/mcp/map-client.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +16 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +125 -88
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/tools/done.d.ts.map +1 -1
- package/dist/mcp/tools/done.js +18 -0
- package/dist/mcp/tools/done.js.map +1 -1
- package/dist/mcp/types.d.ts +9 -1
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/metrics/metrics.js +1 -1
- package/dist/metrics/metrics.js.map +1 -1
- package/dist/roles/builtin/coordinator.d.ts.map +1 -1
- package/dist/roles/builtin/coordinator.js +2 -1
- package/dist/roles/builtin/coordinator.js.map +1 -1
- package/dist/roles/builtin/integrator.d.ts.map +1 -1
- package/dist/roles/builtin/integrator.js +2 -1
- package/dist/roles/builtin/integrator.js.map +1 -1
- package/dist/roles/builtin/worker.d.ts.map +1 -1
- package/dist/roles/builtin/worker.js +3 -1
- package/dist/roles/builtin/worker.js.map +1 -1
- package/dist/roles/capabilities.d.ts +9 -1
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +27 -7
- package/dist/roles/capabilities.js.map +1 -1
- package/dist/roles/config-loader.d.ts +6 -6
- package/dist/roles/config-loader.d.ts.map +1 -1
- package/dist/roles/config-loader.js +8 -7
- package/dist/roles/config-loader.js.map +1 -1
- package/dist/roles/registry.d.ts +2 -2
- package/dist/roles/registry.js +2 -2
- package/dist/roles/types.d.ts +3 -1
- package/dist/roles/types.d.ts.map +1 -1
- package/dist/server/combined-server.d.ts +28 -1
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +111 -8
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.d.ts +2 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +80 -24
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/instance.d.ts +1 -1
- package/dist/store/instance.d.ts.map +1 -1
- package/dist/store/instance.js +2 -2
- package/dist/store/instance.js.map +1 -1
- package/dist/store/types/agents.d.ts +23 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/dist/store/types/events.d.ts +1 -1
- package/dist/store/types/events.d.ts.map +1 -1
- package/dist/task/backend/index.d.ts +47 -29
- package/dist/task/backend/index.d.ts.map +1 -1
- package/dist/task/backend/index.js +109 -71
- package/dist/task/backend/index.js.map +1 -1
- package/dist/task/backend/memory.d.ts +1 -0
- package/dist/task/backend/memory.d.ts.map +1 -1
- package/dist/task/backend/memory.js +3 -0
- package/dist/task/backend/memory.js.map +1 -1
- package/dist/task/backend/opentasks/backend.d.ts +140 -0
- package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
- package/dist/task/backend/opentasks/backend.js +1023 -0
- package/dist/task/backend/opentasks/backend.js.map +1 -0
- package/dist/task/backend/opentasks/client.d.ts +337 -0
- package/dist/task/backend/opentasks/client.d.ts.map +1 -0
- package/dist/task/backend/opentasks/client.js +225 -0
- package/dist/task/backend/opentasks/client.js.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.js +195 -0
- package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
- package/dist/task/backend/opentasks/index.d.ts +21 -0
- package/dist/task/backend/opentasks/index.d.ts.map +1 -0
- package/dist/task/backend/opentasks/index.js +21 -0
- package/dist/task/backend/opentasks/index.js.map +1 -0
- package/dist/task/backend/opentasks/mapping.d.ts +48 -0
- package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
- package/dist/task/backend/opentasks/mapping.js +77 -0
- package/dist/task/backend/opentasks/mapping.js.map +1 -0
- package/dist/task/backend/types.d.ts +33 -53
- package/dist/task/backend/types.d.ts.map +1 -1
- package/dist/task/backend/types.js +7 -11
- package/dist/task/backend/types.js.map +1 -1
- package/dist/task/backend/unified-tool-provider.d.ts +57 -0
- package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
- package/dist/task/backend/unified-tool-provider.js +623 -0
- package/dist/task/backend/unified-tool-provider.js.map +1 -0
- package/dist/teams/index.d.ts +3 -1
- package/dist/teams/index.d.ts.map +1 -1
- package/dist/teams/index.js +2 -0
- package/dist/teams/index.js.map +1 -1
- package/dist/teams/seed-defaults.d.ts +20 -0
- package/dist/teams/seed-defaults.d.ts.map +1 -0
- package/dist/teams/seed-defaults.js +71 -0
- package/dist/teams/seed-defaults.js.map +1 -0
- package/dist/teams/team-loader.d.ts +7 -3
- package/dist/teams/team-loader.d.ts.map +1 -1
- package/dist/teams/team-loader.js +156 -164
- package/dist/teams/team-loader.js.map +1 -1
- package/dist/teams/team-manager.d.ts +112 -0
- package/dist/teams/team-manager.d.ts.map +1 -0
- package/dist/teams/team-manager.js +305 -0
- package/dist/teams/team-manager.js.map +1 -0
- package/dist/teams/team-runtime.d.ts +125 -19
- package/dist/teams/team-runtime.d.ts.map +1 -1
- package/dist/teams/team-runtime.js +529 -119
- package/dist/teams/team-runtime.js.map +1 -1
- package/dist/teams/types.d.ts +41 -151
- package/dist/teams/types.d.ts.map +1 -1
- package/dist/teams/types.js +2 -3
- package/dist/teams/types.js.map +1 -1
- package/docs/architecture.md +7 -6
- package/docs/configuration.md +26 -62
- package/docs/implementation-details.md +5 -5
- package/docs/implementation-summary.md +17 -17
- package/docs/plan-self-driving-support.md +4 -4
- package/docs/spec-self-driving-support.md +10 -10
- package/docs/team-templates.md +2 -2
- package/docs/teams.md +76 -3
- package/docs/troubleshooting.md +10 -11
- package/package.json +7 -4
- package/references/minimem/.claude/settings.json +7 -0
- package/references/minimem/.sudocode/issues.jsonl +18 -0
- package/references/minimem/.sudocode/specs.jsonl +1 -0
- package/references/minimem/CLAUDE.md +310 -0
- package/references/minimem/README.md +562 -0
- package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
- package/references/minimem/claude-plugin/.mcp.json +7 -0
- package/references/minimem/claude-plugin/README.md +158 -0
- package/references/minimem/claude-plugin/commands/recall.md +47 -0
- package/references/minimem/claude-plugin/commands/remember.md +41 -0
- package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
- package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
- package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
- package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
- package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
- package/references/minimem/media/banner.png +0 -0
- package/references/minimem/package-lock.json +5373 -0
- package/references/minimem/package.json +72 -0
- package/references/minimem/scripts/postbuild.js +35 -0
- package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
- package/references/minimem/src/__tests__/errors.test.ts +265 -0
- package/references/minimem/src/__tests__/helpers.ts +199 -0
- package/references/minimem/src/__tests__/internal.test.ts +407 -0
- package/references/minimem/src/__tests__/knowledge.test.ts +287 -0
- package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
- package/references/minimem/src/__tests__/session.test.ts +190 -0
- package/references/minimem/src/cli/__tests__/commands.test.ts +759 -0
- package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
- package/references/minimem/src/cli/commands/append.ts +76 -0
- package/references/minimem/src/cli/commands/config.ts +262 -0
- package/references/minimem/src/cli/commands/conflicts.ts +413 -0
- package/references/minimem/src/cli/commands/daemon.ts +169 -0
- package/references/minimem/src/cli/commands/index.ts +12 -0
- package/references/minimem/src/cli/commands/init.ts +88 -0
- package/references/minimem/src/cli/commands/mcp.ts +177 -0
- package/references/minimem/src/cli/commands/push-pull.ts +213 -0
- package/references/minimem/src/cli/commands/search.ts +158 -0
- package/references/minimem/src/cli/commands/status.ts +84 -0
- package/references/minimem/src/cli/commands/sync-init.ts +290 -0
- package/references/minimem/src/cli/commands/sync.ts +70 -0
- package/references/minimem/src/cli/commands/upsert.ts +197 -0
- package/references/minimem/src/cli/config.ts +584 -0
- package/references/minimem/src/cli/index.ts +264 -0
- package/references/minimem/src/cli/shared.ts +161 -0
- package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
- package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
- package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
- package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
- package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
- package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
- package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
- package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
- package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
- package/references/minimem/src/cli/sync/central.ts +292 -0
- package/references/minimem/src/cli/sync/conflicts.ts +204 -0
- package/references/minimem/src/cli/sync/daemon.ts +407 -0
- package/references/minimem/src/cli/sync/detection.ts +138 -0
- package/references/minimem/src/cli/sync/index.ts +107 -0
- package/references/minimem/src/cli/sync/operations.ts +373 -0
- package/references/minimem/src/cli/sync/registry.ts +279 -0
- package/references/minimem/src/cli/sync/state.ts +355 -0
- package/references/minimem/src/cli/sync/validation.ts +206 -0
- package/references/minimem/src/cli/sync/watcher.ts +234 -0
- package/references/minimem/src/cli/version.ts +34 -0
- package/references/minimem/src/core/index.ts +9 -0
- package/references/minimem/src/core/indexer.ts +628 -0
- package/references/minimem/src/core/searcher.ts +221 -0
- package/references/minimem/src/db/schema.ts +183 -0
- package/references/minimem/src/db/sqlite-vec.ts +24 -0
- package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
- package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
- package/references/minimem/src/embeddings/batch-openai.ts +409 -0
- package/references/minimem/src/embeddings/embeddings.ts +434 -0
- package/references/minimem/src/index.ts +109 -0
- package/references/minimem/src/internal.ts +299 -0
- package/references/minimem/src/minimem.ts +1276 -0
- package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
- package/references/minimem/src/search/graph.ts +234 -0
- package/references/minimem/src/search/hybrid.ts +151 -0
- package/references/minimem/src/search/search.ts +256 -0
- package/references/minimem/src/server/__tests__/mcp.test.ts +341 -0
- package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
- package/references/minimem/src/server/mcp.ts +326 -0
- package/references/minimem/src/server/tools.ts +720 -0
- package/references/minimem/src/session.ts +460 -0
- package/references/minimem/tsconfig.json +19 -0
- package/references/minimem/tsup.config.ts +26 -0
- package/references/minimem/vitest.config.ts +24 -0
- package/references/openteams/.claude/settings.json +6 -0
- package/references/openteams/README.md +1 -0
- package/references/openteams/SKILL.md +341 -0
- package/references/openteams/design.md +411 -0
- package/references/openteams/examples/bmad-method/prompts/analyst/ROLE.md +16 -0
- package/references/openteams/examples/bmad-method/prompts/analyst/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/architect/ROLE.md +24 -0
- package/references/openteams/examples/bmad-method/prompts/architect/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/developer/ROLE.md +25 -0
- package/references/openteams/examples/bmad-method/prompts/developer/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/master/ROLE.md +21 -0
- package/references/openteams/examples/bmad-method/prompts/master/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/pm/ROLE.md +20 -0
- package/references/openteams/examples/bmad-method/prompts/pm/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/qa/ROLE.md +17 -0
- package/references/openteams/examples/bmad-method/prompts/qa/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/ROLE.md +23 -0
- package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/scrum-master/ROLE.md +27 -0
- package/references/openteams/examples/bmad-method/prompts/scrum-master/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/tech-writer/ROLE.md +21 -0
- package/references/openteams/examples/bmad-method/prompts/tech-writer/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/ux-designer/ROLE.md +16 -0
- package/references/openteams/examples/bmad-method/prompts/ux-designer/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/roles/analyst.yaml +9 -0
- package/references/openteams/examples/bmad-method/roles/architect.yaml +9 -0
- package/references/openteams/examples/bmad-method/roles/developer.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/master.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/pm.yaml +9 -0
- package/references/openteams/examples/bmad-method/roles/qa.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/quick-flow-dev.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/scrum-master.yaml +9 -0
- package/references/openteams/examples/bmad-method/roles/tech-writer.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/ux-designer.yaml +8 -0
- package/references/openteams/examples/bmad-method/team.yaml +161 -0
- package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/ROLE.md +17 -0
- package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/debugger/ROLE.md +25 -0
- package/references/openteams/examples/get-shit-done/prompts/debugger/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/executor/ROLE.md +34 -0
- package/references/openteams/examples/get-shit-done/prompts/executor/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/integration-checker/ROLE.md +18 -0
- package/references/openteams/examples/get-shit-done/prompts/integration-checker/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/orchestrator/ROLE.md +42 -0
- package/references/openteams/examples/get-shit-done/prompts/orchestrator/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/phase-researcher/ROLE.md +15 -0
- package/references/openteams/examples/get-shit-done/prompts/phase-researcher/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/plan-checker/ROLE.md +17 -0
- package/references/openteams/examples/get-shit-done/prompts/plan-checker/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/planner/ROLE.md +28 -0
- package/references/openteams/examples/get-shit-done/prompts/planner/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/project-researcher/ROLE.md +16 -0
- package/references/openteams/examples/get-shit-done/prompts/project-researcher/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/ROLE.md +13 -0
- package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/roadmapper/ROLE.md +14 -0
- package/references/openteams/examples/get-shit-done/prompts/roadmapper/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/verifier/ROLE.md +19 -0
- package/references/openteams/examples/get-shit-done/prompts/verifier/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/roles/codebase-mapper.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/debugger.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/executor.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/integration-checker.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/orchestrator.yaml +9 -0
- package/references/openteams/examples/get-shit-done/roles/phase-researcher.yaml +7 -0
- package/references/openteams/examples/get-shit-done/roles/plan-checker.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/planner.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/project-researcher.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/research-synthesizer.yaml +7 -0
- package/references/openteams/examples/get-shit-done/roles/roadmapper.yaml +7 -0
- package/references/openteams/examples/get-shit-done/roles/verifier.yaml +8 -0
- package/references/openteams/examples/get-shit-done/team.yaml +154 -0
- package/references/openteams/package-lock.json +2181 -0
- package/references/openteams/package.json +48 -0
- package/references/openteams/schema/role.schema.json +125 -0
- package/references/openteams/schema/team.schema.json +284 -0
- package/references/openteams/src/cli/agent.ts +104 -0
- package/references/openteams/src/cli/cli.test.ts +381 -0
- package/references/openteams/src/cli/generate.ts +220 -0
- package/references/openteams/src/cli/message.ts +241 -0
- package/references/openteams/src/cli/task.ts +154 -0
- package/references/openteams/src/cli/team.ts +104 -0
- package/references/openteams/src/cli/template.ts +207 -0
- package/references/openteams/src/cli.ts +45 -0
- package/references/openteams/src/db/database.test.ts +185 -0
- package/references/openteams/src/db/database.ts +240 -0
- package/references/openteams/src/generators/agent-prompt-generator.test.ts +332 -0
- package/references/openteams/src/generators/agent-prompt-generator.ts +521 -0
- package/references/openteams/src/generators/package-generator.test.ts +129 -0
- package/references/openteams/src/generators/package-generator.ts +102 -0
- package/references/openteams/src/generators/skill-generator.test.ts +246 -0
- package/references/openteams/src/generators/skill-generator.ts +374 -0
- package/references/openteams/src/index.ts +104 -0
- package/references/openteams/src/services/agent-service.test.ts +158 -0
- package/references/openteams/src/services/agent-service.ts +84 -0
- package/references/openteams/src/services/communication-service.test.ts +455 -0
- package/references/openteams/src/services/communication-service.ts +371 -0
- package/references/openteams/src/services/message-service.test.ts +342 -0
- package/references/openteams/src/services/message-service.ts +203 -0
- package/references/openteams/src/services/task-service.test.ts +434 -0
- package/references/openteams/src/services/task-service.ts +239 -0
- package/references/openteams/src/services/team-service.test.ts +181 -0
- package/references/openteams/src/services/team-service.ts +139 -0
- package/references/openteams/src/services/template-service.test.ts +306 -0
- package/references/openteams/src/services/template-service.ts +182 -0
- package/references/openteams/src/spawner/acp-factory.ts +96 -0
- package/references/openteams/src/spawner/interface.ts +31 -0
- package/references/openteams/src/spawner/mock.test.ts +93 -0
- package/references/openteams/src/spawner/mock.ts +59 -0
- package/references/openteams/src/template/loader.test.ts +1319 -0
- package/references/openteams/src/template/loader.ts +698 -0
- package/references/openteams/src/template/types.ts +200 -0
- package/references/openteams/src/types.ts +205 -0
- package/references/openteams/tsconfig.json +18 -0
- package/references/openteams/vitest.config.ts +9 -0
- package/references/skill-tree/.claude/settings.json +6 -0
- package/references/skill-tree/.sudocode/issues.jsonl +11 -0
- package/references/skill-tree/.sudocode/specs.jsonl +1 -0
- package/references/skill-tree/CLAUDE.md +150 -0
- package/references/skill-tree/README.md +324 -0
- package/references/skill-tree/docs/GAPS_v1.md +221 -0
- package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
- package/references/skill-tree/docs/TODOS.md +91 -0
- package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
- package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
- package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
- package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
- package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
- package/references/skill-tree/docs/scraper/README.md +170 -0
- package/references/skill-tree/examples/basic-usage.ts +190 -0
- package/references/skill-tree/package-lock.json +1509 -0
- package/references/skill-tree/package.json +66 -0
- package/references/skill-tree/scraper/README.md +123 -0
- package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
- package/references/skill-tree/scraper/docs/PLAN.md +336 -0
- package/references/skill-tree/scraper/drizzle.config.ts +10 -0
- package/references/skill-tree/scraper/package-lock.json +6329 -0
- package/references/skill-tree/scraper/package.json +68 -0
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
- package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
- package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
- package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
- package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
- package/references/skill-tree/scraper/tsup.config.ts +14 -0
- package/references/skill-tree/scraper/vitest.config.ts +17 -0
- package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
- package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
- package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
- package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
- package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
- package/references/skill-tree/test/run-all.ts +106 -0
- package/references/skill-tree/test/utils.ts +128 -0
- package/references/skill-tree/vitest.config.ts +16 -0
- package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
- package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
- package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
- package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
- package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
- package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
- package/src/acp/__tests__/integration.test.ts +56 -31
- package/src/acp/__tests__/macro-agent.test.ts +16 -7
- package/src/acp/macro-agent.ts +170 -36
- package/src/acp/types.ts +46 -1
- package/src/agent/__tests__/agent-manager.test.ts +228 -2
- package/src/agent/agent-manager.ts +809 -285
- package/src/agent/types.ts +12 -1
- package/src/api/__tests__/server.test.ts +203 -4
- package/src/api/server.ts +169 -10
- package/src/api/types.ts +3 -1
- package/src/auth/__tests__/token.test.ts +100 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/token.ts +82 -0
- package/src/cli/__tests__/acp.test.ts +1 -1
- package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
- package/src/cli/acp.ts +197 -72
- package/src/cli/index.ts +125 -15
- package/src/cli/mcp.ts +315 -197
- package/src/cli/parse-args.ts +54 -0
- package/src/cli/stable-instance-id.ts +14 -0
- package/src/config/project-config.ts +214 -27
- package/src/index.ts +3 -0
- package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
- package/src/lifecycle/__tests__/handlers.test.ts +53 -0
- package/src/lifecycle/handlers/index.ts +25 -8
- package/src/lifecycle/types.ts +3 -0
- package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +22 -4
- package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
- package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
- package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
- package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
- package/src/map/adapter/__tests__/event-log.test.ts +527 -0
- package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
- package/src/map/adapter/__tests__/extensions.test.ts +408 -0
- package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
- package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
- package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
- package/src/map/adapter/__tests__/stream-extensions.test.ts +494 -0
- package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
- package/src/map/adapter/acp-over-map.ts +678 -66
- package/src/map/adapter/connection-manager.ts +3 -0
- package/src/map/adapter/event-log.ts +208 -0
- package/src/map/adapter/event-translator.ts +6 -6
- package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
- package/src/map/adapter/extensions/index.ts +96 -0
- package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
- package/src/map/adapter/extensions/streams.ts +839 -0
- package/src/map/adapter/extensions/task.ts +11 -0
- package/src/map/adapter/extensions/update-metadata.ts +126 -0
- package/src/map/adapter/index.ts +33 -0
- package/src/map/adapter/interface.ts +2 -0
- package/src/map/adapter/map-adapter.ts +312 -47
- package/src/map/adapter/subscription-manager.ts +5 -1
- package/src/map/adapter/types.ts +10 -1
- package/src/mcp/__tests__/map-client.test.ts +386 -0
- package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
- package/src/mcp/__tests__/mcp-server.test.ts +100 -1
- package/src/mcp/map-client.ts +177 -0
- package/src/mcp/mcp-server.ts +205 -103
- package/src/mcp/tools/done.ts +19 -0
- package/src/mcp/types.ts +6 -1
- package/src/metrics/metrics.ts +1 -1
- package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
- package/src/roles/__tests__/config-loader.test.ts +7 -7
- package/src/roles/builtin/coordinator.ts +2 -0
- package/src/roles/builtin/integrator.ts +2 -0
- package/src/roles/builtin/worker.ts +3 -0
- package/src/roles/capabilities.ts +28 -7
- package/src/roles/config-loader.ts +8 -7
- package/src/roles/registry.ts +2 -2
- package/src/roles/types.ts +7 -0
- package/src/server/__tests__/combined-server.test.ts +94 -21
- package/src/server/combined-server.ts +203 -33
- package/src/steering/__tests__/steering-integration.test.ts +1 -1
- package/src/store/__tests__/event-store-oob.test.ts +109 -0
- package/src/store/__tests__/event-store.test.ts +196 -1
- package/src/store/__tests__/instance.test.ts +3 -3
- package/src/store/event-store.ts +92 -23
- package/src/store/instance.ts +2 -2
- package/src/store/types/agents.ts +20 -0
- package/src/store/types/events.ts +1 -1
- package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
- package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
- package/src/task/backend/__tests__/memory-pull-mode.test.ts +153 -0
- package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
- package/src/task/backend/index.ts +156 -106
- package/src/task/backend/memory.ts +4 -0
- package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
- package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
- package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
- package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
- package/src/task/backend/opentasks/backend.ts +1323 -0
- package/src/task/backend/opentasks/client.ts +652 -0
- package/src/task/backend/opentasks/daemon-manager.ts +256 -0
- package/src/task/backend/opentasks/index.ts +69 -0
- package/src/task/backend/opentasks/mapping.ts +94 -0
- package/src/task/backend/types.ts +42 -66
- package/src/task/backend/unified-tool-provider.ts +779 -0
- package/src/teams/CLAUDE.md +180 -0
- package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
- package/src/teams/__tests__/e2e/workspace-isolation.e2e.test.ts +1263 -0
- package/src/teams/__tests__/team-manager.test.ts +814 -0
- package/src/teams/__tests__/team-system.test.ts +1291 -8
- package/src/teams/index.ts +21 -3
- package/src/teams/seed-defaults.ts +79 -0
- package/src/teams/team-loader.ts +202 -236
- package/src/teams/team-manager.ts +387 -0
- package/src/teams/team-runtime.ts +592 -121
- package/src/teams/types.ts +99 -200
- package/test_fixtures/README.md +2 -3
- package/test_fixtures/fixtures/index.ts +0 -3
- package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
- package/test_fixtures/fixtures/repos/index.ts +1 -3
- package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
- package/test_fixtures/fixtures/repos/types.ts +0 -11
- package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
- package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
- package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
- package/vitest.config.ts +1 -1
- package/vitest.e2e.config.ts +1 -1
- package/vitest.setup.ts +1 -30
- package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
- package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
- package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
- package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
- package/.macro-agent/teams/self-driving/team.yaml +0 -103
- package/.macro-agent/teams/structured/prompts/developer.md +0 -26
- package/.macro-agent/teams/structured/prompts/lead.md +0 -25
- package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
- package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
- package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
- package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
- package/.macro-agent/teams/structured/team.yaml +0 -89
- package/docs/sudocode-integration.md +0 -383
- package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
- package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
- package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
- package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
- package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
- package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
- package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
- package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
- package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
- package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
- package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
- package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
- package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
- package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
- package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
- package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
- package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
- package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
- package/src/task/backend/sudocode/backend.ts +0 -1237
- package/src/task/backend/sudocode/client.ts +0 -515
- package/src/task/backend/sudocode/index.ts +0 -120
- package/src/task/backend/sudocode/mapping.ts +0 -93
- package/src/task/backend/sudocode/server-client.ts +0 -522
- package/src/task/backend/sudocode/standalone-client.ts +0 -623
- package/src/task/backend/sudocode/sync-policy.ts +0 -387
- package/src/task/backend/sudocode/tools.ts +0 -896
- package/src/task/backend/tool-provider.ts +0 -506
- package/test_fixtures/fixtures/sudocode/index.ts +0 -29
- package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
- package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
|
@@ -0,0 +1,761 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E test: Agent Spawn Visibility
|
|
3
|
+
*
|
|
4
|
+
* Verifies that agents spawned via various paths are visible through:
|
|
5
|
+
* 1. query_index MCP bridge (agentManager.list())
|
|
6
|
+
* 2. MAP subscription events (agent_registered notifications)
|
|
7
|
+
*
|
|
8
|
+
* Tests the full pipeline from spawn → EventStore → query/subscription.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
12
|
+
import { WebSocket } from "ws";
|
|
13
|
+
import { createEventStore, type EventStore } from "../../store/event-store.js";
|
|
14
|
+
import {
|
|
15
|
+
createAgentManager,
|
|
16
|
+
type AgentManager,
|
|
17
|
+
} from "../../agent/agent-manager.js";
|
|
18
|
+
import { createTaskManager, type TaskManager } from "../../task/task-manager.js";
|
|
19
|
+
import {
|
|
20
|
+
createMessageRouter,
|
|
21
|
+
type MessageRouter,
|
|
22
|
+
} from "../../router/message-router.js";
|
|
23
|
+
import {
|
|
24
|
+
createCombinedServer,
|
|
25
|
+
type CombinedServer,
|
|
26
|
+
type CombinedServerServices,
|
|
27
|
+
} from "../../server/combined-server.js";
|
|
28
|
+
import { mapCall } from "../../mcp/map-client.js";
|
|
29
|
+
|
|
30
|
+
// =============================================================================
|
|
31
|
+
// Helpers
|
|
32
|
+
// =============================================================================
|
|
33
|
+
|
|
34
|
+
function getRandomPort(): number {
|
|
35
|
+
return 10000 + Math.floor(Math.random() * 50000);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function agentContext(agentId: string, taskId?: string) {
|
|
39
|
+
return {
|
|
40
|
+
agent_id: agentId,
|
|
41
|
+
session_id: "sess_test",
|
|
42
|
+
task_id: taskId ?? "task_test",
|
|
43
|
+
lineage: [],
|
|
44
|
+
cwd: "/test/cwd",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface JsonRpcMessage {
|
|
49
|
+
jsonrpc: "2.0";
|
|
50
|
+
id?: number;
|
|
51
|
+
method?: string;
|
|
52
|
+
params?: unknown;
|
|
53
|
+
result?: unknown;
|
|
54
|
+
error?: { code: number; message: string; data?: unknown };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* WebSocket MAP client for receiving subscription events.
|
|
59
|
+
*/
|
|
60
|
+
class MAPTestClient {
|
|
61
|
+
private ws!: WebSocket;
|
|
62
|
+
private waiters: Map<
|
|
63
|
+
number,
|
|
64
|
+
{ resolve: (r: JsonRpcMessage) => void; reject: (e: Error) => void }
|
|
65
|
+
> = new Map();
|
|
66
|
+
private nextId = 1;
|
|
67
|
+
private url: string;
|
|
68
|
+
|
|
69
|
+
readonly notifications: JsonRpcMessage[] = [];
|
|
70
|
+
|
|
71
|
+
private notificationWaiters: Array<{
|
|
72
|
+
check: (msg: JsonRpcMessage) => boolean;
|
|
73
|
+
resolve: (msg: JsonRpcMessage) => void;
|
|
74
|
+
reject: (e: Error) => void;
|
|
75
|
+
timeout: ReturnType<typeof setTimeout>;
|
|
76
|
+
}> = [];
|
|
77
|
+
|
|
78
|
+
constructor(url: string) {
|
|
79
|
+
this.url = url;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async connect(): Promise<void> {
|
|
83
|
+
this.ws = new WebSocket(this.url);
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
const timeout = setTimeout(
|
|
86
|
+
() => reject(new Error("Connection timeout")),
|
|
87
|
+
5000,
|
|
88
|
+
);
|
|
89
|
+
this.ws.on("open", () => {
|
|
90
|
+
clearTimeout(timeout);
|
|
91
|
+
resolve();
|
|
92
|
+
});
|
|
93
|
+
this.ws.on("error", (err) => {
|
|
94
|
+
clearTimeout(timeout);
|
|
95
|
+
reject(err);
|
|
96
|
+
});
|
|
97
|
+
this.ws.on("message", (data: Buffer) => {
|
|
98
|
+
try {
|
|
99
|
+
const msg = JSON.parse(data.toString()) as JsonRpcMessage;
|
|
100
|
+
if (msg.id != null) {
|
|
101
|
+
const waiter = this.waiters.get(msg.id);
|
|
102
|
+
if (waiter) {
|
|
103
|
+
this.waiters.delete(msg.id);
|
|
104
|
+
waiter.resolve(msg);
|
|
105
|
+
}
|
|
106
|
+
} else if (msg.method) {
|
|
107
|
+
this.notifications.push(msg);
|
|
108
|
+
for (let i = this.notificationWaiters.length - 1; i >= 0; i--) {
|
|
109
|
+
const w = this.notificationWaiters[i];
|
|
110
|
+
if (w.check(msg)) {
|
|
111
|
+
clearTimeout(w.timeout);
|
|
112
|
+
this.notificationWaiters.splice(i, 1);
|
|
113
|
+
w.resolve(msg);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
// ignore
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async request(method: string, params?: unknown): Promise<JsonRpcMessage> {
|
|
125
|
+
const id = this.nextId++;
|
|
126
|
+
return new Promise((resolve, reject) => {
|
|
127
|
+
const timeout = setTimeout(() => {
|
|
128
|
+
this.waiters.delete(id);
|
|
129
|
+
reject(new Error(`Request timeout: ${method}`));
|
|
130
|
+
}, 30000);
|
|
131
|
+
this.waiters.set(id, {
|
|
132
|
+
resolve: (r) => {
|
|
133
|
+
clearTimeout(timeout);
|
|
134
|
+
resolve(r);
|
|
135
|
+
},
|
|
136
|
+
reject: (e) => {
|
|
137
|
+
clearTimeout(timeout);
|
|
138
|
+
reject(e);
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
this.ws.send(JSON.stringify({ jsonrpc: "2.0", method, params, id }));
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
waitForNotification(
|
|
146
|
+
check: (msg: JsonRpcMessage) => boolean,
|
|
147
|
+
timeoutMs = 15000,
|
|
148
|
+
): Promise<JsonRpcMessage> {
|
|
149
|
+
const existing = this.notifications.find(check);
|
|
150
|
+
if (existing) return Promise.resolve(existing);
|
|
151
|
+
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
const timeout = setTimeout(() => {
|
|
154
|
+
const idx = this.notificationWaiters.findIndex(
|
|
155
|
+
(w) => w.resolve === resolve,
|
|
156
|
+
);
|
|
157
|
+
if (idx >= 0) this.notificationWaiters.splice(idx, 1);
|
|
158
|
+
reject(
|
|
159
|
+
new Error(
|
|
160
|
+
`Timeout waiting for notification. Received ${this.notifications.length} notifications:\n` +
|
|
161
|
+
this.notifications
|
|
162
|
+
.map((n) => {
|
|
163
|
+
const p = n.params as Record<string, unknown> | undefined;
|
|
164
|
+
const evt = p?.event as Record<string, unknown> | undefined;
|
|
165
|
+
return ` ${n.method} → type=${evt?.type}, data=${JSON.stringify(evt?.data)}`;
|
|
166
|
+
})
|
|
167
|
+
.join("\n"),
|
|
168
|
+
),
|
|
169
|
+
);
|
|
170
|
+
}, timeoutMs);
|
|
171
|
+
this.notificationWaiters.push({ check, resolve, reject, timeout });
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
close(): void {
|
|
176
|
+
for (const w of this.notificationWaiters) {
|
|
177
|
+
clearTimeout(w.timeout);
|
|
178
|
+
}
|
|
179
|
+
this.notificationWaiters.length = 0;
|
|
180
|
+
try {
|
|
181
|
+
this.ws?.close();
|
|
182
|
+
} catch {
|
|
183
|
+
// ignore
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function isEventOfType(type: string) {
|
|
189
|
+
return (msg: JsonRpcMessage) => {
|
|
190
|
+
if (msg.method !== "map/event") return false;
|
|
191
|
+
const params = msg.params as Record<string, unknown> | undefined;
|
|
192
|
+
const event = params?.event as Record<string, unknown> | undefined;
|
|
193
|
+
return event?.type === type;
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function isEventForAgent(type: string, agentId: string) {
|
|
198
|
+
return (msg: JsonRpcMessage) => {
|
|
199
|
+
if (msg.method !== "map/event") return false;
|
|
200
|
+
const params = msg.params as Record<string, unknown> | undefined;
|
|
201
|
+
const event = params?.event as Record<string, unknown> | undefined;
|
|
202
|
+
if (event?.type !== type) return false;
|
|
203
|
+
const data = event?.data as Record<string, unknown> | undefined;
|
|
204
|
+
return data?.agentId === agentId;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// =============================================================================
|
|
209
|
+
// Tests
|
|
210
|
+
// =============================================================================
|
|
211
|
+
|
|
212
|
+
describe("Agent Spawn Visibility E2E", () => {
|
|
213
|
+
let eventStore: EventStore;
|
|
214
|
+
let agentManager: AgentManager;
|
|
215
|
+
let taskManager: TaskManager;
|
|
216
|
+
let messageRouter: MessageRouter;
|
|
217
|
+
let server: CombinedServer;
|
|
218
|
+
let port: number;
|
|
219
|
+
let serverUrl: string;
|
|
220
|
+
const clients: MAPTestClient[] = [];
|
|
221
|
+
|
|
222
|
+
beforeEach(async () => {
|
|
223
|
+
port = getRandomPort();
|
|
224
|
+
serverUrl = `http://localhost:${port}`;
|
|
225
|
+
|
|
226
|
+
eventStore = await createEventStore({ inMemory: true });
|
|
227
|
+
messageRouter = createMessageRouter(eventStore);
|
|
228
|
+
agentManager = createAgentManager(eventStore, messageRouter, {
|
|
229
|
+
defaultPermissionMode: "auto-approve",
|
|
230
|
+
defaultCwd: "/test/cwd",
|
|
231
|
+
});
|
|
232
|
+
taskManager = createTaskManager(eventStore);
|
|
233
|
+
|
|
234
|
+
const services: CombinedServerServices = {
|
|
235
|
+
eventStore,
|
|
236
|
+
agentManager,
|
|
237
|
+
taskManager,
|
|
238
|
+
messageRouter,
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
server = createCombinedServer(services, { port, host: "localhost" });
|
|
242
|
+
await server.start();
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
afterEach(async () => {
|
|
246
|
+
for (const c of clients) {
|
|
247
|
+
c.close();
|
|
248
|
+
}
|
|
249
|
+
clients.length = 0;
|
|
250
|
+
await server.stop().catch(() => {});
|
|
251
|
+
await agentManager.close();
|
|
252
|
+
await eventStore.close();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
function createClient(): MAPTestClient {
|
|
256
|
+
const client = new MAPTestClient(`ws://localhost:${port}/map`);
|
|
257
|
+
clients.push(client);
|
|
258
|
+
return client;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ─────────────────────────────────────────────────────────────────
|
|
262
|
+
// query_index visibility
|
|
263
|
+
// ─────────────────────────────────────────────────────────────────
|
|
264
|
+
|
|
265
|
+
describe("query_index visibility", () => {
|
|
266
|
+
it("returns parent agent seeded via eventStore.emit", async () => {
|
|
267
|
+
// Seed root agent
|
|
268
|
+
eventStore.emit({
|
|
269
|
+
type: "spawn",
|
|
270
|
+
source: { agent_id: "system" },
|
|
271
|
+
payload: {
|
|
272
|
+
agent_id: "agent_root",
|
|
273
|
+
session_id: "sess_root",
|
|
274
|
+
task: "Root task",
|
|
275
|
+
task_id: "task_root",
|
|
276
|
+
parent: null,
|
|
277
|
+
config: {},
|
|
278
|
+
cwd: "/test",
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
const result = await mapCall<{
|
|
283
|
+
entries: Array<{ type: string; id: string; summary: string; state?: string }>;
|
|
284
|
+
total: number;
|
|
285
|
+
}>(serverUrl, "_macro/mcp/query_index", {
|
|
286
|
+
context: agentContext("agent_root"),
|
|
287
|
+
type: "agents",
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
expect(result.entries.length).toBeGreaterThanOrEqual(1);
|
|
291
|
+
expect(result.entries.some((e) => e.id === "agent_root")).toBe(true);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it("returns child agent after parent seeds it via eventStore.emit", async () => {
|
|
295
|
+
// Seed root agent
|
|
296
|
+
eventStore.emit({
|
|
297
|
+
type: "spawn",
|
|
298
|
+
source: { agent_id: "system" },
|
|
299
|
+
payload: {
|
|
300
|
+
agent_id: "agent_parent",
|
|
301
|
+
session_id: "sess_parent",
|
|
302
|
+
task: "Parent task",
|
|
303
|
+
task_id: "task_parent",
|
|
304
|
+
parent: null,
|
|
305
|
+
config: {},
|
|
306
|
+
cwd: "/test",
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Seed child agent (simulating what agentManager.spawn does internally)
|
|
311
|
+
eventStore.emit({
|
|
312
|
+
type: "spawn",
|
|
313
|
+
source: { agent_id: "agent_parent" },
|
|
314
|
+
payload: {
|
|
315
|
+
agent_id: "agent_child",
|
|
316
|
+
session_id: "sess_child",
|
|
317
|
+
task: "Child task",
|
|
318
|
+
task_id: "task_child",
|
|
319
|
+
parent: "agent_parent",
|
|
320
|
+
config: {},
|
|
321
|
+
cwd: "/test",
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// Query from child's perspective — should see both agents
|
|
326
|
+
const result = await mapCall<{
|
|
327
|
+
entries: Array<{ type: string; id: string; summary: string; state?: string }>;
|
|
328
|
+
total: number;
|
|
329
|
+
}>(serverUrl, "_macro/mcp/query_index", {
|
|
330
|
+
context: agentContext("agent_parent"),
|
|
331
|
+
type: "agents",
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
expect(result.entries.length).toBeGreaterThanOrEqual(2);
|
|
335
|
+
expect(result.entries.some((e) => e.id === "agent_parent")).toBe(true);
|
|
336
|
+
expect(result.entries.some((e) => e.id === "agent_child")).toBe(true);
|
|
337
|
+
|
|
338
|
+
// Verify child has correct parent info
|
|
339
|
+
const child = result.entries.find((e) => e.id === "agent_child")!;
|
|
340
|
+
expect(child.summary).toBe("Child task");
|
|
341
|
+
expect(child.state).toBe("spawning");
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it("returns agents with various states", async () => {
|
|
345
|
+
// Seed agent in spawning state
|
|
346
|
+
eventStore.emit({
|
|
347
|
+
type: "spawn",
|
|
348
|
+
source: { agent_id: "system" },
|
|
349
|
+
payload: {
|
|
350
|
+
agent_id: "agent_spawning",
|
|
351
|
+
session_id: "sess_1",
|
|
352
|
+
task: "Spawning agent",
|
|
353
|
+
task_id: "task_1",
|
|
354
|
+
parent: null,
|
|
355
|
+
config: {},
|
|
356
|
+
cwd: "/test",
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Seed another agent and transition to running via status event
|
|
361
|
+
eventStore.emit({
|
|
362
|
+
type: "spawn",
|
|
363
|
+
source: { agent_id: "system" },
|
|
364
|
+
payload: {
|
|
365
|
+
agent_id: "agent_running",
|
|
366
|
+
session_id: "sess_2",
|
|
367
|
+
task: "Running agent",
|
|
368
|
+
task_id: "task_2",
|
|
369
|
+
parent: null,
|
|
370
|
+
config: {},
|
|
371
|
+
cwd: "/test",
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
eventStore.emit({
|
|
375
|
+
type: "status",
|
|
376
|
+
source: { agent_id: "agent_running" },
|
|
377
|
+
payload: { status_type: "started", summary: "Agent started" },
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Seed a stopped agent
|
|
381
|
+
eventStore.emit({
|
|
382
|
+
type: "spawn",
|
|
383
|
+
source: { agent_id: "system" },
|
|
384
|
+
payload: {
|
|
385
|
+
agent_id: "agent_stopped",
|
|
386
|
+
session_id: "sess_3",
|
|
387
|
+
task: "Stopped agent",
|
|
388
|
+
task_id: "task_3",
|
|
389
|
+
parent: null,
|
|
390
|
+
config: {},
|
|
391
|
+
cwd: "/test",
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
eventStore.emit({
|
|
395
|
+
type: "stop",
|
|
396
|
+
source: { agent_id: "agent_stopped" },
|
|
397
|
+
payload: { reason: "completed" },
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// query_index should return ALL agents (no state filter by default)
|
|
401
|
+
const result = await mapCall<{
|
|
402
|
+
entries: Array<{ type: string; id: string; state?: string }>;
|
|
403
|
+
total: number;
|
|
404
|
+
}>(serverUrl, "_macro/mcp/query_index", {
|
|
405
|
+
context: agentContext("agent_spawning"),
|
|
406
|
+
type: "agents",
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
expect(result.entries.length).toBe(3);
|
|
410
|
+
|
|
411
|
+
const spawning = result.entries.find((e) => e.id === "agent_spawning")!;
|
|
412
|
+
const running = result.entries.find((e) => e.id === "agent_running")!;
|
|
413
|
+
const stopped = result.entries.find((e) => e.id === "agent_stopped")!;
|
|
414
|
+
|
|
415
|
+
expect(spawning.state).toBe("spawning");
|
|
416
|
+
expect(running.state).toBe("running");
|
|
417
|
+
expect(stopped.state).toBe("stopped");
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// ─────────────────────────────────────────────────────────────────
|
|
422
|
+
// MAP subscription visibility (agent_registered events)
|
|
423
|
+
// ─────────────────────────────────────────────────────────────────
|
|
424
|
+
|
|
425
|
+
describe("MAP subscription agent_registered events", () => {
|
|
426
|
+
it("subscriber receives agent_registered when agent is spawned via lifecycle", { timeout: 15_000 }, async () => {
|
|
427
|
+
// Connect a MAP subscriber
|
|
428
|
+
const subscriber = createClient();
|
|
429
|
+
await subscriber.connect();
|
|
430
|
+
const subRes = await subscriber.request("map/subscribe", {
|
|
431
|
+
filter: { eventTypes: ["agent_registered"] },
|
|
432
|
+
});
|
|
433
|
+
expect(subRes.error).toBeUndefined();
|
|
434
|
+
|
|
435
|
+
// Seed an agent via eventStore.emit — this simulates what
|
|
436
|
+
// agentManager.spawn() does internally. However, the lifecycle
|
|
437
|
+
// listener is on agentManager, not eventStore.emit.
|
|
438
|
+
// We need to trigger the lifecycle event.
|
|
439
|
+
//
|
|
440
|
+
// The lifecycle event is fired by notifyLifecycle({ type: "spawned", agent })
|
|
441
|
+
// which is called INSIDE agentManager.spawn() after the agent is created.
|
|
442
|
+
//
|
|
443
|
+
// Since we can't call agentManager.spawn() (needs real processes),
|
|
444
|
+
// we'll directly check if seeding via eventStore.emit triggers
|
|
445
|
+
// the MAP adapter's lifecycle listener.
|
|
446
|
+
|
|
447
|
+
// First, verify direct eventStore.emit does NOT trigger lifecycle
|
|
448
|
+
// (lifecycle is tied to agentManager, not eventStore)
|
|
449
|
+
eventStore.emit({
|
|
450
|
+
type: "spawn",
|
|
451
|
+
source: { agent_id: "system" },
|
|
452
|
+
payload: {
|
|
453
|
+
agent_id: "agent_direct",
|
|
454
|
+
session_id: "sess_direct",
|
|
455
|
+
task: "Direct seed",
|
|
456
|
+
task_id: "task_direct",
|
|
457
|
+
parent: null,
|
|
458
|
+
config: {},
|
|
459
|
+
cwd: "/test",
|
|
460
|
+
},
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
// Wait briefly to see if any notification arrives
|
|
464
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
465
|
+
const directNotifications = subscriber.notifications.filter(
|
|
466
|
+
isEventOfType("agent_registered"),
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
// Direct eventStore.emit bypasses agentManager lifecycle —
|
|
470
|
+
// this tells us whether agent_registered events rely on lifecycle
|
|
471
|
+
console.log(
|
|
472
|
+
`Direct seed produced ${directNotifications.length} agent_registered notifications`,
|
|
473
|
+
);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it("subscriber receives agent_registered with correct data shape for TUI", { timeout: 15_000 }, async () => {
|
|
477
|
+
// Connect subscriber
|
|
478
|
+
const subscriber = createClient();
|
|
479
|
+
await subscriber.connect();
|
|
480
|
+
const subRes = await subscriber.request("map/subscribe", {
|
|
481
|
+
filter: { eventTypes: ["agent_registered", "agent_state_changed"] },
|
|
482
|
+
});
|
|
483
|
+
expect(subRes.error).toBeUndefined();
|
|
484
|
+
|
|
485
|
+
// Use agentManager's lifecycle notification directly if available
|
|
486
|
+
// Seed an agent with proper metadata
|
|
487
|
+
eventStore.emit({
|
|
488
|
+
type: "spawn",
|
|
489
|
+
source: { agent_id: "system" },
|
|
490
|
+
payload: {
|
|
491
|
+
agent_id: "agent_tui_test",
|
|
492
|
+
session_id: "sess_tui",
|
|
493
|
+
task: "TUI visibility test",
|
|
494
|
+
task_id: "task_tui",
|
|
495
|
+
parent: null,
|
|
496
|
+
role: "worker",
|
|
497
|
+
config: {},
|
|
498
|
+
cwd: "/test",
|
|
499
|
+
},
|
|
500
|
+
});
|
|
501
|
+
eventStore.updateAgentMetadata("agent_tui_test" as any, {
|
|
502
|
+
name: "test-agent",
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// Now manually trigger what the MAP adapter's lifecycle listener does
|
|
506
|
+
// by calling emitEvent on the server's MAP adapter.
|
|
507
|
+
// Since we can't access the adapter directly, we check if the
|
|
508
|
+
// onAgentChange listener on eventStore triggers it.
|
|
509
|
+
|
|
510
|
+
// The MAP adapter listens to agentManager.onLifecycleEvent,
|
|
511
|
+
// NOT eventStore.onAgentChange. So direct seeding won't emit
|
|
512
|
+
// MAP events. This is likely part of the bug.
|
|
513
|
+
|
|
514
|
+
// Let's verify by checking if there's an eventStore.onAgentChange
|
|
515
|
+
// listener that could emit agent_registered
|
|
516
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
517
|
+
|
|
518
|
+
console.log(
|
|
519
|
+
`Total notifications after seed: ${subscriber.notifications.length}`,
|
|
520
|
+
);
|
|
521
|
+
console.log(
|
|
522
|
+
`Notification types: ${subscriber.notifications.map((n) => {
|
|
523
|
+
const p = n.params as Record<string, unknown>;
|
|
524
|
+
const e = p?.event as Record<string, unknown>;
|
|
525
|
+
return e?.type;
|
|
526
|
+
}).join(", ")}`,
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
// If no agent_registered notification arrived, the bug is that
|
|
530
|
+
// the MAP adapter only listens to agentManager lifecycle events,
|
|
531
|
+
// but seeding via eventStore.emit (which is what the bridge handler does)
|
|
532
|
+
// doesn't trigger lifecycle events.
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// ─────────────────────────────────────────────────────────────────
|
|
537
|
+
// Spawn via bridge + query visibility (critical integration test)
|
|
538
|
+
// ─────────────────────────────────────────────────────────────────
|
|
539
|
+
|
|
540
|
+
describe("spawn then query integration", () => {
|
|
541
|
+
it("spawn_agent bridge handler makes child visible in query_index", { timeout: 30_000 }, async () => {
|
|
542
|
+
// Seed a root agent (the "caller")
|
|
543
|
+
eventStore.emit({
|
|
544
|
+
type: "spawn",
|
|
545
|
+
source: { agent_id: "system" },
|
|
546
|
+
payload: {
|
|
547
|
+
agent_id: "agent_caller",
|
|
548
|
+
session_id: "sess_caller",
|
|
549
|
+
task: "Caller agent",
|
|
550
|
+
task_id: "task_caller",
|
|
551
|
+
parent: null,
|
|
552
|
+
config: {},
|
|
553
|
+
cwd: "/test/cwd",
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
// Try to spawn a child via the bridge
|
|
558
|
+
// NOTE: This may fail because agentManager.spawn() tries to start
|
|
559
|
+
// a real subprocess via AgentFactory. If it does, we catch and
|
|
560
|
+
// analyze where it fails.
|
|
561
|
+
let spawnedAgentId: string | undefined;
|
|
562
|
+
let spawnError: Error | undefined;
|
|
563
|
+
|
|
564
|
+
try {
|
|
565
|
+
const result = await mapCall<{
|
|
566
|
+
agent_id: string;
|
|
567
|
+
task_id: string;
|
|
568
|
+
session_id: string;
|
|
569
|
+
}>(serverUrl, "_macro/mcp/spawn_agent", {
|
|
570
|
+
context: agentContext("agent_caller", "task_caller"),
|
|
571
|
+
task: "Child task from bridge",
|
|
572
|
+
});
|
|
573
|
+
spawnedAgentId = result.agent_id;
|
|
574
|
+
console.log(`spawn_agent succeeded: ${JSON.stringify(result)}`);
|
|
575
|
+
} catch (err) {
|
|
576
|
+
spawnError = err as Error;
|
|
577
|
+
console.log(`spawn_agent failed: ${spawnError.message}`);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (spawnedAgentId) {
|
|
581
|
+
// Spawn succeeded — verify the child appears in query_index
|
|
582
|
+
const result = await mapCall<{
|
|
583
|
+
entries: Array<{ type: string; id: string; summary: string }>;
|
|
584
|
+
total: number;
|
|
585
|
+
}>(serverUrl, "_macro/mcp/query_index", {
|
|
586
|
+
context: agentContext("agent_caller"),
|
|
587
|
+
type: "agents",
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
console.log(`query_index returned ${result.entries.length} agents:`);
|
|
591
|
+
for (const entry of result.entries) {
|
|
592
|
+
console.log(` ${entry.id}: ${entry.summary}`);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
expect(
|
|
596
|
+
result.entries.some((e) => e.id === spawnedAgentId),
|
|
597
|
+
`Spawned agent ${spawnedAgentId} should appear in query_index`,
|
|
598
|
+
).toBe(true);
|
|
599
|
+
} else {
|
|
600
|
+
// Spawn failed — expected in test env without real processes.
|
|
601
|
+
// Verify the root agent still exists and no orphaned state.
|
|
602
|
+
console.log(
|
|
603
|
+
"spawn_agent requires real process — testing with direct seeding instead",
|
|
604
|
+
);
|
|
605
|
+
|
|
606
|
+
// Directly seed a child (like spawn does internally)
|
|
607
|
+
eventStore.emit({
|
|
608
|
+
type: "spawn",
|
|
609
|
+
source: { agent_id: "agent_caller" },
|
|
610
|
+
payload: {
|
|
611
|
+
agent_id: "agent_child_direct",
|
|
612
|
+
session_id: "sess_child",
|
|
613
|
+
task: "Direct child",
|
|
614
|
+
task_id: "task_child",
|
|
615
|
+
parent: "agent_caller",
|
|
616
|
+
config: {},
|
|
617
|
+
cwd: "/test/cwd",
|
|
618
|
+
},
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
const result = await mapCall<{
|
|
622
|
+
entries: Array<{ type: string; id: string; summary: string }>;
|
|
623
|
+
total: number;
|
|
624
|
+
}>(serverUrl, "_macro/mcp/query_index", {
|
|
625
|
+
context: agentContext("agent_caller"),
|
|
626
|
+
type: "agents",
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
expect(
|
|
630
|
+
result.entries.some((e) => e.id === "agent_child_direct"),
|
|
631
|
+
"Directly seeded child should appear in query_index",
|
|
632
|
+
).toBe(true);
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
it("MAP subscriber receives agent_registered when spawn_agent succeeds", { timeout: 30_000 }, async () => {
|
|
637
|
+
// Set up subscriber first
|
|
638
|
+
const subscriber = createClient();
|
|
639
|
+
await subscriber.connect();
|
|
640
|
+
await subscriber.request("map/subscribe", {
|
|
641
|
+
filter: { eventTypes: ["agent_registered", "agent_state_changed"] },
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
// Seed root agent
|
|
645
|
+
eventStore.emit({
|
|
646
|
+
type: "spawn",
|
|
647
|
+
source: { agent_id: "system" },
|
|
648
|
+
payload: {
|
|
649
|
+
agent_id: "agent_root_sub",
|
|
650
|
+
session_id: "sess_root",
|
|
651
|
+
task: "Root for subscription test",
|
|
652
|
+
task_id: "task_root",
|
|
653
|
+
parent: null,
|
|
654
|
+
config: {},
|
|
655
|
+
cwd: "/test/cwd",
|
|
656
|
+
},
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
// Try spawn via bridge
|
|
660
|
+
let spawnedAgentId: string | undefined;
|
|
661
|
+
try {
|
|
662
|
+
const result = await mapCall<{ agent_id: string }>(
|
|
663
|
+
serverUrl,
|
|
664
|
+
"_macro/mcp/spawn_agent",
|
|
665
|
+
{
|
|
666
|
+
context: agentContext("agent_root_sub", "task_root"),
|
|
667
|
+
task: "Subscriber test child",
|
|
668
|
+
},
|
|
669
|
+
);
|
|
670
|
+
spawnedAgentId = result.agent_id;
|
|
671
|
+
} catch {
|
|
672
|
+
console.log("spawn_agent requires real processes — skipping subscriber verification");
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (spawnedAgentId) {
|
|
676
|
+
// Wait for the agent_registered notification
|
|
677
|
+
const notification = await subscriber.waitForNotification(
|
|
678
|
+
isEventForAgent("agent_registered", spawnedAgentId),
|
|
679
|
+
10000,
|
|
680
|
+
);
|
|
681
|
+
|
|
682
|
+
expect(notification.method).toBe("map/event");
|
|
683
|
+
const params = notification.params as Record<string, unknown>;
|
|
684
|
+
const event = params.event as Record<string, unknown>;
|
|
685
|
+
const data = event.data as Record<string, unknown>;
|
|
686
|
+
|
|
687
|
+
// Verify data shape matches what TUI sync.tsx expects
|
|
688
|
+
expect(data.agentId).toBe(spawnedAgentId);
|
|
689
|
+
expect(data).toHaveProperty("name");
|
|
690
|
+
expect(data).toHaveProperty("role");
|
|
691
|
+
expect(data.role).toBe("worker"); // Defaults to "worker" when not specified
|
|
692
|
+
expect(data).toHaveProperty("state");
|
|
693
|
+
expect(data).toHaveProperty("metadata");
|
|
694
|
+
|
|
695
|
+
console.log("agent_registered event data shape:", JSON.stringify(data, null, 2));
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
// ─────────────────────────────────────────────────────────────────
|
|
701
|
+
// Event shape verification
|
|
702
|
+
// ─────────────────────────────────────────────────────────────────
|
|
703
|
+
|
|
704
|
+
describe("event shape verification for TUI compatibility", () => {
|
|
705
|
+
it("agent_registered notification has SDK format expected by streamEvents", async () => {
|
|
706
|
+
// Connect subscriber
|
|
707
|
+
const subscriber = createClient();
|
|
708
|
+
await subscriber.connect();
|
|
709
|
+
await subscriber.request("map/subscribe", {
|
|
710
|
+
filter: { eventTypes: ["agent_registered"] },
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
// We can't spawn real agents, so let's use the map/replay endpoint
|
|
714
|
+
// to check historical events. First, seed an agent.
|
|
715
|
+
eventStore.emit({
|
|
716
|
+
type: "spawn",
|
|
717
|
+
source: { agent_id: "system" },
|
|
718
|
+
payload: {
|
|
719
|
+
agent_id: "agent_shape_test",
|
|
720
|
+
session_id: "sess_shape",
|
|
721
|
+
task: "Shape test",
|
|
722
|
+
task_id: "task_shape",
|
|
723
|
+
parent: null,
|
|
724
|
+
config: {},
|
|
725
|
+
cwd: "/test",
|
|
726
|
+
},
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
// Use map/replay to see if the spawn was recorded as an agent_registered event
|
|
730
|
+
const replayRes = await subscriber.request("map/replay", {
|
|
731
|
+
filter: { eventTypes: ["agent_registered"] },
|
|
732
|
+
limit: 100,
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
console.log("replay response:", JSON.stringify(replayRes.result, null, 2));
|
|
736
|
+
|
|
737
|
+
// The replay result tells us whether agent_registered events are
|
|
738
|
+
// being recorded. If replay returns empty, the lifecycle listener
|
|
739
|
+
// isn't firing for eventStore.emit-based spawns.
|
|
740
|
+
const result = replayRes.result as {
|
|
741
|
+
events: Array<{ event: { type: string; data: Record<string, unknown> } }>;
|
|
742
|
+
} | null;
|
|
743
|
+
|
|
744
|
+
if (result?.events?.length) {
|
|
745
|
+
// Verify the event shape matches TUI expectations
|
|
746
|
+
const event = result.events[0].event;
|
|
747
|
+
expect(event.type).toBe("agent_registered");
|
|
748
|
+
|
|
749
|
+
// TUI sync.tsx expects data.agentId (line 232-247 of sync.tsx)
|
|
750
|
+
expect(event.data.agentId).toBeDefined();
|
|
751
|
+
console.log("Event data shape:", JSON.stringify(event.data, null, 2));
|
|
752
|
+
} else {
|
|
753
|
+
console.log(
|
|
754
|
+
"No agent_registered events in replay — " +
|
|
755
|
+
"eventStore.emit('spawn') does NOT trigger lifecycle → " +
|
|
756
|
+
"MAP adapter never emits agent_registered for directly seeded agents",
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
});
|
|
761
|
+
});
|