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
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { nanoid } from "nanoid";
|
|
11
|
+
import {
|
|
12
|
+
uniqueNamesGenerator,
|
|
13
|
+
adjectives,
|
|
14
|
+
animals,
|
|
15
|
+
} from "unique-names-generator";
|
|
11
16
|
import {
|
|
12
17
|
AgentFactory,
|
|
13
18
|
type Session,
|
|
@@ -50,6 +55,7 @@ import {
|
|
|
50
55
|
type CascadeAgentManager,
|
|
51
56
|
} from "../lifecycle/cascade.js";
|
|
52
57
|
import type { HealthCheckService } from "../monitor/health-check-service.js";
|
|
58
|
+
import { AgentTokenManager } from "../auth/token.js";
|
|
53
59
|
|
|
54
60
|
// ─────────────────────────────────────────────────────────────────
|
|
55
61
|
// Helper Functions
|
|
@@ -103,8 +109,12 @@ export interface AgentManager {
|
|
|
103
109
|
|
|
104
110
|
/**
|
|
105
111
|
* Resume a stopped agent by loading its existing session.
|
|
112
|
+
* @param permissionMode - Optional permission mode override (defaults to the agent manager's default)
|
|
106
113
|
*/
|
|
107
|
-
resume(
|
|
114
|
+
resume(
|
|
115
|
+
agentId: AgentId,
|
|
116
|
+
permissionMode?: PermissionMode,
|
|
117
|
+
): Promise<SpawnedAgent>;
|
|
108
118
|
|
|
109
119
|
/**
|
|
110
120
|
* Continue a terminated agent by spawning a new agent with the same
|
|
@@ -117,7 +127,20 @@ export interface AgentManager {
|
|
|
117
127
|
*/
|
|
118
128
|
continueAgent(
|
|
119
129
|
agentId: AgentId,
|
|
120
|
-
options?: ContinueAgentOptions
|
|
130
|
+
options?: ContinueAgentOptions,
|
|
131
|
+
): Promise<SpawnedAgent>;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Fork an agent's session, creating a new agent with the same
|
|
135
|
+
* conversation history. Uses forkWithFlush for active sessions
|
|
136
|
+
* or loadSession for stopped agents with persisted sessions.
|
|
137
|
+
*
|
|
138
|
+
* @param sourceAgentId - ID of the agent to fork from
|
|
139
|
+
* @param options - Fork options (name, prompt, cwd)
|
|
140
|
+
*/
|
|
141
|
+
forkAgent(
|
|
142
|
+
sourceAgentId: AgentId,
|
|
143
|
+
options?: { name?: string; prompt?: string; cwd?: string },
|
|
121
144
|
): Promise<SpawnedAgent>;
|
|
122
145
|
|
|
123
146
|
// ── Queries ────────────────────────────────────────────────────
|
|
@@ -143,7 +166,7 @@ export interface AgentManager {
|
|
|
143
166
|
*/
|
|
144
167
|
getHierarchy(
|
|
145
168
|
agentId: AgentId,
|
|
146
|
-
options?: HierarchyOptions
|
|
169
|
+
options?: HierarchyOptions,
|
|
147
170
|
): AgentHierarchy | null;
|
|
148
171
|
|
|
149
172
|
// ── Head Manager ───────────────────────────────────────────────
|
|
@@ -166,7 +189,7 @@ export interface AgentManager {
|
|
|
166
189
|
*/
|
|
167
190
|
prompt(
|
|
168
191
|
agentId: AgentId,
|
|
169
|
-
message: string
|
|
192
|
+
message: string,
|
|
170
193
|
): AsyncIterable<ExtendedSessionUpdate>;
|
|
171
194
|
|
|
172
195
|
/**
|
|
@@ -186,7 +209,7 @@ export interface AgentManager {
|
|
|
186
209
|
maxFollowUps?: number;
|
|
187
210
|
/** Callback for each update during prompting */
|
|
188
211
|
onUpdate?: (update: ExtendedSessionUpdate) => void;
|
|
189
|
-
}
|
|
212
|
+
},
|
|
190
213
|
): Promise<{
|
|
191
214
|
doneCalled: boolean;
|
|
192
215
|
doneStatus?: string;
|
|
@@ -235,7 +258,7 @@ export interface AgentManager {
|
|
|
235
258
|
respondToPermission(
|
|
236
259
|
agentId: AgentId,
|
|
237
260
|
requestId: string,
|
|
238
|
-
optionId: string
|
|
261
|
+
optionId: string,
|
|
239
262
|
): boolean;
|
|
240
263
|
|
|
241
264
|
/**
|
|
@@ -247,6 +270,24 @@ export interface AgentManager {
|
|
|
247
270
|
*/
|
|
248
271
|
cancelPermission(agentId: AgentId, requestId: string): boolean;
|
|
249
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Change the permission mode for a running agent at runtime.
|
|
275
|
+
* Takes effect on the next permission request.
|
|
276
|
+
*
|
|
277
|
+
* @param agentId - Agent ID to change permission mode for
|
|
278
|
+
* @param mode - New permission mode
|
|
279
|
+
* @returns true if the mode was changed successfully
|
|
280
|
+
*/
|
|
281
|
+
setPermissionMode(agentId: AgentId, mode: PermissionMode): boolean;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get the current permission mode for a running agent.
|
|
285
|
+
*
|
|
286
|
+
* @param agentId - Agent ID to query
|
|
287
|
+
* @returns The current permission mode, or null if no active session
|
|
288
|
+
*/
|
|
289
|
+
getPermissionMode(agentId: AgentId): PermissionMode | null;
|
|
290
|
+
|
|
250
291
|
// ── Lifecycle Callbacks ────────────────────────────────────────
|
|
251
292
|
|
|
252
293
|
/**
|
|
@@ -260,15 +301,22 @@ export interface AgentManager {
|
|
|
260
301
|
* Set a spawn interceptor that transforms SpawnAgentOptions before spawning.
|
|
261
302
|
* Used by TeamRuntime to inject team topics, prompts, MCP servers, and env vars.
|
|
262
303
|
*/
|
|
263
|
-
setSpawnInterceptor(
|
|
264
|
-
interceptor: SpawnInterceptor | null
|
|
265
|
-
): void;
|
|
304
|
+
setSpawnInterceptor(interceptor: SpawnInterceptor | null): void;
|
|
266
305
|
|
|
267
306
|
/**
|
|
268
307
|
* Get the RoleRegistry used by this AgentManager.
|
|
269
308
|
*/
|
|
270
309
|
getRoleRegistry(): RoleRegistry;
|
|
271
310
|
|
|
311
|
+
// ── OpenTasks Socket Path (Late Binding) ─────────────────────
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Set the runtime OpenTasks socket path for propagation to child agents.
|
|
315
|
+
* Used when createTaskBackend() discovers the daemon socket path after
|
|
316
|
+
* AgentManager is already created.
|
|
317
|
+
*/
|
|
318
|
+
setOpenTasksSocketPath(socketPath: string): void;
|
|
319
|
+
|
|
272
320
|
// ── Mail Services (Late Binding) ─────────────────────────────
|
|
273
321
|
|
|
274
322
|
/**
|
|
@@ -277,7 +325,7 @@ export interface AgentManager {
|
|
|
277
325
|
*/
|
|
278
326
|
setMailServices(
|
|
279
327
|
mailService: import("../mail/mail-service.js").MailService,
|
|
280
|
-
conversationMap: import("../mail/conversation-map.js").ConversationMap
|
|
328
|
+
conversationMap: import("../mail/conversation-map.js").ConversationMap,
|
|
281
329
|
): void;
|
|
282
330
|
|
|
283
331
|
// ── Cleanup ────────────────────────────────────────────────────
|
|
@@ -335,6 +383,38 @@ export interface AgentManagerConfig {
|
|
|
335
383
|
* Required when mailService is provided.
|
|
336
384
|
*/
|
|
337
385
|
conversationMap?: import("../mail/conversation-map.js").ConversationMap;
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Optional server URL for MCP thin-client mode.
|
|
389
|
+
* When set, spawned agents use ephemeral MAP WebSocket calls instead
|
|
390
|
+
* of creating local service stacks.
|
|
391
|
+
*/
|
|
392
|
+
serverUrl?: string;
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Server authentication token for MCP thin-client connections.
|
|
396
|
+
* Passed to spawned agents as MACRO_SERVER_TOKEN env var.
|
|
397
|
+
*/
|
|
398
|
+
serverToken?: string;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Per-agent token manager for MCP bridge authentication.
|
|
402
|
+
* When provided, generates a unique token per agent at spawn time
|
|
403
|
+
* and revokes it on terminate.
|
|
404
|
+
*/
|
|
405
|
+
agentTokenManager?: AgentTokenManager;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Task backend type to propagate to child MCP subprocesses.
|
|
409
|
+
* Sourced from merged config. Falls back to MACRO_TASK_BACKEND env var.
|
|
410
|
+
*/
|
|
411
|
+
taskBackend?: string;
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* OpenTasks socket path to propagate to child MCP subprocesses.
|
|
415
|
+
* Sourced from merged config. Falls back to OPENTASKS_SOCKET_PATH env var.
|
|
416
|
+
*/
|
|
417
|
+
openTasksSocketPath?: string;
|
|
338
418
|
}
|
|
339
419
|
|
|
340
420
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -346,7 +426,7 @@ export interface AgentManagerConfig {
|
|
|
346
426
|
* Used by TeamRuntime to inject team-specific configuration.
|
|
347
427
|
*/
|
|
348
428
|
export type SpawnInterceptor = (
|
|
349
|
-
options: SpawnAgentOptions
|
|
429
|
+
options: SpawnAgentOptions,
|
|
350
430
|
) => SpawnAgentOptions | Promise<SpawnAgentOptions>;
|
|
351
431
|
|
|
352
432
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -356,7 +436,7 @@ export type SpawnInterceptor = (
|
|
|
356
436
|
export function createAgentManager(
|
|
357
437
|
eventStore: EventStore,
|
|
358
438
|
messageRouter: MessageRouter,
|
|
359
|
-
config: AgentManagerConfig = {}
|
|
439
|
+
config: AgentManagerConfig = {},
|
|
360
440
|
): AgentManager {
|
|
361
441
|
const {
|
|
362
442
|
defaultPermissionMode = "auto-approve",
|
|
@@ -367,8 +447,16 @@ export function createAgentManager(
|
|
|
367
447
|
healthCheckService,
|
|
368
448
|
mailService: initialMailService,
|
|
369
449
|
conversationMap: initialConversationMap,
|
|
450
|
+
serverUrl,
|
|
451
|
+
serverToken,
|
|
452
|
+
agentTokenManager,
|
|
453
|
+
taskBackend: configTaskBackend,
|
|
454
|
+
openTasksSocketPath: initialOpenTasksSocketPath,
|
|
370
455
|
} = config;
|
|
371
456
|
|
|
457
|
+
// Mutable OpenTasks socket path (support late binding via setOpenTasksSocketPath)
|
|
458
|
+
let configOpenTasksSocketPath = initialOpenTasksSocketPath;
|
|
459
|
+
|
|
372
460
|
// Mutable mail services (support late binding via setMailServices)
|
|
373
461
|
let mailService = initialMailService;
|
|
374
462
|
let conversationMap = initialConversationMap;
|
|
@@ -385,11 +473,95 @@ export function createAgentManager(
|
|
|
385
473
|
// Lifecycle event listeners
|
|
386
474
|
const lifecycleListeners = new Set<AgentLifecycleCallback>();
|
|
387
475
|
|
|
476
|
+
// Shutdown guard — prevents spawns during close()
|
|
477
|
+
let isShuttingDown = false;
|
|
478
|
+
|
|
479
|
+
// ─────────────────────────────────────────────────────────────────
|
|
480
|
+
// MCP Server Config
|
|
481
|
+
// ─────────────────────────────────────────────────────────────────
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Build the macro-agent MCP server config for a Claude Code agent session.
|
|
485
|
+
* Used by spawn(), resume(), and forkAgent() to ensure every agent gets
|
|
486
|
+
* access to the macro-agent coordination tools.
|
|
487
|
+
*/
|
|
488
|
+
function buildMacroAgentMcp(opts: {
|
|
489
|
+
agentId: string;
|
|
490
|
+
parentId: string;
|
|
491
|
+
taskId: string;
|
|
492
|
+
cwd: string;
|
|
493
|
+
permissionMode: string;
|
|
494
|
+
lineage?: string[];
|
|
495
|
+
sessionId?: string;
|
|
496
|
+
streamId?: string;
|
|
497
|
+
}) {
|
|
498
|
+
// Common env vars for both thin-client and legacy modes
|
|
499
|
+
const env = [
|
|
500
|
+
{ name: "MACRO_AGENT_ID", value: opts.agentId },
|
|
501
|
+
{ name: "MACRO_PARENT_ID", value: opts.parentId },
|
|
502
|
+
{ name: "MACRO_TASK_ID", value: opts.taskId },
|
|
503
|
+
{ name: "MACRO_AGENT_CWD", value: opts.cwd },
|
|
504
|
+
{ name: "MACRO_PERMISSION_MODE", value: opts.permissionMode },
|
|
505
|
+
{
|
|
506
|
+
name: "MACRO_TASK_BACKEND",
|
|
507
|
+
value: configTaskBackend ?? process.env.MACRO_TASK_BACKEND ?? "",
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
name: "OPENTASKS_SOCKET_PATH",
|
|
511
|
+
value: configOpenTasksSocketPath ?? process.env.OPENTASKS_SOCKET_PATH ?? "",
|
|
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 ?? "" },
|
|
516
|
+
];
|
|
517
|
+
|
|
518
|
+
if (serverUrl) {
|
|
519
|
+
// Thin-client mode: forward tool calls to main server via MAP WebSocket
|
|
520
|
+
env.push(
|
|
521
|
+
{ name: "MACRO_SERVER_URL", value: serverUrl },
|
|
522
|
+
{
|
|
523
|
+
name: "MACRO_AGENT_LINEAGE",
|
|
524
|
+
value: JSON.stringify(opts.lineage ?? []),
|
|
525
|
+
},
|
|
526
|
+
{ name: "MACRO_SESSION_ID", value: opts.sessionId ?? "" },
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
// Auth tokens for thin-client connections
|
|
530
|
+
if (serverToken) {
|
|
531
|
+
env.push({ name: "MACRO_SERVER_TOKEN", value: serverToken });
|
|
532
|
+
}
|
|
533
|
+
if (agentTokenManager) {
|
|
534
|
+
const agentToken = agentTokenManager.createToken(opts.agentId);
|
|
535
|
+
env.push({ name: "MACRO_AGENT_TOKEN", value: agentToken });
|
|
536
|
+
}
|
|
537
|
+
} else {
|
|
538
|
+
// Legacy mode: create local service stack with shared SQLite
|
|
539
|
+
env.push(
|
|
540
|
+
{ name: "MACRO_INSTANCE_ID", value: eventStore.instanceId },
|
|
541
|
+
{ name: "MACRO_BASE_DIR", value: eventStore.baseDir },
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return {
|
|
546
|
+
name: "macro-agent",
|
|
547
|
+
command: "npx",
|
|
548
|
+
args: ["multiagent-mcp"],
|
|
549
|
+
env,
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
|
|
388
553
|
// ─────────────────────────────────────────────────────────────────
|
|
389
554
|
// Lifecycle
|
|
390
555
|
// ─────────────────────────────────────────────────────────────────
|
|
391
556
|
|
|
392
557
|
async function spawn(rawOptions: SpawnAgentOptions): Promise<SpawnedAgent> {
|
|
558
|
+
if (isShuttingDown) {
|
|
559
|
+
throw new AgentManagerError(
|
|
560
|
+
"Cannot spawn agent during shutdown",
|
|
561
|
+
"SHUTDOWN_IN_PROGRESS",
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
|
|
393
565
|
// Apply spawn interceptor if set (used by TeamRuntime for team context injection)
|
|
394
566
|
const options = spawnInterceptor
|
|
395
567
|
? await spawnInterceptor(rawOptions)
|
|
@@ -409,9 +581,11 @@ export function createAgentManager(
|
|
|
409
581
|
interactionPatterns,
|
|
410
582
|
// Workspace-related fields (Phase 2)
|
|
411
583
|
role,
|
|
584
|
+
team_instance,
|
|
412
585
|
streamId,
|
|
413
586
|
streamConfig,
|
|
414
587
|
dataplaneTaskId,
|
|
588
|
+
capabilities,
|
|
415
589
|
} = options;
|
|
416
590
|
|
|
417
591
|
// Generate IDs upfront (including session_id so we can persist before starting MCP)
|
|
@@ -426,7 +600,7 @@ export function createAgentManager(
|
|
|
426
600
|
throw new AgentManagerError(
|
|
427
601
|
`Parent agent not found: ${parent}`,
|
|
428
602
|
"AGENT_NOT_FOUND",
|
|
429
|
-
parent
|
|
603
|
+
parent,
|
|
430
604
|
);
|
|
431
605
|
}
|
|
432
606
|
|
|
@@ -437,8 +611,12 @@ export function createAgentManager(
|
|
|
437
611
|
|
|
438
612
|
// Accept either the specific capability (e.g., agent.spawn.grinder)
|
|
439
613
|
// or the generic agent.spawn.custom as a fallback for non-built-in roles
|
|
440
|
-
const hasSpecific = roleRegistry.hasCapability(
|
|
441
|
-
|
|
614
|
+
const hasSpecific = roleRegistry.hasCapability(
|
|
615
|
+
parentRole,
|
|
616
|
+
requiredCapability,
|
|
617
|
+
);
|
|
618
|
+
const hasGeneric =
|
|
619
|
+
requiredCapability !== AGENT_CAPABILITIES.SPAWN_CUSTOM &&
|
|
442
620
|
roleRegistry.hasCapability(parentRole, AGENT_CAPABILITIES.SPAWN_CUSTOM);
|
|
443
621
|
|
|
444
622
|
if (!hasSpecific && !hasGeneric) {
|
|
@@ -446,7 +624,7 @@ export function createAgentManager(
|
|
|
446
624
|
`Parent agent with role '${parentRole}' does not have capability to spawn '${childRole}' agents. ` +
|
|
447
625
|
`Required capability: ${requiredCapability}`,
|
|
448
626
|
"CAPABILITY_DENIED",
|
|
449
|
-
parent
|
|
627
|
+
parent,
|
|
450
628
|
);
|
|
451
629
|
}
|
|
452
630
|
}
|
|
@@ -502,11 +680,20 @@ export function createAgentManager(
|
|
|
502
680
|
task_id: taskId,
|
|
503
681
|
parent: parent ?? null,
|
|
504
682
|
role: role ?? undefined,
|
|
683
|
+
team_instance: team_instance ?? undefined,
|
|
505
684
|
config: agentConfig ?? {},
|
|
506
685
|
cwd,
|
|
507
686
|
},
|
|
508
687
|
});
|
|
509
688
|
|
|
689
|
+
// Generate a human-readable default name
|
|
690
|
+
const generatedName = uniqueNamesGenerator({
|
|
691
|
+
dictionaries: [adjectives, animals],
|
|
692
|
+
separator: "-",
|
|
693
|
+
length: 2,
|
|
694
|
+
});
|
|
695
|
+
eventStore.updateAgentMetadata(agentId as AgentId, { name: generatedName });
|
|
696
|
+
|
|
510
697
|
// Persist immediately so MCP server subprocess can read the agent
|
|
511
698
|
await eventStore.persist();
|
|
512
699
|
|
|
@@ -514,10 +701,10 @@ export function createAgentManager(
|
|
|
514
701
|
const verifyAgent = eventStore.getAgent(agentId);
|
|
515
702
|
const allAgents = eventStore.listAgents();
|
|
516
703
|
console.error(
|
|
517
|
-
`[AgentManager] After persist: agent ${agentId} exists = ${!!verifyAgent}, total agents = ${allAgents.length}, instancePath = ${eventStore.instancePath}
|
|
704
|
+
`[AgentManager] After persist: agent ${agentId} exists = ${!!verifyAgent}, total agents = ${allAgents.length}, instancePath = ${eventStore.instancePath}`,
|
|
518
705
|
);
|
|
519
706
|
console.error(
|
|
520
|
-
`[AgentManager] All agent IDs: ${allAgents.map((a) => a.id).join(", ")}
|
|
707
|
+
`[AgentManager] All agent IDs: ${allAgents.map((a) => a.id).join(", ")}`,
|
|
521
708
|
);
|
|
522
709
|
|
|
523
710
|
try {
|
|
@@ -527,195 +714,242 @@ export function createAgentManager(
|
|
|
527
714
|
env: agentConfig?.env,
|
|
528
715
|
});
|
|
529
716
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
args: ["multiagent-mcp"],
|
|
537
|
-
env: [
|
|
538
|
-
{ name: "MACRO_AGENT_ID", value: agentId },
|
|
539
|
-
{ name: "MACRO_PARENT_ID", value: parent ?? "" },
|
|
540
|
-
{ name: "MACRO_TASK_ID", value: taskId },
|
|
541
|
-
{ name: "MACRO_AGENT_CWD", value: cwd },
|
|
542
|
-
{ name: "MACRO_INSTANCE_ID", value: eventStore.instanceId },
|
|
543
|
-
{ name: "MACRO_BASE_DIR", value: eventStore.baseDir },
|
|
544
|
-
],
|
|
545
|
-
};
|
|
717
|
+
try {
|
|
718
|
+
// ─────────────────────────────────────────────────────────────────
|
|
719
|
+
// Workspace Creation (before session, so cwd reflects worktree)
|
|
720
|
+
// ─────────────────────────────────────────────────────────────────
|
|
721
|
+
let workspace: Workspace | undefined;
|
|
722
|
+
let resolvedStreamId = streamId;
|
|
546
723
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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
|
+
}
|
|
558
762
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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
|
+
}
|
|
565
784
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
type: "status",
|
|
571
|
-
source: { agent_id: agentId },
|
|
572
|
-
payload: {
|
|
573
|
-
status_type: "started",
|
|
574
|
-
summary: "Agent session started",
|
|
575
|
-
provider_session_id: session.id,
|
|
576
|
-
},
|
|
577
|
-
});
|
|
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;
|
|
578
789
|
|
|
579
|
-
|
|
580
|
-
|
|
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
|
+
}
|
|
581
795
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
796
|
+
const macroAgentMcp = buildMacroAgentMcp({
|
|
797
|
+
agentId,
|
|
798
|
+
parentId: parent ?? "",
|
|
799
|
+
taskId,
|
|
800
|
+
cwd: effectiveCwd,
|
|
801
|
+
permissionMode,
|
|
802
|
+
lineage: parentAgent?.lineage
|
|
803
|
+
? [...parentAgent.lineage, parent!]
|
|
804
|
+
: [],
|
|
805
|
+
sessionId,
|
|
806
|
+
streamId,
|
|
807
|
+
});
|
|
591
808
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
809
|
+
// Combine with any user-provided MCP servers
|
|
810
|
+
// Note: Like macroAgentMcp, user MCP servers use stdio (no 'type' field)
|
|
811
|
+
const userMcpServers =
|
|
812
|
+
agentConfig?.mcpServers?.map((s) => ({
|
|
813
|
+
name: s.name,
|
|
814
|
+
command: s.command,
|
|
815
|
+
args: s.args ?? [],
|
|
816
|
+
env: s.env
|
|
817
|
+
? Object.entries(s.env).map(([name, value]) => ({ name, value }))
|
|
818
|
+
: [],
|
|
819
|
+
})) ?? [];
|
|
820
|
+
|
|
821
|
+
// Create session with MCP servers
|
|
822
|
+
// Note: The MCP server subprocess will start here and look for the agent
|
|
823
|
+
// in EventStore. We already persisted the spawn event above.
|
|
824
|
+
//
|
|
825
|
+
// When permissionMode is "interactive", we strip settingSources so that
|
|
826
|
+
// the Claude Code subprocess doesn't read pre-approved tool rules from
|
|
827
|
+
// the user's ~/.claude/settings.local.json. This ensures ALL tool calls
|
|
828
|
+
// go through the canUseTool → requestPermission ACP flow.
|
|
829
|
+
const agentMeta =
|
|
830
|
+
permissionMode === "interactive"
|
|
831
|
+
? { claudeCode: { options: { settingSources: [] } } }
|
|
600
832
|
: undefined;
|
|
833
|
+
const session = await handle.createSession(effectiveCwd, {
|
|
834
|
+
mcpServers: [macroAgentMcp, ...userMcpServers],
|
|
835
|
+
...(agentMeta && { agentMeta }),
|
|
836
|
+
});
|
|
601
837
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
838
|
+
// Emit started status (session is ready)
|
|
839
|
+
// Include the provider's session ID (e.g., Claude Code UUID) so
|
|
840
|
+
// it can be used for handle.loadSession() during resume
|
|
841
|
+
eventStore.emit({
|
|
842
|
+
type: "status",
|
|
843
|
+
source: { agent_id: agentId },
|
|
844
|
+
payload: {
|
|
845
|
+
status_type: "started",
|
|
846
|
+
summary: "Agent session started",
|
|
847
|
+
provider_session_id: session.id,
|
|
848
|
+
},
|
|
849
|
+
});
|
|
609
850
|
|
|
610
|
-
|
|
611
|
-
|
|
851
|
+
// Persist the status event
|
|
852
|
+
await eventStore.persist();
|
|
853
|
+
|
|
854
|
+
// Set up default subscriptions via MessageRouter
|
|
855
|
+
messageRouter.setupDefaultSubscriptions({
|
|
856
|
+
agent_id: agentId,
|
|
857
|
+
parent_id: parent ?? undefined,
|
|
858
|
+
task_id: taskId,
|
|
859
|
+
subscribe_parent: subscribeParent,
|
|
860
|
+
additional_topics: topics,
|
|
861
|
+
role: role ?? undefined,
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
// ─────────────────────────────────────────────────────────────────
|
|
865
|
+
// Mail: Create task conversation for this agent
|
|
866
|
+
// ─────────────────────────────────────────────────────────────────
|
|
867
|
+
if (mailService && conversationMap) {
|
|
868
|
+
try {
|
|
869
|
+
const parentConversationId = parent
|
|
870
|
+
? (conversationMap.getAgentConversation(parent) ??
|
|
871
|
+
conversationMap.getSessionConversation(parent))
|
|
872
|
+
: undefined;
|
|
873
|
+
|
|
874
|
+
const { conversationId: taskConvId } =
|
|
875
|
+
mailService.createConversation({
|
|
876
|
+
type: "task",
|
|
877
|
+
subject: task?.slice(0, 80),
|
|
878
|
+
createdBy: parent ?? agentId,
|
|
879
|
+
parentConversationId: parentConversationId,
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
// Join parent and child as participants
|
|
883
|
+
if (parent) {
|
|
884
|
+
mailService.joinConversation({
|
|
885
|
+
conversationId: taskConvId,
|
|
886
|
+
participantId: parent,
|
|
887
|
+
participantType: "agent",
|
|
888
|
+
role: "initiator",
|
|
889
|
+
agentId: parent,
|
|
890
|
+
});
|
|
891
|
+
}
|
|
612
892
|
mailService.joinConversation({
|
|
613
893
|
conversationId: taskConvId,
|
|
614
|
-
participantId:
|
|
894
|
+
participantId: agentId,
|
|
615
895
|
participantType: "agent",
|
|
616
|
-
role: "
|
|
617
|
-
agentId
|
|
896
|
+
role: "worker",
|
|
897
|
+
agentId,
|
|
618
898
|
});
|
|
619
|
-
}
|
|
620
|
-
mailService.joinConversation({
|
|
621
|
-
conversationId: taskConvId,
|
|
622
|
-
participantId: agentId,
|
|
623
|
-
participantType: "agent",
|
|
624
|
-
role: "worker",
|
|
625
|
-
agentId,
|
|
626
|
-
});
|
|
627
899
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
900
|
+
conversationMap.setAgentConversation(agentId, taskConvId);
|
|
901
|
+
} catch (err) {
|
|
902
|
+
// Never fail spawn due to mail errors
|
|
903
|
+
console.warn(
|
|
904
|
+
`[AgentManager] Failed to create task conversation for ${agentId}:`,
|
|
905
|
+
err,
|
|
906
|
+
);
|
|
907
|
+
}
|
|
635
908
|
}
|
|
636
|
-
}
|
|
637
909
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
910
|
+
// Track active session
|
|
911
|
+
const activeSession: ActiveSession = {
|
|
912
|
+
agentId,
|
|
913
|
+
handle,
|
|
914
|
+
session,
|
|
915
|
+
createdAt: Date.now(),
|
|
916
|
+
isPrompting: false,
|
|
917
|
+
};
|
|
918
|
+
activeSessions.set(agentId, activeSession);
|
|
647
919
|
|
|
648
|
-
|
|
649
|
-
|
|
920
|
+
// Get the agent from materialized view
|
|
921
|
+
const agent = eventStore.getAgent(agentId)!;
|
|
650
922
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
let workspace: Workspace | undefined;
|
|
655
|
-
let resolvedStreamId = streamId;
|
|
923
|
+
// Notify lifecycle listeners
|
|
924
|
+
notifyLifecycle({ type: "spawned", agent });
|
|
925
|
+
notifyLifecycle({ type: "started", agent });
|
|
656
926
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
workspaceManager,
|
|
661
|
-
agentId,
|
|
662
|
-
role,
|
|
663
|
-
{
|
|
664
|
-
streamId,
|
|
665
|
-
streamConfig,
|
|
666
|
-
dataplaneTaskId,
|
|
667
|
-
cwd,
|
|
668
|
-
}
|
|
669
|
-
);
|
|
670
|
-
|
|
671
|
-
if (workspace) {
|
|
672
|
-
agentWorkspaces.set(agentId, workspace);
|
|
673
|
-
resolvedStreamId = workspace.streamId;
|
|
674
|
-
|
|
675
|
-
// Register with parent coordinator if applicable
|
|
676
|
-
if (
|
|
677
|
-
parent &&
|
|
678
|
-
(role === "worker" || role === "integrator")
|
|
679
|
-
) {
|
|
680
|
-
const parentWorkspace = agentWorkspaces.get(parent);
|
|
681
|
-
if (parentWorkspace?.role === "coordinator") {
|
|
682
|
-
workspaceManager.registerChildWorkspace(
|
|
683
|
-
parent,
|
|
684
|
-
agentId,
|
|
685
|
-
workspace.path
|
|
686
|
-
);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
} catch (wsError) {
|
|
691
|
-
console.error(
|
|
692
|
-
`[AgentManager] Failed to create workspace for ${agentId}: ${wsError}`
|
|
693
|
-
);
|
|
694
|
-
// Continue without workspace - don't fail the spawn
|
|
927
|
+
// Start health monitoring for coordinators
|
|
928
|
+
if (healthCheckService && role === "coordinator") {
|
|
929
|
+
healthCheckService.startForCoordinator(agentId);
|
|
695
930
|
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
// Notify lifecycle listeners
|
|
699
|
-
notifyLifecycle({ type: "spawned", agent });
|
|
700
|
-
notifyLifecycle({ type: "started", agent });
|
|
701
931
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
932
|
+
return {
|
|
933
|
+
id: agentId,
|
|
934
|
+
session_id: sessionId, // Macro-agent's own session ID for ACP protocol mapping
|
|
935
|
+
agent,
|
|
936
|
+
session,
|
|
937
|
+
workspace,
|
|
938
|
+
streamId: resolvedStreamId,
|
|
939
|
+
};
|
|
940
|
+
} catch (handleError) {
|
|
941
|
+
// Close the spawned process to prevent orphaning
|
|
942
|
+
try {
|
|
943
|
+
await handle.close();
|
|
944
|
+
} catch {
|
|
945
|
+
// Ignore errors during cleanup
|
|
946
|
+
}
|
|
947
|
+
throw handleError;
|
|
705
948
|
}
|
|
706
|
-
|
|
707
|
-
return {
|
|
708
|
-
id: agentId,
|
|
709
|
-
session_id: sessionId, // Macro-agent's own session ID for ACP protocol mapping
|
|
710
|
-
agent,
|
|
711
|
-
session,
|
|
712
|
-
workspace,
|
|
713
|
-
streamId: resolvedStreamId,
|
|
714
|
-
};
|
|
715
949
|
} catch (error) {
|
|
716
950
|
// Clean up the spawn event we already emitted
|
|
717
951
|
eventStore.emit({
|
|
718
|
-
type: "
|
|
952
|
+
type: "stop",
|
|
719
953
|
source: { agent_id: agentId },
|
|
720
954
|
payload: {
|
|
721
955
|
reason: "failed",
|
|
@@ -726,21 +960,21 @@ export function createAgentManager(
|
|
|
726
960
|
throw new AgentManagerError(
|
|
727
961
|
`Failed to spawn agent: ${error}`,
|
|
728
962
|
"SPAWN_FAILED",
|
|
729
|
-
agentId
|
|
963
|
+
agentId,
|
|
730
964
|
);
|
|
731
965
|
}
|
|
732
966
|
}
|
|
733
967
|
|
|
734
968
|
async function terminate(
|
|
735
969
|
agentId: AgentId,
|
|
736
|
-
reason: AgentStopReason
|
|
970
|
+
reason: AgentStopReason,
|
|
737
971
|
): Promise<void> {
|
|
738
972
|
const agent = eventStore.getAgent(agentId);
|
|
739
973
|
if (!agent) {
|
|
740
974
|
throw new AgentManagerError(
|
|
741
975
|
`Agent not found: ${agentId}`,
|
|
742
976
|
"AGENT_NOT_FOUND",
|
|
743
|
-
agentId
|
|
977
|
+
agentId,
|
|
744
978
|
);
|
|
745
979
|
}
|
|
746
980
|
|
|
@@ -769,12 +1003,17 @@ export function createAgentManager(
|
|
|
769
1003
|
agentWorkspaces.delete(agentId);
|
|
770
1004
|
} catch (wsError) {
|
|
771
1005
|
console.error(
|
|
772
|
-
`[AgentManager] Failed to deallocate workspace for ${agentId}: ${wsError}
|
|
1006
|
+
`[AgentManager] Failed to deallocate workspace for ${agentId}: ${wsError}`,
|
|
773
1007
|
);
|
|
774
1008
|
// Continue with termination even if workspace cleanup fails
|
|
775
1009
|
}
|
|
776
1010
|
}
|
|
777
1011
|
|
|
1012
|
+
// Revoke agent authentication token
|
|
1013
|
+
if (agentTokenManager) {
|
|
1014
|
+
agentTokenManager.revokeToken(agentId);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
778
1017
|
// ─────────────────────────────────────────────────────────────────
|
|
779
1018
|
// Mail: Close task conversation on terminate
|
|
780
1019
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -789,8 +1028,7 @@ export function createAgentManager(
|
|
|
789
1028
|
});
|
|
790
1029
|
}
|
|
791
1030
|
// Close any peer conversations
|
|
792
|
-
const peerConvIds =
|
|
793
|
-
conversationMap.closePeerConversationsFor(agentId);
|
|
1031
|
+
const peerConvIds = conversationMap.closePeerConversationsFor(agentId);
|
|
794
1032
|
for (const peerConvId of peerConvIds) {
|
|
795
1033
|
mailService.closeConversation({
|
|
796
1034
|
conversationId: peerConvId,
|
|
@@ -802,14 +1040,14 @@ export function createAgentManager(
|
|
|
802
1040
|
} catch (err) {
|
|
803
1041
|
console.warn(
|
|
804
1042
|
`[AgentManager] Failed to close conversation for ${agentId}:`,
|
|
805
|
-
err
|
|
1043
|
+
err,
|
|
806
1044
|
);
|
|
807
1045
|
}
|
|
808
1046
|
}
|
|
809
1047
|
|
|
810
|
-
// Emit
|
|
1048
|
+
// Emit stop event
|
|
811
1049
|
eventStore.emit({
|
|
812
|
-
type: "
|
|
1050
|
+
type: "stop",
|
|
813
1051
|
source: { agent_id: agentId },
|
|
814
1052
|
payload: {
|
|
815
1053
|
agent_id: agentId,
|
|
@@ -876,19 +1114,30 @@ export function createAgentManager(
|
|
|
876
1114
|
child.id,
|
|
877
1115
|
agentId,
|
|
878
1116
|
cascadeAdapter,
|
|
879
|
-
workspaceProvider
|
|
1117
|
+
workspaceProvider,
|
|
880
1118
|
);
|
|
881
1119
|
}
|
|
882
1120
|
}
|
|
883
1121
|
}
|
|
884
1122
|
|
|
885
|
-
async function resume(
|
|
1123
|
+
async function resume(
|
|
1124
|
+
agentId: AgentId,
|
|
1125
|
+
overridePermissionMode?: PermissionMode,
|
|
1126
|
+
): Promise<SpawnedAgent> {
|
|
1127
|
+
if (isShuttingDown) {
|
|
1128
|
+
throw new AgentManagerError(
|
|
1129
|
+
"Cannot resume agent during shutdown",
|
|
1130
|
+
"SHUTDOWN_IN_PROGRESS",
|
|
1131
|
+
agentId,
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
886
1135
|
const agent = eventStore.getAgent(agentId);
|
|
887
1136
|
if (!agent) {
|
|
888
1137
|
throw new AgentManagerError(
|
|
889
1138
|
`Agent not found: ${agentId}`,
|
|
890
1139
|
"AGENT_NOT_FOUND",
|
|
891
|
-
agentId
|
|
1140
|
+
agentId,
|
|
892
1141
|
);
|
|
893
1142
|
}
|
|
894
1143
|
|
|
@@ -897,66 +1146,261 @@ export function createAgentManager(
|
|
|
897
1146
|
throw new AgentManagerError(
|
|
898
1147
|
`Agent already has active session: ${agentId}`,
|
|
899
1148
|
"ALREADY_RUNNING",
|
|
900
|
-
agentId
|
|
1149
|
+
agentId,
|
|
901
1150
|
);
|
|
902
1151
|
}
|
|
903
1152
|
|
|
1153
|
+
const permissionMode = overridePermissionMode ?? defaultPermissionMode;
|
|
1154
|
+
|
|
904
1155
|
// Spawn new process
|
|
905
1156
|
const handle = await AgentFactory.spawn(defaultAgentType, {
|
|
906
|
-
permissionMode
|
|
1157
|
+
permissionMode,
|
|
907
1158
|
});
|
|
908
1159
|
|
|
909
|
-
|
|
910
|
-
|
|
1160
|
+
try {
|
|
1161
|
+
const agentCwd = agent.cwd ?? defaultCwd;
|
|
1162
|
+
let session;
|
|
911
1163
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
1164
|
+
// When interactive mode, strip settings to prevent auto-approval
|
|
1165
|
+
const resumeAgentMeta =
|
|
1166
|
+
permissionMode === "interactive"
|
|
1167
|
+
? { claudeCode: { options: { settingSources: [] } } }
|
|
1168
|
+
: undefined;
|
|
1169
|
+
|
|
1170
|
+
const macroAgentMcp = buildMacroAgentMcp({
|
|
1171
|
+
agentId,
|
|
1172
|
+
parentId: agent.parent ?? "",
|
|
1173
|
+
taskId: agent.task_id ?? "",
|
|
1174
|
+
cwd: agentCwd,
|
|
1175
|
+
permissionMode,
|
|
1176
|
+
lineage: agent.lineage ?? [],
|
|
1177
|
+
sessionId: agent.session_id ?? "",
|
|
1178
|
+
});
|
|
1179
|
+
const mcpServers = [macroAgentMcp];
|
|
1180
|
+
|
|
1181
|
+
if (agent.provider_session_id) {
|
|
1182
|
+
// Load existing session using the provider's session ID (e.g., Claude Code UUID)
|
|
1183
|
+
// Note: loadSession's TS type for mcpServers is { name, uri }[] but
|
|
1184
|
+
// the underlying ACP protocol accepts full McpServerStdio. The JS
|
|
1185
|
+
// implementation passes mcpServers through to the connection unchanged.
|
|
1186
|
+
session = await handle.loadSession(
|
|
1187
|
+
agent.provider_session_id,
|
|
1188
|
+
agentCwd,
|
|
1189
|
+
mcpServers as any,
|
|
1190
|
+
resumeAgentMeta ? { agentMeta: resumeAgentMeta } : undefined,
|
|
1191
|
+
);
|
|
1192
|
+
} else {
|
|
1193
|
+
// No provider session ID available (agent predates this feature or wasn't persisted).
|
|
1194
|
+
// Create a new session instead of loading with the macro-agent session_id
|
|
1195
|
+
// which is not a valid provider session ID (e.g., Claude Code expects UUIDs).
|
|
1196
|
+
session = await handle.createSession(agentCwd, {
|
|
1197
|
+
mcpServers,
|
|
1198
|
+
...(resumeAgentMeta && { agentMeta: resumeAgentMeta }),
|
|
1199
|
+
});
|
|
1200
|
+
|
|
1201
|
+
// Store the provider session ID for future resumes
|
|
1202
|
+
eventStore.emit({
|
|
1203
|
+
type: "status",
|
|
1204
|
+
source: { agent_id: agentId },
|
|
1205
|
+
payload: {
|
|
1206
|
+
status_type: "started",
|
|
1207
|
+
summary: "Agent session created (no provider session to resume)",
|
|
1208
|
+
provider_session_id: session.id,
|
|
1209
|
+
},
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
// Track active session
|
|
1214
|
+
const activeSession: ActiveSession = {
|
|
1215
|
+
agentId,
|
|
1216
|
+
handle,
|
|
1217
|
+
session,
|
|
1218
|
+
createdAt: Date.now(),
|
|
1219
|
+
isPrompting: false,
|
|
1220
|
+
};
|
|
1221
|
+
activeSessions.set(agentId, activeSession);
|
|
920
1222
|
|
|
921
|
-
//
|
|
1223
|
+
// Emit status event for resume
|
|
922
1224
|
eventStore.emit({
|
|
923
1225
|
type: "status",
|
|
924
1226
|
source: { agent_id: agentId },
|
|
925
1227
|
payload: {
|
|
926
1228
|
status_type: "started",
|
|
927
|
-
summary: "Agent session
|
|
1229
|
+
summary: "Agent session resumed",
|
|
928
1230
|
provider_session_id: session.id,
|
|
929
1231
|
},
|
|
930
1232
|
});
|
|
1233
|
+
|
|
1234
|
+
return {
|
|
1235
|
+
id: agentId,
|
|
1236
|
+
session_id: agent.session_id, // Macro-agent's own session ID
|
|
1237
|
+
agent: eventStore.getAgent(agentId)!,
|
|
1238
|
+
session,
|
|
1239
|
+
};
|
|
1240
|
+
} catch (handleError) {
|
|
1241
|
+
// Close the spawned process to prevent orphaning
|
|
1242
|
+
try {
|
|
1243
|
+
await handle.close();
|
|
1244
|
+
} catch {
|
|
1245
|
+
// Ignore errors during cleanup
|
|
1246
|
+
}
|
|
1247
|
+
throw handleError;
|
|
931
1248
|
}
|
|
1249
|
+
}
|
|
932
1250
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
handle,
|
|
937
|
-
session,
|
|
938
|
-
createdAt: Date.now(),
|
|
939
|
-
isPrompting: false,
|
|
940
|
-
};
|
|
941
|
-
activeSessions.set(agentId, activeSession);
|
|
1251
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1252
|
+
// Fork
|
|
1253
|
+
// ─────────────────────────────────────────────────────────────────
|
|
942
1254
|
|
|
943
|
-
|
|
1255
|
+
async function forkAgent(
|
|
1256
|
+
sourceAgentId: AgentId,
|
|
1257
|
+
options?: { name?: string; prompt?: string; cwd?: string },
|
|
1258
|
+
): Promise<SpawnedAgent> {
|
|
1259
|
+
if (isShuttingDown) {
|
|
1260
|
+
throw new AgentManagerError(
|
|
1261
|
+
"Cannot fork agent during shutdown",
|
|
1262
|
+
"SHUTDOWN_IN_PROGRESS",
|
|
1263
|
+
sourceAgentId,
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
const sourceAgent = eventStore.getAgent(sourceAgentId);
|
|
1268
|
+
if (!sourceAgent) {
|
|
1269
|
+
throw new AgentManagerError(
|
|
1270
|
+
`Agent not found: ${sourceAgentId}`,
|
|
1271
|
+
"AGENT_NOT_FOUND",
|
|
1272
|
+
sourceAgentId,
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
// Need either an active session or a persisted provider_session_id
|
|
1277
|
+
const activeSession = activeSessions.get(sourceAgentId);
|
|
1278
|
+
if (!activeSession && !sourceAgent.provider_session_id) {
|
|
1279
|
+
throw new AgentManagerError(
|
|
1280
|
+
`Agent has no session to fork: ${sourceAgentId}`,
|
|
1281
|
+
"FORK_NOT_SUPPORTED",
|
|
1282
|
+
sourceAgentId,
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// Generate new IDs
|
|
1287
|
+
const agentId = `agent_${nanoid(12)}`;
|
|
1288
|
+
const taskId = `task_${nanoid(12)}`;
|
|
1289
|
+
const sessionId = `session_${nanoid(12)}`;
|
|
1290
|
+
const cwd = options?.cwd ?? sourceAgent.cwd ?? defaultCwd;
|
|
1291
|
+
|
|
1292
|
+
// Emit spawn event with fork metadata
|
|
944
1293
|
eventStore.emit({
|
|
945
|
-
type: "
|
|
946
|
-
source: { agent_id:
|
|
1294
|
+
type: "spawn",
|
|
1295
|
+
source: { agent_id: sourceAgentId },
|
|
947
1296
|
payload: {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1297
|
+
agent_id: agentId,
|
|
1298
|
+
session_id: sessionId,
|
|
1299
|
+
task: options?.name ?? `[Fork of ${sourceAgentId}]`,
|
|
1300
|
+
task_id: taskId,
|
|
1301
|
+
parent: sourceAgent.parent ?? null,
|
|
1302
|
+
role: sourceAgent.role ?? undefined,
|
|
1303
|
+
team_instance: sourceAgent.team_instance ?? undefined,
|
|
1304
|
+
config: {},
|
|
1305
|
+
cwd,
|
|
1306
|
+
metadata: { fork_of: sourceAgentId },
|
|
951
1307
|
},
|
|
952
1308
|
});
|
|
953
1309
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
};
|
|
1310
|
+
// Generate a human-readable name
|
|
1311
|
+
const generatedName = uniqueNamesGenerator({
|
|
1312
|
+
dictionaries: [adjectives, animals],
|
|
1313
|
+
separator: "-",
|
|
1314
|
+
length: 2,
|
|
1315
|
+
});
|
|
1316
|
+
eventStore.updateAgentMetadata(agentId as AgentId, { name: generatedName });
|
|
1317
|
+
await eventStore.persist();
|
|
1318
|
+
|
|
1319
|
+
// Get the provider session ID to fork from
|
|
1320
|
+
let forkedProviderSessionId: string;
|
|
1321
|
+
if (activeSession) {
|
|
1322
|
+
// Active session: fork with flush to ensure data is persisted
|
|
1323
|
+
const forkedSession = await activeSession.session.forkWithFlush();
|
|
1324
|
+
forkedProviderSessionId = forkedSession.id;
|
|
1325
|
+
} else {
|
|
1326
|
+
// Stopped agent: use the persisted provider session ID directly
|
|
1327
|
+
forkedProviderSessionId = sourceAgent.provider_session_id!;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// Spawn a new process
|
|
1331
|
+
const handle = await AgentFactory.spawn(defaultAgentType, {
|
|
1332
|
+
permissionMode: defaultPermissionMode,
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
try {
|
|
1336
|
+
const macroAgentMcp = buildMacroAgentMcp({
|
|
1337
|
+
agentId,
|
|
1338
|
+
parentId: sourceAgent.parent ?? "",
|
|
1339
|
+
taskId,
|
|
1340
|
+
cwd,
|
|
1341
|
+
permissionMode: defaultPermissionMode,
|
|
1342
|
+
lineage: sourceAgent.lineage ?? [],
|
|
1343
|
+
sessionId,
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
// Load the forked session on the new process with correct MCP config.
|
|
1347
|
+
// Note: loadSession's TS type for mcpServers is { name, uri }[] but
|
|
1348
|
+
// the underlying ACP protocol accepts full McpServerStdio. The JS
|
|
1349
|
+
// implementation passes mcpServers through to the connection unchanged.
|
|
1350
|
+
const session = await handle.loadSession(forkedProviderSessionId, cwd, [
|
|
1351
|
+
macroAgentMcp,
|
|
1352
|
+
] as any);
|
|
1353
|
+
|
|
1354
|
+
// Emit started status with provider session ID
|
|
1355
|
+
eventStore.emit({
|
|
1356
|
+
type: "status",
|
|
1357
|
+
source: { agent_id: agentId },
|
|
1358
|
+
payload: {
|
|
1359
|
+
status_type: "started",
|
|
1360
|
+
summary: "Agent session started (forked)",
|
|
1361
|
+
provider_session_id: session.id,
|
|
1362
|
+
},
|
|
1363
|
+
});
|
|
1364
|
+
await eventStore.persist();
|
|
1365
|
+
|
|
1366
|
+
// Set up message router subscriptions
|
|
1367
|
+
messageRouter.setupDefaultSubscriptions({
|
|
1368
|
+
agent_id: agentId,
|
|
1369
|
+
parent_id: sourceAgent.parent ?? undefined,
|
|
1370
|
+
task_id: taskId,
|
|
1371
|
+
subscribe_parent: false,
|
|
1372
|
+
additional_topics: [],
|
|
1373
|
+
role: sourceAgent.role ?? undefined,
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
// Track active session
|
|
1377
|
+
const newActiveSession: ActiveSession = {
|
|
1378
|
+
agentId,
|
|
1379
|
+
handle,
|
|
1380
|
+
session,
|
|
1381
|
+
createdAt: Date.now(),
|
|
1382
|
+
isPrompting: false,
|
|
1383
|
+
};
|
|
1384
|
+
activeSessions.set(agentId, newActiveSession);
|
|
1385
|
+
|
|
1386
|
+
const agent = eventStore.getAgent(agentId)!;
|
|
1387
|
+
notifyLifecycle({ type: "spawned", agent });
|
|
1388
|
+
notifyLifecycle({ type: "started", agent });
|
|
1389
|
+
|
|
1390
|
+
return {
|
|
1391
|
+
id: agentId,
|
|
1392
|
+
session_id: sessionId,
|
|
1393
|
+
agent,
|
|
1394
|
+
session,
|
|
1395
|
+
};
|
|
1396
|
+
} catch (handleError) {
|
|
1397
|
+
try {
|
|
1398
|
+
await handle.close();
|
|
1399
|
+
} catch {
|
|
1400
|
+
// Ignore errors during cleanup
|
|
1401
|
+
}
|
|
1402
|
+
throw handleError;
|
|
1403
|
+
}
|
|
960
1404
|
}
|
|
961
1405
|
|
|
962
1406
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -994,7 +1438,7 @@ export function createAgentManager(
|
|
|
994
1438
|
|
|
995
1439
|
function getHierarchy(
|
|
996
1440
|
agentId: AgentId,
|
|
997
|
-
options?: HierarchyOptions
|
|
1441
|
+
options?: HierarchyOptions,
|
|
998
1442
|
): AgentHierarchy | null {
|
|
999
1443
|
const agent = eventStore.getAgent(agentId);
|
|
1000
1444
|
if (!agent) return null;
|
|
@@ -1035,7 +1479,7 @@ export function createAgentManager(
|
|
|
1035
1479
|
// ─────────────────────────────────────────────────────────────────
|
|
1036
1480
|
|
|
1037
1481
|
async function getOrCreateHeadManager(
|
|
1038
|
-
options: HeadManagerOptions
|
|
1482
|
+
options: HeadManagerOptions,
|
|
1039
1483
|
): Promise<SpawnedAgent> {
|
|
1040
1484
|
const {
|
|
1041
1485
|
cwd,
|
|
@@ -1107,14 +1551,14 @@ export function createAgentManager(
|
|
|
1107
1551
|
|
|
1108
1552
|
async function* prompt(
|
|
1109
1553
|
agentId: AgentId,
|
|
1110
|
-
message: string
|
|
1554
|
+
message: string,
|
|
1111
1555
|
): AsyncIterable<ExtendedSessionUpdate> {
|
|
1112
1556
|
const activeSession = activeSessions.get(agentId);
|
|
1113
1557
|
if (!activeSession) {
|
|
1114
1558
|
throw new AgentManagerError(
|
|
1115
1559
|
`No active session for agent: ${agentId}`,
|
|
1116
1560
|
"SESSION_NOT_FOUND",
|
|
1117
|
-
agentId
|
|
1561
|
+
agentId,
|
|
1118
1562
|
);
|
|
1119
1563
|
}
|
|
1120
1564
|
|
|
@@ -1139,7 +1583,7 @@ export function createAgentManager(
|
|
|
1139
1583
|
maxFollowUps?: number;
|
|
1140
1584
|
throwOnMaxExceeded?: boolean;
|
|
1141
1585
|
onUpdate?: (update: ExtendedSessionUpdate) => void;
|
|
1142
|
-
}
|
|
1586
|
+
},
|
|
1143
1587
|
): Promise<{
|
|
1144
1588
|
doneCalled: boolean;
|
|
1145
1589
|
doneStatus?: string;
|
|
@@ -1156,7 +1600,10 @@ export function createAgentManager(
|
|
|
1156
1600
|
// Helper to check if done() was called by looking for status events
|
|
1157
1601
|
// The done() MCP tool emits status events with status_type completed/failed
|
|
1158
1602
|
// and includes signal: "WORKER_DONE" in the details
|
|
1159
|
-
const checkDoneCalled = async (): Promise<{
|
|
1603
|
+
const checkDoneCalled = async (): Promise<{
|
|
1604
|
+
called: boolean;
|
|
1605
|
+
status?: string;
|
|
1606
|
+
}> => {
|
|
1160
1607
|
// Reload from disk to see events from MCP subprocess
|
|
1161
1608
|
await eventStore.reload();
|
|
1162
1609
|
const statusEvents = eventStore.query({ type: "status" });
|
|
@@ -1166,14 +1613,15 @@ export function createAgentManager(
|
|
|
1166
1613
|
(e) =>
|
|
1167
1614
|
e.source?.agent_id === agentId &&
|
|
1168
1615
|
(e.payload?.status_type === "completed" ||
|
|
1169
|
-
|
|
1170
|
-
|
|
1616
|
+
e.payload?.status_type === "failed" ||
|
|
1617
|
+
(e.payload?.details as Record<string, unknown>)?.signal ===
|
|
1618
|
+
"WORKER_DONE"),
|
|
1171
1619
|
);
|
|
1172
1620
|
|
|
1173
1621
|
if (agentCompletedStatus) {
|
|
1174
1622
|
return {
|
|
1175
1623
|
called: true,
|
|
1176
|
-
status: agentCompletedStatus.payload?.status_type as string
|
|
1624
|
+
status: agentCompletedStatus.payload?.status_type as string,
|
|
1177
1625
|
};
|
|
1178
1626
|
}
|
|
1179
1627
|
|
|
@@ -1213,7 +1661,8 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1213
1661
|
|
|
1214
1662
|
for (let i = 0; i < maxFollowUps; i++) {
|
|
1215
1663
|
followUpCount++;
|
|
1216
|
-
const followUpMessage =
|
|
1664
|
+
const followUpMessage =
|
|
1665
|
+
followUpMessages[Math.min(i, followUpMessages.length - 1)];
|
|
1217
1666
|
|
|
1218
1667
|
// Send follow-up prompt
|
|
1219
1668
|
for await (const update of prompt(agentId, followUpMessage)) {
|
|
@@ -1238,7 +1687,7 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1238
1687
|
if (throwOnMaxExceeded) {
|
|
1239
1688
|
throw new Error(
|
|
1240
1689
|
`Agent ${agentId} did not call done() after ${maxFollowUps} follow-up attempts. ` +
|
|
1241
|
-
|
|
1690
|
+
`Total prompts sent: ${1 + followUpCount}. Consider increasing maxFollowUps or investigating agent behavior.`,
|
|
1242
1691
|
);
|
|
1243
1692
|
}
|
|
1244
1693
|
|
|
@@ -1293,12 +1742,12 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1293
1742
|
function respondToPermission(
|
|
1294
1743
|
agentId: AgentId,
|
|
1295
1744
|
requestId: string,
|
|
1296
|
-
optionId: string
|
|
1745
|
+
optionId: string,
|
|
1297
1746
|
): boolean {
|
|
1298
1747
|
const activeSession = activeSessions.get(agentId);
|
|
1299
1748
|
if (!activeSession) {
|
|
1300
1749
|
console.warn(
|
|
1301
|
-
`[AgentManager] Cannot respond to permission: no active session for agent ${agentId}
|
|
1750
|
+
`[AgentManager] Cannot respond to permission: no active session for agent ${agentId}`,
|
|
1302
1751
|
);
|
|
1303
1752
|
return false;
|
|
1304
1753
|
}
|
|
@@ -1306,13 +1755,13 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1306
1755
|
try {
|
|
1307
1756
|
activeSession.session.respondToPermission(requestId, optionId);
|
|
1308
1757
|
console.log(
|
|
1309
|
-
`[AgentManager] Responded to permission ${requestId} for agent ${agentId} with ${optionId}
|
|
1758
|
+
`[AgentManager] Responded to permission ${requestId} for agent ${agentId} with ${optionId}`,
|
|
1310
1759
|
);
|
|
1311
1760
|
return true;
|
|
1312
1761
|
} catch (err) {
|
|
1313
1762
|
console.error(
|
|
1314
1763
|
`[AgentManager] Error responding to permission ${requestId}:`,
|
|
1315
|
-
err
|
|
1764
|
+
err,
|
|
1316
1765
|
);
|
|
1317
1766
|
return false;
|
|
1318
1767
|
}
|
|
@@ -1322,7 +1771,7 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1322
1771
|
const activeSession = activeSessions.get(agentId);
|
|
1323
1772
|
if (!activeSession) {
|
|
1324
1773
|
console.warn(
|
|
1325
|
-
`[AgentManager] Cannot cancel permission: no active session for agent ${agentId}
|
|
1774
|
+
`[AgentManager] Cannot cancel permission: no active session for agent ${agentId}`,
|
|
1326
1775
|
);
|
|
1327
1776
|
return false;
|
|
1328
1777
|
}
|
|
@@ -1330,18 +1779,50 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1330
1779
|
try {
|
|
1331
1780
|
activeSession.session.cancelPermission(requestId);
|
|
1332
1781
|
console.log(
|
|
1333
|
-
`[AgentManager] Cancelled permission ${requestId} for agent ${agentId}
|
|
1782
|
+
`[AgentManager] Cancelled permission ${requestId} for agent ${agentId}`,
|
|
1334
1783
|
);
|
|
1335
1784
|
return true;
|
|
1336
1785
|
} catch (err) {
|
|
1337
1786
|
console.error(
|
|
1338
1787
|
`[AgentManager] Error cancelling permission ${requestId}:`,
|
|
1339
|
-
err
|
|
1788
|
+
err,
|
|
1340
1789
|
);
|
|
1341
1790
|
return false;
|
|
1342
1791
|
}
|
|
1343
1792
|
}
|
|
1344
1793
|
|
|
1794
|
+
function setPermissionMode(agentId: AgentId, mode: PermissionMode): boolean {
|
|
1795
|
+
const activeSession = activeSessions.get(agentId);
|
|
1796
|
+
if (!activeSession) {
|
|
1797
|
+
console.warn(
|
|
1798
|
+
`[AgentManager] Cannot set permission mode: no active session for agent ${agentId}`,
|
|
1799
|
+
);
|
|
1800
|
+
return false;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
try {
|
|
1804
|
+
activeSession.handle.setPermissionMode(mode);
|
|
1805
|
+
console.log(
|
|
1806
|
+
`[AgentManager] Set permission mode for agent ${agentId} to ${mode}`,
|
|
1807
|
+
);
|
|
1808
|
+
return true;
|
|
1809
|
+
} catch (err) {
|
|
1810
|
+
console.error(
|
|
1811
|
+
`[AgentManager] Error setting permission mode for agent ${agentId}:`,
|
|
1812
|
+
err,
|
|
1813
|
+
);
|
|
1814
|
+
return false;
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
function getPermissionMode(agentId: AgentId): PermissionMode | null {
|
|
1819
|
+
const activeSession = activeSessions.get(agentId);
|
|
1820
|
+
if (!activeSession) {
|
|
1821
|
+
return null;
|
|
1822
|
+
}
|
|
1823
|
+
return activeSession.handle.getPermissionMode();
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1345
1826
|
// ─────────────────────────────────────────────────────────────────
|
|
1346
1827
|
// Lifecycle Callbacks
|
|
1347
1828
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -1361,13 +1842,21 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1361
1842
|
}
|
|
1362
1843
|
}
|
|
1363
1844
|
|
|
1845
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1846
|
+
// OpenTasks Socket Path (Late Binding)
|
|
1847
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1848
|
+
|
|
1849
|
+
function setOpenTasksSocketPath(socketPath: string): void {
|
|
1850
|
+
configOpenTasksSocketPath = socketPath;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1364
1853
|
// ─────────────────────────────────────────────────────────────────
|
|
1365
1854
|
// Mail Services (Late Binding)
|
|
1366
1855
|
// ─────────────────────────────────────────────────────────────────
|
|
1367
1856
|
|
|
1368
1857
|
function setMailServices(
|
|
1369
1858
|
ms: import("../mail/mail-service.js").MailService,
|
|
1370
|
-
cm: import("../mail/conversation-map.js").ConversationMap
|
|
1859
|
+
cm: import("../mail/conversation-map.js").ConversationMap,
|
|
1371
1860
|
): void {
|
|
1372
1861
|
mailService = ms;
|
|
1373
1862
|
conversationMap = cm;
|
|
@@ -1378,6 +1867,9 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1378
1867
|
// ─────────────────────────────────────────────────────────────────
|
|
1379
1868
|
|
|
1380
1869
|
async function close(): Promise<void> {
|
|
1870
|
+
// Prevent new spawns/resumes from racing with cleanup
|
|
1871
|
+
isShuttingDown = true;
|
|
1872
|
+
|
|
1381
1873
|
// Stop all health checks
|
|
1382
1874
|
if (healthCheckService) {
|
|
1383
1875
|
healthCheckService.stopAll();
|
|
@@ -1393,7 +1885,7 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1393
1885
|
} catch {
|
|
1394
1886
|
// Ignore errors during cleanup
|
|
1395
1887
|
}
|
|
1396
|
-
})()
|
|
1888
|
+
})(),
|
|
1397
1889
|
);
|
|
1398
1890
|
}
|
|
1399
1891
|
|
|
@@ -1416,14 +1908,14 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1416
1908
|
*/
|
|
1417
1909
|
async function continueAgent(
|
|
1418
1910
|
agentId: AgentId,
|
|
1419
|
-
options?: ContinueAgentOptions
|
|
1911
|
+
options?: ContinueAgentOptions,
|
|
1420
1912
|
): Promise<SpawnedAgent> {
|
|
1421
1913
|
const agent = eventStore.getAgent(agentId);
|
|
1422
1914
|
if (!agent) {
|
|
1423
1915
|
throw new AgentManagerError(
|
|
1424
1916
|
`Agent not found: ${agentId}`,
|
|
1425
1917
|
"AGENT_NOT_FOUND",
|
|
1426
|
-
agentId
|
|
1918
|
+
agentId,
|
|
1427
1919
|
);
|
|
1428
1920
|
}
|
|
1429
1921
|
|
|
@@ -1443,7 +1935,9 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1443
1935
|
|
|
1444
1936
|
if (events.length > 0) {
|
|
1445
1937
|
contextLines.push("## Prior Session Context");
|
|
1446
|
-
contextLines.push(
|
|
1938
|
+
contextLines.push(
|
|
1939
|
+
`Continuing from agent ${agentId} (${events.length} events).`,
|
|
1940
|
+
);
|
|
1447
1941
|
for (const event of events.slice(-20)) {
|
|
1448
1942
|
const summary = event.payload?.summary;
|
|
1449
1943
|
if (summary && typeof summary === "string") {
|
|
@@ -1456,9 +1950,7 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1456
1950
|
|
|
1457
1951
|
// Spawn a continuation agent with same role, task, and context
|
|
1458
1952
|
const taskDescription =
|
|
1459
|
-
options?.task ??
|
|
1460
|
-
agent.task ??
|
|
1461
|
-
`Continue work from ${agentId}`;
|
|
1953
|
+
options?.task ?? agent.task ?? `Continue work from ${agentId}`;
|
|
1462
1954
|
|
|
1463
1955
|
const newAgent = await spawn({
|
|
1464
1956
|
task: taskDescription,
|
|
@@ -1487,6 +1979,7 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1487
1979
|
terminate,
|
|
1488
1980
|
resume,
|
|
1489
1981
|
continueAgent,
|
|
1982
|
+
forkAgent,
|
|
1490
1983
|
get,
|
|
1491
1984
|
list,
|
|
1492
1985
|
getChildren,
|
|
@@ -1502,9 +1995,12 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
|
|
|
1502
1995
|
isProcessRunning,
|
|
1503
1996
|
respondToPermission,
|
|
1504
1997
|
cancelPermission,
|
|
1998
|
+
setPermissionMode,
|
|
1999
|
+
getPermissionMode,
|
|
1505
2000
|
onLifecycleEvent,
|
|
1506
2001
|
setSpawnInterceptor,
|
|
1507
2002
|
getRoleRegistry,
|
|
2003
|
+
setOpenTasksSocketPath,
|
|
1508
2004
|
setMailServices,
|
|
1509
2005
|
close,
|
|
1510
2006
|
};
|
|
@@ -1518,84 +2014,112 @@ interface CreateWorkspaceOptions {
|
|
|
1518
2014
|
streamId?: string;
|
|
1519
2015
|
streamConfig?: import("../workspace/types.js").StreamConfig;
|
|
1520
2016
|
dataplaneTaskId?: string;
|
|
2017
|
+
capabilities?: string[];
|
|
1521
2018
|
cwd: string;
|
|
1522
2019
|
}
|
|
1523
2020
|
|
|
1524
2021
|
/**
|
|
1525
|
-
* 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.
|
|
1526
2031
|
*
|
|
1527
2032
|
* @param workspaceManager - WorkspaceManager instance
|
|
1528
2033
|
* @param agentId - Agent ID
|
|
1529
|
-
* @param role - Agent role (
|
|
1530
|
-
* @param options -
|
|
2034
|
+
* @param role - Agent role name (used for logging and fallback)
|
|
2035
|
+
* @param options - Workspace options including capabilities
|
|
1531
2036
|
* @returns Created workspace or undefined
|
|
1532
2037
|
*/
|
|
1533
2038
|
async function createWorkspaceForRole(
|
|
1534
2039
|
workspaceManager: WorkspaceManager,
|
|
1535
2040
|
agentId: AgentId,
|
|
1536
2041
|
role: string,
|
|
1537
|
-
options: CreateWorkspaceOptions
|
|
2042
|
+
options: CreateWorkspaceOptions,
|
|
1538
2043
|
): Promise<Workspace | undefined> {
|
|
1539
|
-
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);
|
|
1540
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)
|
|
1541
2085
|
switch (role) {
|
|
1542
2086
|
case "coordinator": {
|
|
1543
|
-
// Coordinators create a new integration stream
|
|
1544
2087
|
if (!streamConfig) {
|
|
1545
2088
|
console.warn(
|
|
1546
|
-
`[AgentManager] Coordinator ${agentId} spawn missing streamConfig, skipping workspace
|
|
2089
|
+
`[AgentManager] Coordinator ${agentId} spawn missing streamConfig, skipping workspace`,
|
|
1547
2090
|
);
|
|
1548
2091
|
return undefined;
|
|
1549
2092
|
}
|
|
1550
|
-
|
|
1551
|
-
const newStreamId = workspaceManager.createIntegrationStream(
|
|
1552
|
-
agentId,
|
|
1553
|
-
streamConfig
|
|
1554
|
-
);
|
|
1555
|
-
|
|
2093
|
+
const newStreamId = workspaceManager.createIntegrationStream(agentId, streamConfig);
|
|
1556
2094
|
return workspaceManager.createCoordinatorWorkspace(agentId, newStreamId);
|
|
1557
2095
|
}
|
|
1558
2096
|
|
|
1559
2097
|
case "integrator": {
|
|
1560
|
-
// Integrators join an existing stream
|
|
1561
2098
|
if (!streamId) {
|
|
1562
2099
|
console.warn(
|
|
1563
|
-
`[AgentManager] Integrator ${agentId} spawn missing streamId, skipping workspace
|
|
2100
|
+
`[AgentManager] Integrator ${agentId} spawn missing streamId, skipping workspace`,
|
|
1564
2101
|
);
|
|
1565
2102
|
return undefined;
|
|
1566
2103
|
}
|
|
1567
|
-
|
|
1568
2104
|
return workspaceManager.createIntegratorWorkspace(agentId, streamId);
|
|
1569
2105
|
}
|
|
1570
2106
|
|
|
1571
2107
|
case "worker":
|
|
1572
2108
|
case "worker.resolver": {
|
|
1573
|
-
// Workers need streamId and either dataplaneTaskId or create a new task
|
|
1574
2109
|
if (!streamId) {
|
|
1575
2110
|
console.warn(
|
|
1576
|
-
`[AgentManager] Worker ${agentId} spawn missing streamId, skipping workspace
|
|
1577
|
-
);
|
|
1578
|
-
return undefined;
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
// Use provided task ID or skip (task should be created separately)
|
|
1582
|
-
const taskId = dataplaneTaskId;
|
|
1583
|
-
if (!taskId) {
|
|
1584
|
-
console.warn(
|
|
1585
|
-
`[AgentManager] Worker ${agentId} spawn missing dataplaneTaskId, skipping workspace`
|
|
2111
|
+
`[AgentManager] Worker ${agentId} spawn missing streamId, skipping workspace`,
|
|
1586
2112
|
);
|
|
1587
2113
|
return undefined;
|
|
1588
2114
|
}
|
|
1589
|
-
|
|
2115
|
+
const taskId = dataplaneTaskId ?? agentId;
|
|
1590
2116
|
return workspaceManager.createWorkerWorkspace(agentId, taskId, streamId);
|
|
1591
2117
|
}
|
|
1592
2118
|
|
|
1593
2119
|
case "monitor":
|
|
1594
|
-
// Monitors don't need workspaces
|
|
1595
2120
|
return undefined;
|
|
1596
2121
|
|
|
1597
2122
|
default:
|
|
1598
|
-
// Unknown role - no workspace
|
|
1599
2123
|
return undefined;
|
|
1600
2124
|
}
|
|
1601
2125
|
}
|