macro-agent 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.macro-agent/teams/self-driving/prompts/grinder.md +27 -0
- package/.macro-agent/teams/self-driving/prompts/judge.md +27 -0
- package/.macro-agent/teams/self-driving/prompts/planner.md +33 -0
- package/.macro-agent/teams/self-driving/roles/grinder.yaml +17 -0
- package/.macro-agent/teams/self-driving/roles/judge.yaml +24 -0
- package/.macro-agent/teams/self-driving/roles/planner.yaml +18 -0
- package/.macro-agent/teams/self-driving/team.yaml +103 -0
- package/.macro-agent/teams/structured/prompts/developer.md +26 -0
- package/.macro-agent/teams/structured/prompts/lead.md +25 -0
- package/.macro-agent/teams/structured/prompts/reviewer.md +24 -0
- package/.macro-agent/teams/structured/roles/developer.yaml +12 -0
- package/.macro-agent/teams/structured/roles/lead.yaml +11 -0
- package/.macro-agent/teams/structured/roles/reviewer.yaml +19 -0
- package/.macro-agent/teams/structured/team.yaml +89 -0
- package/.sudocode/issues.jsonl +6 -0
- package/.sudocode/specs.jsonl +7 -0
- package/CLAUDE.md +110 -30
- package/README.md +60 -3
- package/dist/acp/macro-agent.d.ts +4 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +50 -4
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/session-mapper.d.ts +20 -1
- package/dist/acp/session-mapper.d.ts.map +1 -1
- package/dist/acp/session-mapper.js +90 -1
- package/dist/acp/session-mapper.js.map +1 -1
- package/dist/acp/types.d.ts +24 -1
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js.map +1 -1
- package/dist/agent/agent-manager.d.ts +25 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +93 -7
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +22 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/agent-detection/command-builder.d.ts +30 -0
- package/dist/agent-detection/command-builder.d.ts.map +1 -0
- package/dist/agent-detection/command-builder.js +71 -0
- package/dist/agent-detection/command-builder.js.map +1 -0
- package/dist/agent-detection/detector.d.ts +84 -0
- package/dist/agent-detection/detector.d.ts.map +1 -0
- package/dist/agent-detection/detector.js +240 -0
- package/dist/agent-detection/detector.js.map +1 -0
- package/dist/agent-detection/index.d.ts +12 -0
- package/dist/agent-detection/index.d.ts.map +1 -0
- package/dist/agent-detection/index.js +14 -0
- package/dist/agent-detection/index.js.map +1 -0
- package/dist/agent-detection/registry.d.ts +53 -0
- package/dist/agent-detection/registry.d.ts.map +1 -0
- package/dist/agent-detection/registry.js +177 -0
- package/dist/agent-detection/registry.js.map +1 -0
- package/dist/agent-detection/types.d.ts +121 -0
- package/dist/agent-detection/types.d.ts.map +1 -0
- package/dist/agent-detection/types.js +20 -0
- package/dist/agent-detection/types.js.map +1 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +95 -0
- package/dist/api/server.js.map +1 -1
- package/dist/cli/index.js +29 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.js +38 -0
- package/dist/cli/mcp.js.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/project-config.d.ts +46 -0
- package/dist/config/project-config.d.ts.map +1 -0
- package/dist/config/project-config.js +68 -0
- package/dist/config/project-config.js.map +1 -0
- package/dist/lifecycle/cascade.d.ts +1 -1
- package/dist/lifecycle/cascade.d.ts.map +1 -1
- package/dist/lifecycle/handlers/index.d.ts +4 -0
- package/dist/lifecycle/handlers/index.d.ts.map +1 -1
- package/dist/lifecycle/handlers/index.js +2 -0
- package/dist/lifecycle/handlers/index.js.map +1 -1
- package/dist/lifecycle/handlers/worker.d.ts +4 -0
- package/dist/lifecycle/handlers/worker.d.ts.map +1 -1
- package/dist/lifecycle/handlers/worker.js +35 -3
- package/dist/lifecycle/handlers/worker.js.map +1 -1
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +32 -2
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/adapter/event-translator.d.ts.map +1 -1
- package/dist/map/adapter/event-translator.js +1 -0
- package/dist/map/adapter/event-translator.js.map +1 -1
- package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
- package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-detection.js +91 -0
- package/dist/map/adapter/extensions/agent-detection.js.map +1 -0
- package/dist/map/adapter/extensions/index.d.ts +10 -1
- package/dist/map/adapter/extensions/index.d.ts.map +1 -1
- package/dist/map/adapter/extensions/index.js +39 -0
- package/dist/map/adapter/extensions/index.js.map +1 -1
- package/dist/map/adapter/extensions/resume.d.ts +47 -0
- package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
- package/dist/map/adapter/extensions/resume.js +59 -0
- package/dist/map/adapter/extensions/resume.js.map +1 -0
- package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
- package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
- package/dist/map/adapter/extensions/workspace-files.js +338 -0
- package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +6 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +45 -0
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/tools/claim_task.d.ts +35 -0
- package/dist/mcp/tools/claim_task.d.ts.map +1 -0
- package/dist/mcp/tools/claim_task.js +58 -0
- package/dist/mcp/tools/claim_task.js.map +1 -0
- package/dist/mcp/tools/done.d.ts +11 -2
- package/dist/mcp/tools/done.d.ts.map +1 -1
- package/dist/mcp/tools/done.js +15 -10
- package/dist/mcp/tools/done.js.map +1 -1
- package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
- package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
- package/dist/mcp/tools/list_claimable_tasks.js +63 -0
- package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
- package/dist/mcp/tools/unclaim_task.d.ts +31 -0
- package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
- package/dist/mcp/tools/unclaim_task.js +47 -0
- package/dist/mcp/tools/unclaim_task.js.map +1 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +2 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/metrics.d.ts +79 -0
- package/dist/metrics/metrics.d.ts.map +1 -0
- package/dist/metrics/metrics.js +166 -0
- package/dist/metrics/metrics.js.map +1 -0
- package/dist/roles/capabilities.d.ts +1 -0
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +3 -0
- package/dist/roles/capabilities.js.map +1 -1
- package/dist/roles/types.d.ts +1 -1
- package/dist/roles/types.d.ts.map +1 -1
- package/dist/router/message-router.d.ts +41 -0
- package/dist/router/message-router.d.ts.map +1 -1
- package/dist/router/message-router.js +136 -5
- package/dist/router/message-router.js.map +1 -1
- package/dist/store/event-store.d.ts +8 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +120 -4
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +1 -1
- package/dist/store/types/agents.d.ts.map +1 -1
- package/dist/store/types/events.d.ts +1 -1
- package/dist/store/types/events.d.ts.map +1 -1
- package/dist/store/types/events.js.map +1 -1
- package/dist/store/types/index.d.ts +1 -0
- package/dist/store/types/index.d.ts.map +1 -1
- package/dist/store/types/index.js +1 -0
- package/dist/store/types/index.js.map +1 -1
- package/dist/store/types/sessions.d.ts +44 -0
- package/dist/store/types/sessions.d.ts.map +1 -0
- package/dist/store/types/sessions.js +9 -0
- package/dist/store/types/sessions.js.map +1 -0
- package/dist/store/types/tasks.d.ts +2 -0
- package/dist/store/types/tasks.d.ts.map +1 -1
- package/dist/task/backend/memory.d.ts +4 -1
- package/dist/task/backend/memory.d.ts.map +1 -1
- package/dist/task/backend/memory.js +81 -0
- package/dist/task/backend/memory.js.map +1 -1
- package/dist/task/backend/types.d.ts +30 -0
- package/dist/task/backend/types.d.ts.map +1 -1
- package/dist/task/backend/types.js.map +1 -1
- package/dist/teams/index.d.ts +4 -0
- package/dist/teams/index.d.ts.map +1 -0
- package/dist/teams/index.js +4 -0
- package/dist/teams/index.js.map +1 -0
- package/dist/teams/team-loader.d.ts +20 -0
- package/dist/teams/team-loader.d.ts.map +1 -0
- package/dist/teams/team-loader.js +293 -0
- package/dist/teams/team-loader.js.map +1 -0
- package/dist/teams/team-runtime.d.ts +139 -0
- package/dist/teams/team-runtime.d.ts.map +1 -0
- package/dist/teams/team-runtime.js +613 -0
- package/dist/teams/team-runtime.js.map +1 -0
- package/dist/teams/types.d.ts +266 -0
- package/dist/teams/types.d.ts.map +1 -0
- package/dist/teams/types.js +20 -0
- package/dist/teams/types.js.map +1 -0
- package/dist/workspace/dataplane-adapter.d.ts +1 -1
- package/dist/workspace/dataplane-adapter.d.ts.map +1 -1
- package/dist/workspace/dataplane-adapter.js +1 -1
- package/dist/workspace/dataplane-adapter.js.map +1 -1
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/strategies/index.d.ts +6 -0
- package/dist/workspace/strategies/index.d.ts.map +1 -0
- package/dist/workspace/strategies/index.js +5 -0
- package/dist/workspace/strategies/index.js.map +1 -0
- package/dist/workspace/strategies/optimistic.d.ts +26 -0
- package/dist/workspace/strategies/optimistic.d.ts.map +1 -0
- package/dist/workspace/strategies/optimistic.js +121 -0
- package/dist/workspace/strategies/optimistic.js.map +1 -0
- package/dist/workspace/strategies/queue.d.ts +26 -0
- package/dist/workspace/strategies/queue.d.ts.map +1 -0
- package/dist/workspace/strategies/queue.js +67 -0
- package/dist/workspace/strategies/queue.js.map +1 -0
- package/dist/workspace/strategies/registry.d.ts +37 -0
- package/dist/workspace/strategies/registry.d.ts.map +1 -0
- package/dist/workspace/strategies/registry.js +63 -0
- package/dist/workspace/strategies/registry.js.map +1 -0
- package/dist/workspace/strategies/trunk.d.ts +20 -0
- package/dist/workspace/strategies/trunk.d.ts.map +1 -0
- package/dist/workspace/strategies/trunk.js +108 -0
- package/dist/workspace/strategies/trunk.js.map +1 -0
- package/dist/workspace/strategies/types.d.ts +104 -0
- package/dist/workspace/strategies/types.d.ts.map +1 -0
- package/dist/workspace/strategies/types.js +11 -0
- package/dist/workspace/strategies/types.js.map +1 -0
- package/dist/workspace/types.d.ts +1 -1
- package/dist/workspace/types.d.ts.map +1 -1
- package/dist/workspace/workspace-manager.d.ts +1 -1
- package/dist/workspace/workspace-manager.d.ts.map +1 -1
- package/docs/implementation-details.md +1127 -0
- package/docs/implementation-summary.md +448 -0
- package/docs/plan-self-driving-support.md +433 -0
- package/docs/spec-self-driving-support.md +462 -0
- package/docs/team-templates.md +860 -0
- package/docs/teams.md +233 -0
- package/package.json +4 -2
- package/src/acp/__tests__/integration.test.ts +161 -1
- package/src/acp/__tests__/macro-agent.test.ts +95 -0
- package/src/acp/__tests__/session-persistence.test.ts +276 -0
- package/src/acp/macro-agent.ts +79 -7
- package/src/acp/session-mapper.ts +108 -1
- package/src/acp/types.ts +33 -1
- package/src/agent/agent-manager.ts +158 -6
- package/src/agent/types.ts +27 -0
- package/src/agent-detection/__tests__/command-builder.test.ts +336 -0
- package/src/agent-detection/__tests__/detector.test.ts +768 -0
- package/src/agent-detection/__tests__/registry.test.ts +254 -0
- package/src/agent-detection/command-builder.ts +90 -0
- package/src/agent-detection/detector.ts +307 -0
- package/src/agent-detection/index.ts +36 -0
- package/src/agent-detection/registry.ts +200 -0
- package/src/agent-detection/types.ts +184 -0
- package/src/api/server.ts +110 -0
- package/src/cli/index.ts +44 -0
- package/src/cli/mcp.ts +47 -0
- package/src/config/index.ts +9 -0
- package/src/config/project-config.ts +107 -0
- package/src/lifecycle/cascade.ts +1 -1
- package/src/lifecycle/handlers/index.ts +8 -0
- package/src/lifecycle/handlers/worker.ts +48 -3
- package/src/map/adapter/__tests__/extensions.test.ts +359 -0
- package/src/map/adapter/__tests__/workspace-files.test.ts +673 -0
- package/src/map/adapter/acp-over-map.ts +45 -2
- package/src/map/adapter/event-translator.ts +1 -0
- package/src/map/adapter/extensions/agent-detection.ts +201 -0
- package/src/map/adapter/extensions/index.ts +63 -0
- package/src/map/adapter/extensions/resume.ts +114 -0
- package/src/map/adapter/extensions/workspace-files.ts +449 -0
- package/src/mcp/mcp-server.ts +67 -0
- package/src/mcp/tools/claim_task.ts +86 -0
- package/src/mcp/tools/done.ts +24 -10
- package/src/mcp/tools/list_claimable_tasks.ts +93 -0
- package/src/mcp/tools/unclaim_task.ts +71 -0
- package/src/metrics/index.ts +9 -0
- package/src/metrics/metrics.ts +280 -0
- package/src/roles/capabilities.ts +3 -0
- package/src/roles/types.ts +2 -1
- package/src/router/__tests__/message-router.test.ts +561 -0
- package/src/router/message-router.ts +223 -6
- package/src/store/event-store.ts +151 -3
- package/src/store/types/agents.ts +1 -1
- package/src/store/types/events.ts +2 -1
- package/src/store/types/index.ts +1 -0
- package/src/store/types/sessions.ts +53 -0
- package/src/store/types/tasks.ts +3 -0
- package/src/task/backend/memory.ts +116 -0
- package/src/task/backend/types.ts +43 -0
- package/src/teams/__tests__/cross-subsystem.integration.test.ts +983 -0
- package/src/teams/__tests__/e2e/team-runtime.e2e.test.ts +553 -0
- package/src/teams/__tests__/team-system.test.ts +1280 -0
- package/src/teams/index.ts +13 -0
- package/src/teams/team-loader.ts +434 -0
- package/src/teams/team-runtime.ts +727 -0
- package/src/teams/types.ts +377 -0
- package/src/workspace/dataplane-adapter.ts +1 -1
- package/src/workspace/index.ts +1 -1
- package/src/workspace/strategies/index.ts +18 -0
- package/src/workspace/strategies/optimistic.ts +136 -0
- package/src/workspace/strategies/queue.ts +81 -0
- package/src/workspace/strategies/registry.ts +89 -0
- package/src/workspace/strategies/trunk.ts +123 -0
- package/src/workspace/strategies/types.ts +145 -0
- package/src/workspace/types.ts +1 -1
- package/src/workspace/workspace-manager.ts +1 -1
- package/.claude/settings.local.json +0 -59
- package/dist/map/utils/address-translation.d.ts +0 -99
- package/dist/map/utils/address-translation.d.ts.map +0 -1
- package/dist/map/utils/address-translation.js +0 -285
- package/dist/map/utils/address-translation.js.map +0 -1
- package/dist/map/utils/index.d.ts +0 -7
- package/dist/map/utils/index.d.ts.map +0 -1
- package/dist/map/utils/index.js +0 -7
- package/dist/map/utils/index.js.map +0 -1
- package/references/acp-factory-ref/CHANGELOG.md +0 -33
- package/references/acp-factory-ref/LICENSE +0 -21
- package/references/acp-factory-ref/README.md +0 -341
- package/references/acp-factory-ref/package-lock.json +0 -3102
- package/references/acp-factory-ref/package.json +0 -96
- package/references/acp-factory-ref/python/CHANGELOG.md +0 -33
- package/references/acp-factory-ref/python/LICENSE +0 -21
- package/references/acp-factory-ref/python/Makefile +0 -57
- package/references/acp-factory-ref/python/README.md +0 -253
- package/references/acp-factory-ref/python/pyproject.toml +0 -73
- package/references/acp-factory-ref/python/tests/__init__.py +0 -0
- package/references/acp-factory-ref/python/tests/e2e/__init__.py +0 -1
- package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +0 -349
- package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +0 -165
- package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +0 -296
- package/references/acp-factory-ref/python/tests/test_client_handler.py +0 -543
- package/references/acp-factory-ref/python/tests/test_pushable.py +0 -199
- package/references/claude-code-acp/.github/workflows/ci.yml +0 -45
- package/references/claude-code-acp/.github/workflows/publish.yml +0 -34
- package/references/claude-code-acp/.prettierrc.json +0 -4
- package/references/claude-code-acp/CHANGELOG.md +0 -249
- package/references/claude-code-acp/LICENSE +0 -222
- package/references/claude-code-acp/README.md +0 -53
- package/references/claude-code-acp/docs/RELEASES.md +0 -24
- package/references/claude-code-acp/eslint.config.js +0 -48
- package/references/claude-code-acp/package-lock.json +0 -4570
- package/references/claude-code-acp/package.json +0 -88
- package/references/claude-code-acp/scripts/release.sh +0 -119
- package/references/claude-code-acp/src/acp-agent.ts +0 -2065
- package/references/claude-code-acp/src/index.ts +0 -26
- package/references/claude-code-acp/src/lib.ts +0 -38
- package/references/claude-code-acp/src/mcp-server.ts +0 -911
- package/references/claude-code-acp/src/settings.ts +0 -522
- package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +0 -5
- package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +0 -6
- package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +0 -479
- package/references/claude-code-acp/src/tests/acp-agent.test.ts +0 -1502
- package/references/claude-code-acp/src/tests/extract-lines.test.ts +0 -103
- package/references/claude-code-acp/src/tests/fork-session.test.ts +0 -335
- package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +0 -334
- package/references/claude-code-acp/src/tests/settings.test.ts +0 -617
- package/references/claude-code-acp/src/tests/skills-options.test.ts +0 -187
- package/references/claude-code-acp/src/tests/tools.test.ts +0 -318
- package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +0 -558
- package/references/claude-code-acp/src/tools.ts +0 -819
- package/references/claude-code-acp/src/utils.ts +0 -171
- package/references/claude-code-acp/tsconfig.json +0 -18
- package/references/claude-code-acp/vitest.config.ts +0 -19
- package/references/multi-agent-protocol/.sudocode/issues.jsonl +0 -111
- package/references/multi-agent-protocol/.sudocode/specs.jsonl +0 -13
- package/references/multi-agent-protocol/LICENSE +0 -21
- package/references/multi-agent-protocol/README.md +0 -113
- package/references/multi-agent-protocol/docs/00-design-specification.md +0 -496
- package/references/multi-agent-protocol/docs/01-open-questions.md +0 -1050
- package/references/multi-agent-protocol/docs/02-wire-protocol.md +0 -296
- package/references/multi-agent-protocol/docs/03-streaming-semantics.md +0 -252
- package/references/multi-agent-protocol/docs/04-error-handling.md +0 -231
- package/references/multi-agent-protocol/docs/05-connection-model.md +0 -244
- package/references/multi-agent-protocol/docs/06-visibility-permissions.md +0 -243
- package/references/multi-agent-protocol/docs/07-federation.md +0 -259
- package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +0 -253
- package/references/multi-agent-protocol/docs/09-authentication.md +0 -680
- package/references/multi-agent-protocol/docs/10-mail-protocol.md +0 -553
- package/references/multi-agent-protocol/docs/agent-iam-integration.md +0 -877
- package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +0 -459
- package/references/multi-agent-protocol/docs/git-transport-draft.md +0 -251
- package/references/multi-agent-protocol/docs-site/Gemfile +0 -22
- package/references/multi-agent-protocol/docs-site/README.md +0 -82
- package/references/multi-agent-protocol/docs-site/_config.yml +0 -91
- package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +0 -20
- package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +0 -42
- package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +0 -34
- package/references/multi-agent-protocol/docs-site/examples/full-integration.md +0 -510
- package/references/multi-agent-protocol/docs-site/examples/index.md +0 -138
- package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +0 -282
- package/references/multi-agent-protocol/docs-site/examples/task-queue.md +0 -399
- package/references/multi-agent-protocol/docs-site/getting-started/index.md +0 -98
- package/references/multi-agent-protocol/docs-site/getting-started/installation.md +0 -219
- package/references/multi-agent-protocol/docs-site/getting-started/overview.md +0 -172
- package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +0 -237
- package/references/multi-agent-protocol/docs-site/index.md +0 -136
- package/references/multi-agent-protocol/docs-site/protocol/authentication.md +0 -391
- package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +0 -376
- package/references/multi-agent-protocol/docs-site/protocol/design.md +0 -284
- package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +0 -312
- package/references/multi-agent-protocol/docs-site/protocol/federation.md +0 -449
- package/references/multi-agent-protocol/docs-site/protocol/index.md +0 -129
- package/references/multi-agent-protocol/docs-site/protocol/permissions.md +0 -398
- package/references/multi-agent-protocol/docs-site/protocol/streaming.md +0 -353
- package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +0 -369
- package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +0 -357
- package/references/multi-agent-protocol/docs-site/sdk/api/client.md +0 -380
- package/references/multi-agent-protocol/docs-site/sdk/api/index.md +0 -62
- package/references/multi-agent-protocol/docs-site/sdk/api/server.md +0 -453
- package/references/multi-agent-protocol/docs-site/sdk/api/types.md +0 -468
- package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +0 -375
- package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +0 -405
- package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +0 -352
- package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +0 -89
- package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +0 -360
- package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +0 -446
- package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +0 -363
- package/references/multi-agent-protocol/docs-site/sdk/index.md +0 -206
- package/references/multi-agent-protocol/package-lock.json +0 -3886
- package/references/multi-agent-protocol/package.json +0 -56
- package/references/multi-agent-protocol/schema/meta.json +0 -467
- package/references/multi-agent-protocol/schema/schema.json +0 -2558
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Registry Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect } from "vitest";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
AgentRegistry,
|
|
9
|
+
createAgentRegistry,
|
|
10
|
+
BUILTIN_AGENTS,
|
|
11
|
+
} from "../registry.js";
|
|
12
|
+
import type { CLIAgentDefinition } from "../types.js";
|
|
13
|
+
|
|
14
|
+
describe("AgentRegistry", () => {
|
|
15
|
+
// ===========================================================================
|
|
16
|
+
// Built-in Agents
|
|
17
|
+
// ===========================================================================
|
|
18
|
+
|
|
19
|
+
describe("BUILTIN_AGENTS", () => {
|
|
20
|
+
it("contains all 6 known agents", () => {
|
|
21
|
+
expect(BUILTIN_AGENTS).toHaveLength(6);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("includes claude-code", () => {
|
|
25
|
+
const agent = BUILTIN_AGENTS.find((a) => a.id === "claude-code");
|
|
26
|
+
expect(agent).toBeDefined();
|
|
27
|
+
expect(agent!.binary).toBe("claude");
|
|
28
|
+
expect(agent!.vendor).toBe("Anthropic");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("includes codex", () => {
|
|
32
|
+
const agent = BUILTIN_AGENTS.find((a) => a.id === "codex");
|
|
33
|
+
expect(agent).toBeDefined();
|
|
34
|
+
expect(agent!.binary).toBe("codex");
|
|
35
|
+
expect(agent!.vendor).toBe("OpenAI");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("includes gemini-cli", () => {
|
|
39
|
+
const agent = BUILTIN_AGENTS.find((a) => a.id === "gemini-cli");
|
|
40
|
+
expect(agent).toBeDefined();
|
|
41
|
+
expect(agent!.binary).toBe("gemini");
|
|
42
|
+
expect(agent!.vendor).toBe("Google");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("includes opencode", () => {
|
|
46
|
+
const agent = BUILTIN_AGENTS.find((a) => a.id === "opencode");
|
|
47
|
+
expect(agent).toBeDefined();
|
|
48
|
+
expect(agent!.binary).toBe("opencode");
|
|
49
|
+
expect(agent!.vendor).toBe("Anomaly");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("includes aider", () => {
|
|
53
|
+
const agent = BUILTIN_AGENTS.find((a) => a.id === "aider");
|
|
54
|
+
expect(agent).toBeDefined();
|
|
55
|
+
expect(agent!.binary).toBe("aider");
|
|
56
|
+
expect(agent!.vendor).toBe("Aider");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("includes goose", () => {
|
|
60
|
+
const agent = BUILTIN_AGENTS.find((a) => a.id === "goose");
|
|
61
|
+
expect(agent).toBeDefined();
|
|
62
|
+
expect(agent!.binary).toBe("goose");
|
|
63
|
+
expect(agent!.vendor).toBe("Block");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("all agents have required fields", () => {
|
|
67
|
+
for (const agent of BUILTIN_AGENTS) {
|
|
68
|
+
expect(agent.id).toBeTruthy();
|
|
69
|
+
expect(agent.name).toBeTruthy();
|
|
70
|
+
expect(agent.description).toBeTruthy();
|
|
71
|
+
expect(agent.binary).toBeTruthy();
|
|
72
|
+
expect(agent.versionArgs).toBeDefined();
|
|
73
|
+
expect(agent.versionArgs.length).toBeGreaterThan(0);
|
|
74
|
+
expect(agent.headless).toBeDefined();
|
|
75
|
+
expect(agent.headless.promptFlag).toBeDefined();
|
|
76
|
+
expect(agent.vendor).toBeTruthy();
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// ===========================================================================
|
|
82
|
+
// Registry Operations
|
|
83
|
+
// ===========================================================================
|
|
84
|
+
|
|
85
|
+
describe("constructor", () => {
|
|
86
|
+
it("creates registry with built-in agents", () => {
|
|
87
|
+
const registry = new AgentRegistry();
|
|
88
|
+
expect(registry.size).toBe(6);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("creates registry with additional custom agents", () => {
|
|
92
|
+
const custom: CLIAgentDefinition = {
|
|
93
|
+
id: "custom-agent",
|
|
94
|
+
name: "Custom Agent",
|
|
95
|
+
description: "A custom agent",
|
|
96
|
+
binary: "custom",
|
|
97
|
+
versionArgs: ["--version"],
|
|
98
|
+
headless: { promptFlag: "--prompt" },
|
|
99
|
+
vendor: "Custom",
|
|
100
|
+
};
|
|
101
|
+
const registry = new AgentRegistry([custom]);
|
|
102
|
+
expect(registry.size).toBe(7);
|
|
103
|
+
expect(registry.get("custom-agent")).toEqual(custom);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("custom agents can override built-in agents", () => {
|
|
107
|
+
const override: CLIAgentDefinition = {
|
|
108
|
+
id: "claude-code",
|
|
109
|
+
name: "Custom Claude",
|
|
110
|
+
description: "Overridden",
|
|
111
|
+
binary: "custom-claude",
|
|
112
|
+
versionArgs: ["--version"],
|
|
113
|
+
headless: { promptFlag: "-p" },
|
|
114
|
+
vendor: "Custom",
|
|
115
|
+
};
|
|
116
|
+
const registry = new AgentRegistry([override]);
|
|
117
|
+
expect(registry.get("claude-code")!.binary).toBe("custom-claude");
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe("get()", () => {
|
|
122
|
+
it("returns agent definition by ID", () => {
|
|
123
|
+
const registry = new AgentRegistry();
|
|
124
|
+
const agent = registry.get("claude-code");
|
|
125
|
+
expect(agent).toBeDefined();
|
|
126
|
+
expect(agent!.id).toBe("claude-code");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("returns undefined for unknown ID", () => {
|
|
130
|
+
const registry = new AgentRegistry();
|
|
131
|
+
expect(registry.get("nonexistent")).toBeUndefined();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("has()", () => {
|
|
136
|
+
it("returns true for existing agent", () => {
|
|
137
|
+
const registry = new AgentRegistry();
|
|
138
|
+
expect(registry.has("claude-code")).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("returns false for unknown agent", () => {
|
|
142
|
+
const registry = new AgentRegistry();
|
|
143
|
+
expect(registry.has("nonexistent")).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe("register()", () => {
|
|
148
|
+
it("adds a new agent definition", () => {
|
|
149
|
+
const registry = new AgentRegistry();
|
|
150
|
+
const custom: CLIAgentDefinition = {
|
|
151
|
+
id: "new-agent",
|
|
152
|
+
name: "New Agent",
|
|
153
|
+
description: "Newly added",
|
|
154
|
+
binary: "new",
|
|
155
|
+
versionArgs: ["--version"],
|
|
156
|
+
headless: { promptFlag: "--prompt" },
|
|
157
|
+
vendor: "New",
|
|
158
|
+
};
|
|
159
|
+
registry.register(custom);
|
|
160
|
+
expect(registry.has("new-agent")).toBe(true);
|
|
161
|
+
expect(registry.get("new-agent")).toEqual(custom);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("overrides existing agent definition", () => {
|
|
165
|
+
const registry = new AgentRegistry();
|
|
166
|
+
const override: CLIAgentDefinition = {
|
|
167
|
+
id: "claude-code",
|
|
168
|
+
name: "Custom Claude",
|
|
169
|
+
description: "Overridden",
|
|
170
|
+
binary: "custom",
|
|
171
|
+
versionArgs: ["--version"],
|
|
172
|
+
headless: { promptFlag: "-p" },
|
|
173
|
+
vendor: "Custom",
|
|
174
|
+
};
|
|
175
|
+
registry.register(override);
|
|
176
|
+
expect(registry.get("claude-code")!.name).toBe("Custom Claude");
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe("remove()", () => {
|
|
181
|
+
it("removes an existing agent definition", () => {
|
|
182
|
+
const registry = new AgentRegistry();
|
|
183
|
+
expect(registry.remove("claude-code")).toBe(true);
|
|
184
|
+
expect(registry.has("claude-code")).toBe(false);
|
|
185
|
+
expect(registry.size).toBe(5);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("returns false for non-existent agent", () => {
|
|
189
|
+
const registry = new AgentRegistry();
|
|
190
|
+
expect(registry.remove("nonexistent")).toBe(false);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe("list()", () => {
|
|
195
|
+
it("returns all registered agents", () => {
|
|
196
|
+
const registry = new AgentRegistry();
|
|
197
|
+
const agents = registry.list();
|
|
198
|
+
expect(agents).toHaveLength(6);
|
|
199
|
+
const ids = agents.map((a) => a.id);
|
|
200
|
+
expect(ids).toContain("claude-code");
|
|
201
|
+
expect(ids).toContain("codex");
|
|
202
|
+
expect(ids).toContain("gemini-cli");
|
|
203
|
+
expect(ids).toContain("opencode");
|
|
204
|
+
expect(ids).toContain("aider");
|
|
205
|
+
expect(ids).toContain("goose");
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe("listEnabled()", () => {
|
|
210
|
+
it("returns all agents when no disabled list", () => {
|
|
211
|
+
const registry = new AgentRegistry();
|
|
212
|
+
expect(registry.listEnabled()).toHaveLength(6);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("returns all agents when disabled list is empty", () => {
|
|
216
|
+
const registry = new AgentRegistry();
|
|
217
|
+
expect(registry.listEnabled([])).toHaveLength(6);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("excludes disabled agents", () => {
|
|
221
|
+
const registry = new AgentRegistry();
|
|
222
|
+
const enabled = registry.listEnabled(["goose", "aider"]);
|
|
223
|
+
expect(enabled).toHaveLength(4);
|
|
224
|
+
const ids = enabled.map((a) => a.id);
|
|
225
|
+
expect(ids).not.toContain("goose");
|
|
226
|
+
expect(ids).not.toContain("aider");
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// ===========================================================================
|
|
231
|
+
// Factory
|
|
232
|
+
// ===========================================================================
|
|
233
|
+
|
|
234
|
+
describe("createAgentRegistry()", () => {
|
|
235
|
+
it("creates registry with defaults", () => {
|
|
236
|
+
const registry = createAgentRegistry();
|
|
237
|
+
expect(registry.size).toBe(6);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("creates registry with additional agents", () => {
|
|
241
|
+
const custom: CLIAgentDefinition = {
|
|
242
|
+
id: "extra",
|
|
243
|
+
name: "Extra",
|
|
244
|
+
description: "Extra agent",
|
|
245
|
+
binary: "extra",
|
|
246
|
+
versionArgs: ["--version"],
|
|
247
|
+
headless: { promptFlag: "--prompt" },
|
|
248
|
+
vendor: "Extra",
|
|
249
|
+
};
|
|
250
|
+
const registry = createAgentRegistry([custom]);
|
|
251
|
+
expect(registry.size).toBe(7);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Builder
|
|
3
|
+
*
|
|
4
|
+
* Constructs headless invocation commands for CLI coding agents
|
|
5
|
+
* based on their definitions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
CLIAgentDefinition,
|
|
10
|
+
SpawnCommand,
|
|
11
|
+
SpawnCommandOptions,
|
|
12
|
+
} from "./types.js";
|
|
13
|
+
import { AgentDetectionError } from "./types.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Build a headless spawn command for a CLI agent.
|
|
17
|
+
*
|
|
18
|
+
* Constructs the command and arguments array based on the agent definition's
|
|
19
|
+
* headless configuration, model flag, and working directory flag.
|
|
20
|
+
*
|
|
21
|
+
* @param definition - The CLI agent definition
|
|
22
|
+
* @param task - The prompt/task to pass to the agent
|
|
23
|
+
* @param options - Optional model and cwd overrides
|
|
24
|
+
* @returns The command and args array ready for child_process.spawn()
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const cmd = buildSpawnCommand(claudeCode, "Fix the auth bug", { model: "claude-sonnet-4-5" });
|
|
29
|
+
* // { command: "claude", args: ["-p", "Fix the auth bug", "--output-format", "stream-json", "--model", "claude-sonnet-4-5"] }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function buildSpawnCommand(
|
|
33
|
+
definition: CLIAgentDefinition,
|
|
34
|
+
task: string,
|
|
35
|
+
options?: SpawnCommandOptions
|
|
36
|
+
): SpawnCommand {
|
|
37
|
+
if (!task) {
|
|
38
|
+
throw new AgentDetectionError(
|
|
39
|
+
"Task prompt is required",
|
|
40
|
+
"DETECTION_FAILED"
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const args: string[] = [];
|
|
45
|
+
|
|
46
|
+
// 1. Subcommand (e.g., "exec", "run")
|
|
47
|
+
if (definition.headless.subcommand) {
|
|
48
|
+
args.push(definition.headless.subcommand);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 2. Default flags (e.g., "--full-auto", "--yes")
|
|
52
|
+
if (definition.headless.defaultFlags) {
|
|
53
|
+
args.push(...definition.headless.defaultFlags);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 3. Model flag
|
|
57
|
+
if (options?.model && definition.modelFlag) {
|
|
58
|
+
args.push(definition.modelFlag, options.model);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 4. Working directory flag
|
|
62
|
+
if (options?.cwd && definition.cwdFlag) {
|
|
63
|
+
args.push(definition.cwdFlag, options.cwd);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 5. Prompt (flag-based or positional)
|
|
67
|
+
if (definition.headless.promptFlag) {
|
|
68
|
+
args.push(definition.headless.promptFlag, task);
|
|
69
|
+
} else {
|
|
70
|
+
args.push(task);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { command: definition.binary, args };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Format a spawn command as a single shell string (for display/logging).
|
|
78
|
+
*/
|
|
79
|
+
export function formatSpawnCommand(spawnCommand: SpawnCommand): string {
|
|
80
|
+
const parts = [spawnCommand.command];
|
|
81
|
+
for (const arg of spawnCommand.args) {
|
|
82
|
+
// Quote arguments that contain spaces
|
|
83
|
+
if (arg.includes(" ")) {
|
|
84
|
+
parts.push(`"${arg}"`);
|
|
85
|
+
} else {
|
|
86
|
+
parts.push(arg);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return parts.join(" ");
|
|
90
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Agent Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects installed CLI coding agents by checking PATH availability
|
|
5
|
+
* and querying version information. Results are cached with configurable TTL.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execFile } from "node:child_process";
|
|
9
|
+
import { promisify } from "node:util";
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
CLIAgentDefinition,
|
|
13
|
+
DetectedAgent,
|
|
14
|
+
DetectionResult,
|
|
15
|
+
AgentDetectionConfig,
|
|
16
|
+
} from "./types.js";
|
|
17
|
+
import { AgentDetectionError } from "./types.js";
|
|
18
|
+
import { AgentRegistry, createAgentRegistry } from "./registry.js";
|
|
19
|
+
|
|
20
|
+
const execFileAsync = promisify(execFile);
|
|
21
|
+
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// Constants
|
|
24
|
+
// =============================================================================
|
|
25
|
+
|
|
26
|
+
const DEFAULT_CACHE_TTL_MS = 60_000;
|
|
27
|
+
const DEFAULT_WHICH_TIMEOUT_MS = 5_000;
|
|
28
|
+
const DEFAULT_VERSION_TIMEOUT_MS = 10_000;
|
|
29
|
+
|
|
30
|
+
/** Regex to parse version strings like "1.2.3", "0.82.1-beta", etc. */
|
|
31
|
+
const VERSION_REGEX = /\d+\.\d+[\.\d]*/;
|
|
32
|
+
|
|
33
|
+
// =============================================================================
|
|
34
|
+
// Agent Detector
|
|
35
|
+
// =============================================================================
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Detects installed CLI coding agents on the system.
|
|
39
|
+
*
|
|
40
|
+
* Runs binary lookups and version checks in parallel, caches results,
|
|
41
|
+
* and provides query methods for available agents.
|
|
42
|
+
*/
|
|
43
|
+
export class AgentDetector {
|
|
44
|
+
private readonly registry: AgentRegistry;
|
|
45
|
+
private readonly cacheTtlMs: number;
|
|
46
|
+
private readonly whichTimeoutMs: number;
|
|
47
|
+
private readonly versionTimeoutMs: number;
|
|
48
|
+
private readonly disabledAgents: Set<string>;
|
|
49
|
+
|
|
50
|
+
private cachedResult: DetectionResult | null = null;
|
|
51
|
+
private detectionInProgress: Promise<DetectionResult> | null = null;
|
|
52
|
+
|
|
53
|
+
constructor(config?: AgentDetectionConfig) {
|
|
54
|
+
this.cacheTtlMs = config?.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
55
|
+
this.whichTimeoutMs = config?.whichTimeoutMs ?? DEFAULT_WHICH_TIMEOUT_MS;
|
|
56
|
+
this.versionTimeoutMs =
|
|
57
|
+
config?.versionTimeoutMs ?? DEFAULT_VERSION_TIMEOUT_MS;
|
|
58
|
+
this.disabledAgents = new Set(config?.disabledAgents ?? []);
|
|
59
|
+
|
|
60
|
+
this.registry = createAgentRegistry(config?.additionalAgents);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get the underlying agent registry.
|
|
65
|
+
*/
|
|
66
|
+
getRegistry(): AgentRegistry {
|
|
67
|
+
return this.registry;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Detect all installed agents.
|
|
72
|
+
*
|
|
73
|
+
* Returns cached results if available and not expired.
|
|
74
|
+
* If a detection is already in progress, returns its promise.
|
|
75
|
+
*/
|
|
76
|
+
async detect(options?: { refresh?: boolean }): Promise<DetectionResult> {
|
|
77
|
+
// Return cached result if valid
|
|
78
|
+
if (!options?.refresh && this.cachedResult && !this.isCacheExpired()) {
|
|
79
|
+
return this.cachedResult;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// If detection is already running, return the in-progress promise
|
|
83
|
+
if (this.detectionInProgress) {
|
|
84
|
+
return this.detectionInProgress;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Start a new detection scan
|
|
88
|
+
this.detectionInProgress = this.runDetection();
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const result = await this.detectionInProgress;
|
|
92
|
+
this.cachedResult = result;
|
|
93
|
+
return result;
|
|
94
|
+
} finally {
|
|
95
|
+
this.detectionInProgress = null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get available agents (installed only by default).
|
|
101
|
+
*/
|
|
102
|
+
async getAvailableAgents(options?: {
|
|
103
|
+
refresh?: boolean;
|
|
104
|
+
includeNotInstalled?: boolean;
|
|
105
|
+
}): Promise<DetectionResult> {
|
|
106
|
+
const result = await this.detect({ refresh: options?.refresh });
|
|
107
|
+
|
|
108
|
+
if (options?.includeNotInstalled) {
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
...result,
|
|
114
|
+
agents: result.agents.filter((a) => a.installed),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get a specific detected agent by ID.
|
|
120
|
+
*/
|
|
121
|
+
async getAgent(id: string): Promise<DetectedAgent | undefined> {
|
|
122
|
+
const result = await this.detect();
|
|
123
|
+
return result.agents.find((a) => a.id === id);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if a specific agent is installed.
|
|
128
|
+
*/
|
|
129
|
+
async isInstalled(id: string): Promise<boolean> {
|
|
130
|
+
const agent = await this.getAgent(id);
|
|
131
|
+
return agent?.installed ?? false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get the definition for an agent, throwing if not found.
|
|
136
|
+
*/
|
|
137
|
+
getDefinition(id: string): CLIAgentDefinition {
|
|
138
|
+
const def = this.registry.get(id);
|
|
139
|
+
if (!def) {
|
|
140
|
+
throw new AgentDetectionError(
|
|
141
|
+
`Unknown agent backend: ${id}`,
|
|
142
|
+
"UNKNOWN_AGENT",
|
|
143
|
+
id
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
return def;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Invalidate the detection cache.
|
|
151
|
+
*/
|
|
152
|
+
invalidateCache(): void {
|
|
153
|
+
this.cachedResult = null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get partial results if detection is in progress, or cached results.
|
|
158
|
+
* Returns null if no results are available yet.
|
|
159
|
+
*/
|
|
160
|
+
getCachedResult(): DetectionResult | null {
|
|
161
|
+
return this.cachedResult;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Whether a detection scan is currently running.
|
|
166
|
+
*/
|
|
167
|
+
isDetecting(): boolean {
|
|
168
|
+
return this.detectionInProgress !== null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ===========================================================================
|
|
172
|
+
// Private
|
|
173
|
+
// ===========================================================================
|
|
174
|
+
|
|
175
|
+
private isCacheExpired(): boolean {
|
|
176
|
+
if (!this.cachedResult) return true;
|
|
177
|
+
const maxAge = Math.max(...this.cachedResult.agents.map((a) => a.detectedAt));
|
|
178
|
+
return Date.now() - maxAge > this.cacheTtlMs;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private async runDetection(): Promise<DetectionResult> {
|
|
182
|
+
const definitions = this.registry.listEnabled(
|
|
183
|
+
Array.from(this.disabledAgents)
|
|
184
|
+
);
|
|
185
|
+
const startTime = Date.now();
|
|
186
|
+
|
|
187
|
+
const results = await Promise.allSettled(
|
|
188
|
+
definitions.map((def) => this.detectAgent(def))
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const agents: DetectedAgent[] = results.map((result, i) => {
|
|
192
|
+
if (result.status === "fulfilled") {
|
|
193
|
+
return result.value;
|
|
194
|
+
}
|
|
195
|
+
// On failure, return a not-installed entry
|
|
196
|
+
return {
|
|
197
|
+
id: definitions[i].id,
|
|
198
|
+
name: definitions[i].name,
|
|
199
|
+
installed: false,
|
|
200
|
+
definition: definitions[i],
|
|
201
|
+
detectedAt: Date.now(),
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
agents,
|
|
207
|
+
scanned: definitions.length,
|
|
208
|
+
durationMs: Date.now() - startTime,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private async detectAgent(
|
|
213
|
+
definition: CLIAgentDefinition
|
|
214
|
+
): Promise<DetectedAgent> {
|
|
215
|
+
const detectedAt = Date.now();
|
|
216
|
+
|
|
217
|
+
// Step 1: Check if binary exists on PATH
|
|
218
|
+
const binaryPath = await this.findBinary(definition.binary);
|
|
219
|
+
|
|
220
|
+
if (!binaryPath) {
|
|
221
|
+
return {
|
|
222
|
+
id: definition.id,
|
|
223
|
+
name: definition.name,
|
|
224
|
+
installed: false,
|
|
225
|
+
definition,
|
|
226
|
+
detectedAt,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Step 2: Get version string
|
|
231
|
+
const version = await this.getVersion(definition);
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
id: definition.id,
|
|
235
|
+
name: definition.name,
|
|
236
|
+
installed: true,
|
|
237
|
+
version: version ?? undefined,
|
|
238
|
+
path: binaryPath,
|
|
239
|
+
definition,
|
|
240
|
+
detectedAt,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private async findBinary(binary: string): Promise<string | null> {
|
|
245
|
+
try {
|
|
246
|
+
const { stdout } = await execFileAsync("which", [binary], {
|
|
247
|
+
timeout: this.whichTimeoutMs,
|
|
248
|
+
});
|
|
249
|
+
const path = stdout.trim();
|
|
250
|
+
return path || null;
|
|
251
|
+
} catch {
|
|
252
|
+
// Binary not found or which failed
|
|
253
|
+
try {
|
|
254
|
+
// Fallback to command -v
|
|
255
|
+
const { stdout } = await execFileAsync(
|
|
256
|
+
"/bin/sh",
|
|
257
|
+
["-c", `command -v ${binary}`],
|
|
258
|
+
{ timeout: this.whichTimeoutMs }
|
|
259
|
+
);
|
|
260
|
+
const path = stdout.trim();
|
|
261
|
+
return path || null;
|
|
262
|
+
} catch {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private async getVersion(
|
|
269
|
+
definition: CLIAgentDefinition
|
|
270
|
+
): Promise<string | null> {
|
|
271
|
+
try {
|
|
272
|
+
const { stdout, stderr } = await execFileAsync(
|
|
273
|
+
definition.binary,
|
|
274
|
+
definition.versionArgs,
|
|
275
|
+
{ timeout: this.versionTimeoutMs }
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
// Some tools output version to stderr
|
|
279
|
+
const output = stdout || stderr;
|
|
280
|
+
return parseVersion(output);
|
|
281
|
+
} catch {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// =============================================================================
|
|
288
|
+
// Helpers
|
|
289
|
+
// =============================================================================
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Parse a version string from command output.
|
|
293
|
+
* Extracts the first semver-like pattern (e.g., "1.2.3").
|
|
294
|
+
*/
|
|
295
|
+
export function parseVersion(output: string): string | null {
|
|
296
|
+
const match = output.match(VERSION_REGEX);
|
|
297
|
+
return match ? match[0] : null;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Create a new AgentDetector with the given configuration.
|
|
302
|
+
*/
|
|
303
|
+
export function createAgentDetector(
|
|
304
|
+
config?: AgentDetectionConfig
|
|
305
|
+
): AgentDetector {
|
|
306
|
+
return new AgentDetector(config);
|
|
307
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Agent Auto-Detection Module
|
|
3
|
+
*
|
|
4
|
+
* Detects installed CLI coding agents, exposes them via a registry,
|
|
5
|
+
* and provides command construction for headless invocation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Types
|
|
9
|
+
export type {
|
|
10
|
+
CLIAgentDefinition,
|
|
11
|
+
HeadlessConfig,
|
|
12
|
+
DetectedAgent,
|
|
13
|
+
DetectionResult,
|
|
14
|
+
SpawnCommand,
|
|
15
|
+
SpawnCommandOptions,
|
|
16
|
+
AgentDetectionConfig,
|
|
17
|
+
AgentDetectionErrorCode,
|
|
18
|
+
} from "./types.js";
|
|
19
|
+
export { AgentDetectionError } from "./types.js";
|
|
20
|
+
|
|
21
|
+
// Registry
|
|
22
|
+
export {
|
|
23
|
+
AgentRegistry,
|
|
24
|
+
createAgentRegistry,
|
|
25
|
+
BUILTIN_AGENTS,
|
|
26
|
+
} from "./registry.js";
|
|
27
|
+
|
|
28
|
+
// Detector
|
|
29
|
+
export {
|
|
30
|
+
AgentDetector,
|
|
31
|
+
createAgentDetector,
|
|
32
|
+
parseVersion,
|
|
33
|
+
} from "./detector.js";
|
|
34
|
+
|
|
35
|
+
// Command builder
|
|
36
|
+
export { buildSpawnCommand, formatSpawnCommand } from "./command-builder.js";
|