macro-agent 0.1.1 → 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/.sudocode/issues.jsonl +28 -0
- package/.sudocode/specs.jsonl +4 -0
- package/CLAUDE.md +9 -3
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +111 -48
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +7 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/server.d.ts +5 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +100 -3
- 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/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +71 -1
- package/dist/cli/acp.js.map +1 -1
- package/dist/cli/index.js +5 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.js +27 -8
- package/dist/cli/mcp.js.map +1 -1
- package/dist/config/project-config.d.ts +13 -2
- package/dist/config/project-config.d.ts.map +1 -1
- package/dist/config/project-config.js +12 -2
- 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/extensions/index.d.ts +4 -1
- package/dist/map/adapter/extensions/index.d.ts.map +1 -1
- package/dist/map/adapter/extensions/index.js +27 -0
- package/dist/map/adapter/extensions/index.js.map +1 -1
- 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/index.d.ts +1 -1
- package/dist/map/adapter/index.d.ts.map +1 -1
- package/dist/map/adapter/index.js +3 -1
- package/dist/map/adapter/index.js.map +1 -1
- package/dist/map/adapter/types.d.ts +1 -1
- package/dist/map/adapter/types.d.ts.map +1 -1
- package/dist/mcp/mcp-server.d.ts +2 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +12 -3
- 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/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 +6 -0
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +10 -0
- package/dist/roles/capabilities.js.map +1 -1
- package/dist/roles/config-loader.d.ts +1 -1
- package/dist/roles/config-loader.d.ts.map +1 -1
- package/dist/roles/config-loader.js +3 -2
- package/dist/roles/config-loader.js.map +1 -1
- package/dist/roles/types.d.ts +3 -1
- package/dist/roles/types.d.ts.map +1 -1
- package/dist/server/combined-server.d.ts +8 -1
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +6 -2
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +12 -5
- 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 +5 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -1
- package/dist/task/backend/opentasks/daemon-manager.js +1 -1
- package/dist/task/backend/opentasks/daemon-manager.js.map +1 -1
- 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 +6 -2
- package/dist/teams/team-loader.d.ts.map +1 -1
- package/dist/teams/team-loader.js +154 -162
- 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 +527 -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/teams.md +73 -0
- package/package.json +2 -1
- 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/agent/agent-manager.ts +143 -72
- package/src/agent/types.ts +9 -0
- package/src/api/__tests__/server.test.ts +203 -4
- package/src/api/server.ts +130 -5
- package/src/api/types.ts +3 -1
- package/src/cli/acp.ts +68 -1
- package/src/cli/index.ts +5 -1
- package/src/cli/mcp.ts +27 -13
- package/src/config/project-config.ts +27 -3
- package/src/index.ts +3 -0
- 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__/stream-extensions.test.ts +494 -0
- package/src/map/adapter/extensions/index.ts +36 -0
- package/src/map/adapter/extensions/streams.ts +839 -0
- package/src/map/adapter/index.ts +5 -0
- package/src/map/adapter/types.ts +8 -1
- package/src/mcp/mcp-server.ts +14 -3
- package/src/mcp/tools/done.ts +19 -0
- 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 +11 -0
- package/src/roles/config-loader.ts +3 -2
- package/src/roles/types.ts +7 -0
- package/src/server/combined-server.ts +15 -1
- package/src/store/__tests__/event-store-oob.test.ts +109 -0
- package/src/store/event-store.ts +13 -3
- package/src/store/instance.ts +2 -2
- package/src/store/types/agents.ts +5 -0
- package/src/task/backend/__tests__/memory-pull-mode.test.ts +153 -0
- package/src/task/backend/opentasks/daemon-manager.ts +4 -1
- package/src/teams/CLAUDE.md +180 -0
- 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 +200 -234
- package/src/teams/team-manager.ts +387 -0
- package/src/teams/team-runtime.ts +590 -121
- package/src/teams/types.ts +99 -200
|
@@ -493,6 +493,7 @@ export function createAgentManager(
|
|
|
493
493
|
permissionMode: string;
|
|
494
494
|
lineage?: string[];
|
|
495
495
|
sessionId?: string;
|
|
496
|
+
streamId?: string;
|
|
496
497
|
}) {
|
|
497
498
|
// Common env vars for both thin-client and legacy modes
|
|
498
499
|
const env = [
|
|
@@ -509,6 +510,9 @@ export function createAgentManager(
|
|
|
509
510
|
name: "OPENTASKS_SOCKET_PATH",
|
|
510
511
|
value: configOpenTasksSocketPath ?? process.env.OPENTASKS_SOCKET_PATH ?? "",
|
|
511
512
|
},
|
|
513
|
+
// Pass streamId so MCP subprocess can include it in lifecycle context
|
|
514
|
+
// (WorkspaceManager is not available in subprocess)
|
|
515
|
+
{ name: "MACRO_STREAM_ID", value: opts.streamId ?? "" },
|
|
512
516
|
];
|
|
513
517
|
|
|
514
518
|
if (serverUrl) {
|
|
@@ -577,9 +581,11 @@ export function createAgentManager(
|
|
|
577
581
|
interactionPatterns,
|
|
578
582
|
// Workspace-related fields (Phase 2)
|
|
579
583
|
role,
|
|
584
|
+
team_instance,
|
|
580
585
|
streamId,
|
|
581
586
|
streamConfig,
|
|
582
587
|
dataplaneTaskId,
|
|
588
|
+
capabilities,
|
|
583
589
|
} = options;
|
|
584
590
|
|
|
585
591
|
// Generate IDs upfront (including session_id so we can persist before starting MCP)
|
|
@@ -674,6 +680,7 @@ export function createAgentManager(
|
|
|
674
680
|
task_id: taskId,
|
|
675
681
|
parent: parent ?? null,
|
|
676
682
|
role: role ?? undefined,
|
|
683
|
+
team_instance: team_instance ?? undefined,
|
|
677
684
|
config: agentConfig ?? {},
|
|
678
685
|
cwd,
|
|
679
686
|
},
|
|
@@ -708,16 +715,95 @@ export function createAgentManager(
|
|
|
708
715
|
});
|
|
709
716
|
|
|
710
717
|
try {
|
|
718
|
+
// ─────────────────────────────────────────────────────────────────
|
|
719
|
+
// Workspace Creation (before session, so cwd reflects worktree)
|
|
720
|
+
// ─────────────────────────────────────────────────────────────────
|
|
721
|
+
let workspace: Workspace | undefined;
|
|
722
|
+
let resolvedStreamId = streamId;
|
|
723
|
+
|
|
724
|
+
if (workspaceManager && role) {
|
|
725
|
+
try {
|
|
726
|
+
workspace = await createWorkspaceForRole(
|
|
727
|
+
workspaceManager,
|
|
728
|
+
agentId,
|
|
729
|
+
role,
|
|
730
|
+
{
|
|
731
|
+
streamId,
|
|
732
|
+
streamConfig,
|
|
733
|
+
dataplaneTaskId,
|
|
734
|
+
capabilities,
|
|
735
|
+
cwd,
|
|
736
|
+
},
|
|
737
|
+
);
|
|
738
|
+
|
|
739
|
+
if (workspace) {
|
|
740
|
+
agentWorkspaces.set(agentId, workspace);
|
|
741
|
+
resolvedStreamId = workspace.streamId;
|
|
742
|
+
|
|
743
|
+
// Create and claim a dataplane task so the worktree gets a real
|
|
744
|
+
// worker branch. Without this, the worktree stays in detached
|
|
745
|
+
// HEAD and done() would detect "HEAD" instead of the actual
|
|
746
|
+
// worker branch name (e.g. worker/<agentId>/<taskId>).
|
|
747
|
+
if (workspace.role === "worker" && workspace.streamId) {
|
|
748
|
+
try {
|
|
749
|
+
const dpTaskId = workspaceManager.createTask(
|
|
750
|
+
workspace.streamId,
|
|
751
|
+
{ title: task ?? `Task for ${agentId}` },
|
|
752
|
+
);
|
|
753
|
+
workspaceManager.claimTask(dpTaskId, agentId, workspace.path);
|
|
754
|
+
} catch (claimErr) {
|
|
755
|
+
console.error(
|
|
756
|
+
`[AgentManager] Failed to create/claim dataplane task for ${agentId}:`,
|
|
757
|
+
claimErr,
|
|
758
|
+
);
|
|
759
|
+
// Continue without a branch — worktree stays in detached HEAD
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Register with parent coordinator if applicable
|
|
764
|
+
const isChildRole = role === "worker" || role === "integrator" ||
|
|
765
|
+
(capabilities && (capabilities.includes("workspace.worktree") || capabilities.includes("workspace.integrate")));
|
|
766
|
+
if (parent && isChildRole) {
|
|
767
|
+
const parentWorkspace = agentWorkspaces.get(parent);
|
|
768
|
+
if (parentWorkspace?.role === "coordinator") {
|
|
769
|
+
workspaceManager.registerChildWorkspace(
|
|
770
|
+
parent,
|
|
771
|
+
agentId,
|
|
772
|
+
workspace.path,
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
} catch (wsError) {
|
|
778
|
+
console.error(
|
|
779
|
+
`[AgentManager] Failed to create workspace for ${agentId}: ${wsError}`,
|
|
780
|
+
);
|
|
781
|
+
// Continue without workspace — don't fail the spawn
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// Use workspace path as the agent's working directory when available.
|
|
786
|
+
// This ensures the agent process, MCP subprocess (MACRO_AGENT_CWD), and
|
|
787
|
+
// done handler all use the worktree path instead of the repo root.
|
|
788
|
+
const effectiveCwd = workspace?.path ?? cwd;
|
|
789
|
+
|
|
790
|
+
// Update agent's cwd in EventStore so resume() also uses workspace path
|
|
791
|
+
if (workspace) {
|
|
792
|
+
eventStore.updateAgentMetadata(agentId as AgentId, { cwd: effectiveCwd });
|
|
793
|
+
await eventStore.persist();
|
|
794
|
+
}
|
|
795
|
+
|
|
711
796
|
const macroAgentMcp = buildMacroAgentMcp({
|
|
712
797
|
agentId,
|
|
713
798
|
parentId: parent ?? "",
|
|
714
799
|
taskId,
|
|
715
|
-
cwd,
|
|
800
|
+
cwd: effectiveCwd,
|
|
716
801
|
permissionMode,
|
|
717
802
|
lineage: parentAgent?.lineage
|
|
718
803
|
? [...parentAgent.lineage, parent!]
|
|
719
804
|
: [],
|
|
720
805
|
sessionId,
|
|
806
|
+
streamId,
|
|
721
807
|
});
|
|
722
808
|
|
|
723
809
|
// Combine with any user-provided MCP servers
|
|
@@ -744,7 +830,7 @@ export function createAgentManager(
|
|
|
744
830
|
permissionMode === "interactive"
|
|
745
831
|
? { claudeCode: { options: { settingSources: [] } } }
|
|
746
832
|
: undefined;
|
|
747
|
-
const session = await handle.createSession(
|
|
833
|
+
const session = await handle.createSession(effectiveCwd, {
|
|
748
834
|
mcpServers: [macroAgentMcp, ...userMcpServers],
|
|
749
835
|
...(agentMeta && { agentMeta }),
|
|
750
836
|
});
|
|
@@ -834,50 +920,6 @@ export function createAgentManager(
|
|
|
834
920
|
// Get the agent from materialized view
|
|
835
921
|
const agent = eventStore.getAgent(agentId)!;
|
|
836
922
|
|
|
837
|
-
// ─────────────────────────────────────────────────────────────────
|
|
838
|
-
// Workspace Creation (Phase 2)
|
|
839
|
-
// ─────────────────────────────────────────────────────────────────
|
|
840
|
-
let workspace: Workspace | undefined;
|
|
841
|
-
let resolvedStreamId = streamId;
|
|
842
|
-
|
|
843
|
-
if (workspaceManager && role) {
|
|
844
|
-
try {
|
|
845
|
-
workspace = await createWorkspaceForRole(
|
|
846
|
-
workspaceManager,
|
|
847
|
-
agentId,
|
|
848
|
-
role,
|
|
849
|
-
{
|
|
850
|
-
streamId,
|
|
851
|
-
streamConfig,
|
|
852
|
-
dataplaneTaskId,
|
|
853
|
-
cwd,
|
|
854
|
-
},
|
|
855
|
-
);
|
|
856
|
-
|
|
857
|
-
if (workspace) {
|
|
858
|
-
agentWorkspaces.set(agentId, workspace);
|
|
859
|
-
resolvedStreamId = workspace.streamId;
|
|
860
|
-
|
|
861
|
-
// Register with parent coordinator if applicable
|
|
862
|
-
if (parent && (role === "worker" || role === "integrator")) {
|
|
863
|
-
const parentWorkspace = agentWorkspaces.get(parent);
|
|
864
|
-
if (parentWorkspace?.role === "coordinator") {
|
|
865
|
-
workspaceManager.registerChildWorkspace(
|
|
866
|
-
parent,
|
|
867
|
-
agentId,
|
|
868
|
-
workspace.path,
|
|
869
|
-
);
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
} catch (wsError) {
|
|
874
|
-
console.error(
|
|
875
|
-
`[AgentManager] Failed to create workspace for ${agentId}: ${wsError}`,
|
|
876
|
-
);
|
|
877
|
-
// Continue without workspace - don't fail the spawn
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
|
|
881
923
|
// Notify lifecycle listeners
|
|
882
924
|
notifyLifecycle({ type: "spawned", agent });
|
|
883
925
|
notifyLifecycle({ type: "started", agent });
|
|
@@ -1258,6 +1300,7 @@ export function createAgentManager(
|
|
|
1258
1300
|
task_id: taskId,
|
|
1259
1301
|
parent: sourceAgent.parent ?? null,
|
|
1260
1302
|
role: sourceAgent.role ?? undefined,
|
|
1303
|
+
team_instance: sourceAgent.team_instance ?? undefined,
|
|
1261
1304
|
config: {},
|
|
1262
1305
|
cwd,
|
|
1263
1306
|
metadata: { fork_of: sourceAgentId },
|
|
@@ -1971,16 +2014,25 @@ interface CreateWorkspaceOptions {
|
|
|
1971
2014
|
streamId?: string;
|
|
1972
2015
|
streamConfig?: import("../workspace/types.js").StreamConfig;
|
|
1973
2016
|
dataplaneTaskId?: string;
|
|
2017
|
+
capabilities?: string[];
|
|
1974
2018
|
cwd: string;
|
|
1975
2019
|
}
|
|
1976
2020
|
|
|
1977
2021
|
/**
|
|
1978
|
-
* Create a workspace for an agent based on their
|
|
2022
|
+
* Create a workspace for an agent based on their capabilities.
|
|
2023
|
+
*
|
|
2024
|
+
* Dispatches on workspace capabilities (workspace.stream, workspace.integrate,
|
|
2025
|
+
* workspace.worktree) rather than role names. This allows team-defined roles
|
|
2026
|
+
* (e.g., "developer" extending "worker") to get proper workspace allocation
|
|
2027
|
+
* by inheriting workspace capabilities from their base role.
|
|
2028
|
+
*
|
|
2029
|
+
* Falls back to role-name matching for backward compatibility when no
|
|
2030
|
+
* capabilities are provided.
|
|
1979
2031
|
*
|
|
1980
2032
|
* @param workspaceManager - WorkspaceManager instance
|
|
1981
2033
|
* @param agentId - Agent ID
|
|
1982
|
-
* @param role - Agent role (
|
|
1983
|
-
* @param options -
|
|
2034
|
+
* @param role - Agent role name (used for logging and fallback)
|
|
2035
|
+
* @param options - Workspace options including capabilities
|
|
1984
2036
|
* @returns Created workspace or undefined
|
|
1985
2037
|
*/
|
|
1986
2038
|
async function createWorkspaceForRole(
|
|
@@ -1989,66 +2041,85 @@ async function createWorkspaceForRole(
|
|
|
1989
2041
|
role: string,
|
|
1990
2042
|
options: CreateWorkspaceOptions,
|
|
1991
2043
|
): Promise<Workspace | undefined> {
|
|
1992
|
-
const { streamId, streamConfig, dataplaneTaskId } = options;
|
|
2044
|
+
const { streamId, streamConfig, dataplaneTaskId, capabilities } = options;
|
|
2045
|
+
|
|
2046
|
+
// Capability-based dispatch (preferred — works for team-defined roles)
|
|
2047
|
+
if (capabilities && capabilities.length > 0) {
|
|
2048
|
+
if (capabilities.includes("workspace.stream")) {
|
|
2049
|
+
// Coordinator pattern: create integration stream.
|
|
2050
|
+
// In team mode, stream is managed by TeamRuntime.setupWorkspaceIntegration(),
|
|
2051
|
+
// so missing streamConfig is expected — return silently.
|
|
2052
|
+
if (!streamConfig) {
|
|
2053
|
+
return undefined;
|
|
2054
|
+
}
|
|
2055
|
+
const newStreamId = workspaceManager.createIntegrationStream(agentId, streamConfig);
|
|
2056
|
+
return workspaceManager.createCoordinatorWorkspace(agentId, newStreamId);
|
|
2057
|
+
|
|
2058
|
+
} else if (capabilities.includes("workspace.integrate")) {
|
|
2059
|
+
// Integrator pattern: join existing stream
|
|
2060
|
+
if (!streamId) {
|
|
2061
|
+
console.warn(
|
|
2062
|
+
`[AgentManager] ${role} ${agentId} has workspace.integrate but no streamId, skipping workspace`,
|
|
2063
|
+
);
|
|
2064
|
+
return undefined;
|
|
2065
|
+
}
|
|
2066
|
+
return workspaceManager.createIntegratorWorkspace(agentId, streamId);
|
|
1993
2067
|
|
|
2068
|
+
} else if (capabilities.includes("workspace.worktree")) {
|
|
2069
|
+
// Worker pattern: create worktree in stream
|
|
2070
|
+
if (!streamId) {
|
|
2071
|
+
console.warn(
|
|
2072
|
+
`[AgentManager] ${role} ${agentId} has workspace.worktree but no streamId, skipping workspace`,
|
|
2073
|
+
);
|
|
2074
|
+
return undefined;
|
|
2075
|
+
}
|
|
2076
|
+
const taskId = dataplaneTaskId ?? agentId;
|
|
2077
|
+
return workspaceManager.createWorkerWorkspace(agentId, taskId, streamId);
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
// Has capabilities but no workspace capability — no workspace needed
|
|
2081
|
+
return undefined;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
// Fallback: role-name dispatch (backward compatibility for non-team spawns)
|
|
1994
2085
|
switch (role) {
|
|
1995
2086
|
case "coordinator": {
|
|
1996
|
-
// Coordinators create a new integration stream
|
|
1997
2087
|
if (!streamConfig) {
|
|
1998
2088
|
console.warn(
|
|
1999
2089
|
`[AgentManager] Coordinator ${agentId} spawn missing streamConfig, skipping workspace`,
|
|
2000
2090
|
);
|
|
2001
2091
|
return undefined;
|
|
2002
2092
|
}
|
|
2003
|
-
|
|
2004
|
-
const newStreamId = workspaceManager.createIntegrationStream(
|
|
2005
|
-
agentId,
|
|
2006
|
-
streamConfig,
|
|
2007
|
-
);
|
|
2008
|
-
|
|
2093
|
+
const newStreamId = workspaceManager.createIntegrationStream(agentId, streamConfig);
|
|
2009
2094
|
return workspaceManager.createCoordinatorWorkspace(agentId, newStreamId);
|
|
2010
2095
|
}
|
|
2011
2096
|
|
|
2012
2097
|
case "integrator": {
|
|
2013
|
-
// Integrators join an existing stream
|
|
2014
2098
|
if (!streamId) {
|
|
2015
2099
|
console.warn(
|
|
2016
2100
|
`[AgentManager] Integrator ${agentId} spawn missing streamId, skipping workspace`,
|
|
2017
2101
|
);
|
|
2018
2102
|
return undefined;
|
|
2019
2103
|
}
|
|
2020
|
-
|
|
2021
2104
|
return workspaceManager.createIntegratorWorkspace(agentId, streamId);
|
|
2022
2105
|
}
|
|
2023
2106
|
|
|
2024
2107
|
case "worker":
|
|
2025
2108
|
case "worker.resolver": {
|
|
2026
|
-
// Workers need streamId and either dataplaneTaskId or create a new task
|
|
2027
2109
|
if (!streamId) {
|
|
2028
2110
|
console.warn(
|
|
2029
2111
|
`[AgentManager] Worker ${agentId} spawn missing streamId, skipping workspace`,
|
|
2030
2112
|
);
|
|
2031
2113
|
return undefined;
|
|
2032
2114
|
}
|
|
2033
|
-
|
|
2034
|
-
// Use provided task ID or skip (task should be created separately)
|
|
2035
|
-
const taskId = dataplaneTaskId;
|
|
2036
|
-
if (!taskId) {
|
|
2037
|
-
console.warn(
|
|
2038
|
-
`[AgentManager] Worker ${agentId} spawn missing dataplaneTaskId, skipping workspace`,
|
|
2039
|
-
);
|
|
2040
|
-
return undefined;
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2115
|
+
const taskId = dataplaneTaskId ?? agentId;
|
|
2043
2116
|
return workspaceManager.createWorkerWorkspace(agentId, taskId, streamId);
|
|
2044
2117
|
}
|
|
2045
2118
|
|
|
2046
2119
|
case "monitor":
|
|
2047
|
-
// Monitors don't need workspaces
|
|
2048
2120
|
return undefined;
|
|
2049
2121
|
|
|
2050
2122
|
default:
|
|
2051
|
-
// Unknown role - no workspace
|
|
2052
2123
|
return undefined;
|
|
2053
2124
|
}
|
|
2054
2125
|
}
|
package/src/agent/types.ts
CHANGED
|
@@ -74,6 +74,9 @@ export interface SpawnAgentOptions {
|
|
|
74
74
|
*/
|
|
75
75
|
role?: string;
|
|
76
76
|
|
|
77
|
+
/** Team instance ID this agent belongs to (set by TeamManager interceptor) */
|
|
78
|
+
team_instance?: string;
|
|
79
|
+
|
|
77
80
|
/**
|
|
78
81
|
* Stream ID to join (for workers and integrators).
|
|
79
82
|
* Required for workers and integrators when using workspace isolation.
|
|
@@ -91,6 +94,12 @@ export interface SpawnAgentOptions {
|
|
|
91
94
|
* If provided, the worker will claim this task and work on it.
|
|
92
95
|
*/
|
|
93
96
|
dataplaneTaskId?: string;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Resolved capabilities for this agent's role.
|
|
100
|
+
* Injected by TeamRuntime spawn interceptor for capability-based workspace dispatch.
|
|
101
|
+
*/
|
|
102
|
+
capabilities?: string[];
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
/**
|
|
@@ -9,6 +9,7 @@ import type { EventStore } from "../../store/event-store.js";
|
|
|
9
9
|
import type { AgentManager } from "../../agent/agent-manager.js";
|
|
10
10
|
import type { TaskManager } from "../../task/task-manager.js";
|
|
11
11
|
import type { MessageRouter } from "../../router/message-router.js";
|
|
12
|
+
import type { TeamManager, TeamInstance } from "../../teams/team-manager.js";
|
|
12
13
|
import type { Agent, Task, Event } from "../../store/types/index.js";
|
|
13
14
|
|
|
14
15
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -154,6 +155,41 @@ function createMockMessageRouter(): MessageRouter {
|
|
|
154
155
|
};
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
function createMockTeamInstance(overrides: Partial<TeamInstance> = {}): TeamInstance {
|
|
159
|
+
return {
|
|
160
|
+
id: "test-team-1",
|
|
161
|
+
templateName: "test-team",
|
|
162
|
+
runtime: {
|
|
163
|
+
getTaskMode: vi.fn(() => "push"),
|
|
164
|
+
getStrategyName: vi.fn(() => "queue"),
|
|
165
|
+
getManifest: vi.fn(() => ({
|
|
166
|
+
roles: [{ name: "worker", extends: "worker" }],
|
|
167
|
+
communication: { channels: [] },
|
|
168
|
+
})),
|
|
169
|
+
} as any,
|
|
170
|
+
result: {
|
|
171
|
+
rootId: "agent_root1",
|
|
172
|
+
companionIds: ["agent_comp1"],
|
|
173
|
+
},
|
|
174
|
+
...overrides,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function createMockTeamManager(): TeamManager {
|
|
179
|
+
const instance = createMockTeamInstance();
|
|
180
|
+
return {
|
|
181
|
+
startTeam: vi.fn(async () => instance),
|
|
182
|
+
stopTeam: vi.fn(async () => {}),
|
|
183
|
+
teardownAll: vi.fn(async () => {}),
|
|
184
|
+
getTeamForAgent: vi.fn(() => undefined),
|
|
185
|
+
getInstance: vi.fn((id: string) => (id === instance.id ? instance : undefined)),
|
|
186
|
+
getInstances: vi.fn(() => [instance]),
|
|
187
|
+
hasActiveTeam: vi.fn(() => true),
|
|
188
|
+
install: vi.fn(),
|
|
189
|
+
uninstall: vi.fn(),
|
|
190
|
+
} as unknown as TeamManager;
|
|
191
|
+
}
|
|
192
|
+
|
|
157
193
|
// ─────────────────────────────────────────────────────────────────
|
|
158
194
|
// Test Suite
|
|
159
195
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -485,7 +521,7 @@ describe("API Server", () => {
|
|
|
485
521
|
|
|
486
522
|
describe("Graceful Shutdown", () => {
|
|
487
523
|
it("should call eventStore.persist and close on graceful shutdown", async () => {
|
|
488
|
-
const server = createTrackedServer();
|
|
524
|
+
const server = createTrackedServer(services, { port: 0 });
|
|
489
525
|
await server.start();
|
|
490
526
|
await server.stop();
|
|
491
527
|
|
|
@@ -495,7 +531,7 @@ describe("API Server", () => {
|
|
|
495
531
|
});
|
|
496
532
|
|
|
497
533
|
it("should skip grace period on force shutdown", async () => {
|
|
498
|
-
const server = createTrackedServer(services, { shutdownGracePeriodMs: 5000 });
|
|
534
|
+
const server = createTrackedServer(services, { port: 0, shutdownGracePeriodMs: 5000 });
|
|
499
535
|
await server.start();
|
|
500
536
|
|
|
501
537
|
const startTime = Date.now();
|
|
@@ -509,7 +545,7 @@ describe("API Server", () => {
|
|
|
509
545
|
});
|
|
510
546
|
|
|
511
547
|
it("should reject new messages during shutdown", async () => {
|
|
512
|
-
const server = createTrackedServer();
|
|
548
|
+
const server = createTrackedServer(services, { port: 0 });
|
|
513
549
|
await server.start();
|
|
514
550
|
|
|
515
551
|
// Initialize first
|
|
@@ -535,7 +571,7 @@ describe("API Server", () => {
|
|
|
535
571
|
});
|
|
536
572
|
|
|
537
573
|
it("should only shutdown once on multiple stop calls", async () => {
|
|
538
|
-
const server = createTrackedServer();
|
|
574
|
+
const server = createTrackedServer(services, { port: 0 });
|
|
539
575
|
await server.start();
|
|
540
576
|
|
|
541
577
|
// Call stop twice concurrently
|
|
@@ -549,6 +585,7 @@ describe("API Server", () => {
|
|
|
549
585
|
it("should use custom shutdown grace period", async () => {
|
|
550
586
|
const customGracePeriod = 100;
|
|
551
587
|
const server = createTrackedServer(services, {
|
|
588
|
+
port: 0,
|
|
552
589
|
shutdownGracePeriodMs: customGracePeriod,
|
|
553
590
|
});
|
|
554
591
|
await server.start();
|
|
@@ -1012,4 +1049,166 @@ describe("API Server", () => {
|
|
|
1012
1049
|
);
|
|
1013
1050
|
});
|
|
1014
1051
|
});
|
|
1052
|
+
|
|
1053
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1054
|
+
// Team Management API Endpoints
|
|
1055
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1056
|
+
|
|
1057
|
+
describe("Team Management API", () => {
|
|
1058
|
+
let teamManager: TeamManager;
|
|
1059
|
+
|
|
1060
|
+
beforeEach(() => {
|
|
1061
|
+
teamManager = createMockTeamManager();
|
|
1062
|
+
services = { ...services, teamManager };
|
|
1063
|
+
});
|
|
1064
|
+
|
|
1065
|
+
describe("POST /api/teams", () => {
|
|
1066
|
+
it("should start a team instance", async () => {
|
|
1067
|
+
const server = createTrackedServer();
|
|
1068
|
+
const res = await request(server.app)
|
|
1069
|
+
.post("/api/teams")
|
|
1070
|
+
.send({ template: "test-team" });
|
|
1071
|
+
|
|
1072
|
+
expect(res.status).toBe(201);
|
|
1073
|
+
expect(res.body.id).toBe("test-team-1");
|
|
1074
|
+
expect(res.body.templateName).toBe("test-team");
|
|
1075
|
+
expect(res.body.rootAgentId).toBe("agent_root1");
|
|
1076
|
+
expect(res.body.companionAgentIds).toEqual(["agent_comp1"]);
|
|
1077
|
+
expect(res.body.taskMode).toBe("push");
|
|
1078
|
+
expect(res.body.strategy).toBe("queue");
|
|
1079
|
+
expect(teamManager.startTeam).toHaveBeenCalledWith("test-team", expect.any(String), undefined);
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
it("should return 400 when template is missing", async () => {
|
|
1083
|
+
const server = createTrackedServer();
|
|
1084
|
+
const res = await request(server.app)
|
|
1085
|
+
.post("/api/teams")
|
|
1086
|
+
.send({});
|
|
1087
|
+
|
|
1088
|
+
expect(res.status).toBe(400);
|
|
1089
|
+
expect(res.body.code).toBe("INVALID_REQUEST");
|
|
1090
|
+
});
|
|
1091
|
+
|
|
1092
|
+
it("should allow starting multiple teams", async () => {
|
|
1093
|
+
const secondInstance = createMockTeamInstance({
|
|
1094
|
+
id: "second-team-1",
|
|
1095
|
+
templateName: "second-team",
|
|
1096
|
+
});
|
|
1097
|
+
(teamManager.startTeam as any)
|
|
1098
|
+
.mockResolvedValueOnce(createMockTeamInstance())
|
|
1099
|
+
.mockResolvedValueOnce(secondInstance);
|
|
1100
|
+
|
|
1101
|
+
const server = createTrackedServer();
|
|
1102
|
+
|
|
1103
|
+
const res1 = await request(server.app)
|
|
1104
|
+
.post("/api/teams")
|
|
1105
|
+
.send({ template: "test-team" });
|
|
1106
|
+
expect(res1.status).toBe(201);
|
|
1107
|
+
|
|
1108
|
+
const res2 = await request(server.app)
|
|
1109
|
+
.post("/api/teams")
|
|
1110
|
+
.send({ template: "second-team" });
|
|
1111
|
+
expect(res2.status).toBe(201);
|
|
1112
|
+
expect(res2.body.id).toBe("second-team-1");
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
it("should return 500 on start failure", async () => {
|
|
1116
|
+
(teamManager.startTeam as any).mockRejectedValueOnce(
|
|
1117
|
+
new Error("Template not found")
|
|
1118
|
+
);
|
|
1119
|
+
|
|
1120
|
+
const server = createTrackedServer();
|
|
1121
|
+
const res = await request(server.app)
|
|
1122
|
+
.post("/api/teams")
|
|
1123
|
+
.send({ template: "bad-team" });
|
|
1124
|
+
|
|
1125
|
+
expect(res.status).toBe(500);
|
|
1126
|
+
expect(res.body.code).toBe("TEAM_START_FAILED");
|
|
1127
|
+
});
|
|
1128
|
+
});
|
|
1129
|
+
|
|
1130
|
+
describe("GET /api/teams", () => {
|
|
1131
|
+
it("should list running team instances", async () => {
|
|
1132
|
+
const server = createTrackedServer();
|
|
1133
|
+
const res = await request(server.app).get("/api/teams");
|
|
1134
|
+
|
|
1135
|
+
expect(res.status).toBe(200);
|
|
1136
|
+
expect(res.body).toHaveLength(1);
|
|
1137
|
+
expect(res.body[0].id).toBe("test-team-1");
|
|
1138
|
+
expect(res.body[0].templateName).toBe("test-team");
|
|
1139
|
+
expect(res.body[0].rootAgentId).toBe("agent_root1");
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
it("should return empty array when no teams running", async () => {
|
|
1143
|
+
(teamManager.getInstances as any).mockReturnValue([]);
|
|
1144
|
+
|
|
1145
|
+
const server = createTrackedServer();
|
|
1146
|
+
const res = await request(server.app).get("/api/teams");
|
|
1147
|
+
|
|
1148
|
+
expect(res.status).toBe(200);
|
|
1149
|
+
expect(res.body).toEqual([]);
|
|
1150
|
+
});
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
describe("GET /api/teams/:id", () => {
|
|
1154
|
+
it("should return team instance details", async () => {
|
|
1155
|
+
const server = createTrackedServer();
|
|
1156
|
+
const res = await request(server.app).get("/api/teams/test-team-1");
|
|
1157
|
+
|
|
1158
|
+
expect(res.status).toBe(200);
|
|
1159
|
+
expect(res.body.id).toBe("test-team-1");
|
|
1160
|
+
expect(res.body.roles).toBeDefined();
|
|
1161
|
+
expect(res.body.communication).toBeDefined();
|
|
1162
|
+
});
|
|
1163
|
+
|
|
1164
|
+
it("should return 404 for unknown team", async () => {
|
|
1165
|
+
const server = createTrackedServer();
|
|
1166
|
+
const res = await request(server.app).get("/api/teams/nonexistent");
|
|
1167
|
+
|
|
1168
|
+
expect(res.status).toBe(404);
|
|
1169
|
+
expect(res.body.code).toBe("TEAM_NOT_FOUND");
|
|
1170
|
+
});
|
|
1171
|
+
});
|
|
1172
|
+
|
|
1173
|
+
describe("DELETE /api/teams/:id", () => {
|
|
1174
|
+
it("should teardown a team instance", async () => {
|
|
1175
|
+
const server = createTrackedServer();
|
|
1176
|
+
const res = await request(server.app).delete("/api/teams/test-team-1");
|
|
1177
|
+
|
|
1178
|
+
expect(res.status).toBe(200);
|
|
1179
|
+
expect(res.body.success).toBe(true);
|
|
1180
|
+
expect(teamManager.stopTeam).toHaveBeenCalledWith("test-team-1");
|
|
1181
|
+
});
|
|
1182
|
+
|
|
1183
|
+
it("should return 404 for unknown team", async () => {
|
|
1184
|
+
const server = createTrackedServer();
|
|
1185
|
+
const res = await request(server.app).delete("/api/teams/nonexistent");
|
|
1186
|
+
|
|
1187
|
+
expect(res.status).toBe(404);
|
|
1188
|
+
expect(res.body.code).toBe("TEAM_NOT_FOUND");
|
|
1189
|
+
});
|
|
1190
|
+
|
|
1191
|
+
it("should return 500 on stop failure", async () => {
|
|
1192
|
+
(teamManager.stopTeam as any).mockRejectedValueOnce(
|
|
1193
|
+
new Error("Teardown failed")
|
|
1194
|
+
);
|
|
1195
|
+
|
|
1196
|
+
const server = createTrackedServer();
|
|
1197
|
+
const res = await request(server.app).delete("/api/teams/test-team-1");
|
|
1198
|
+
|
|
1199
|
+
expect(res.status).toBe(500);
|
|
1200
|
+
expect(res.body.code).toBe("TEAM_STOP_FAILED");
|
|
1201
|
+
});
|
|
1202
|
+
});
|
|
1203
|
+
|
|
1204
|
+
describe("without teamManager", () => {
|
|
1205
|
+
it("should not register team routes when teamManager is not provided", async () => {
|
|
1206
|
+
const servicesNoTeam = { eventStore, agentManager, taskManager, messageRouter };
|
|
1207
|
+
const server = createTrackedServer(servicesNoTeam);
|
|
1208
|
+
|
|
1209
|
+
const res = await request(server.app).get("/api/teams");
|
|
1210
|
+
expect(res.status).toBe(404);
|
|
1211
|
+
});
|
|
1212
|
+
});
|
|
1213
|
+
});
|
|
1015
1214
|
});
|