@ag-eco/agentplate-cli 0.13.0
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/LICENSE +21 -0
- package/README.md +462 -0
- package/agents/ap-co-creation.md +90 -0
- package/agents/builder.md +144 -0
- package/agents/coordinator.md +377 -0
- package/agents/lead.md +435 -0
- package/agents/merger.md +164 -0
- package/agents/monitor.md +214 -0
- package/agents/orchestrator.md +239 -0
- package/agents/reviewer.md +140 -0
- package/agents/scout.md +125 -0
- package/agents/supervisor.md +427 -0
- package/package.json +66 -0
- package/src/agents/capabilities.test.ts +85 -0
- package/src/agents/capabilities.ts +125 -0
- package/src/agents/checkpoint.test.ts +88 -0
- package/src/agents/checkpoint.ts +101 -0
- package/src/agents/copilot-hooks-deployer.test.ts +162 -0
- package/src/agents/copilot-hooks-deployer.ts +93 -0
- package/src/agents/guard-rules.test.ts +372 -0
- package/src/agents/guard-rules.ts +97 -0
- package/src/agents/headless-mail-injector.test.ts +709 -0
- package/src/agents/headless-mail-injector.ts +377 -0
- package/src/agents/headless-prompt.test.ts +102 -0
- package/src/agents/headless-prompt.ts +68 -0
- package/src/agents/hooks-deployer.test.ts +3119 -0
- package/src/agents/hooks-deployer.ts +804 -0
- package/src/agents/identity.test.ts +604 -0
- package/src/agents/identity.ts +384 -0
- package/src/agents/lifecycle.test.ts +196 -0
- package/src/agents/lifecycle.ts +183 -0
- package/src/agents/mail-poll-detect.test.ts +153 -0
- package/src/agents/mail-poll-detect.ts +73 -0
- package/src/agents/manifest.test.ts +1026 -0
- package/src/agents/manifest.ts +376 -0
- package/src/agents/overlay.test.ts +1058 -0
- package/src/agents/overlay.ts +490 -0
- package/src/agents/scope-detect.test.ts +190 -0
- package/src/agents/scope-detect.ts +146 -0
- package/src/agents/turn-lock.test.ts +181 -0
- package/src/agents/turn-lock.ts +235 -0
- package/src/agents/turn-runner-dispatch.test.ts +182 -0
- package/src/agents/turn-runner-dispatch.ts +105 -0
- package/src/agents/turn-runner.test.ts +2312 -0
- package/src/agents/turn-runner.ts +1383 -0
- package/src/beads/client.test.ts +217 -0
- package/src/beads/client.ts +230 -0
- package/src/beads/molecules.test.ts +338 -0
- package/src/beads/molecules.ts +198 -0
- package/src/commands/agents.test.ts +328 -0
- package/src/commands/agents.ts +299 -0
- package/src/commands/clean.test.ts +797 -0
- package/src/commands/clean.ts +791 -0
- package/src/commands/completions.test.ts +348 -0
- package/src/commands/completions.ts +981 -0
- package/src/commands/coordinator.test.ts +2975 -0
- package/src/commands/coordinator.ts +1841 -0
- package/src/commands/costs.test.ts +1183 -0
- package/src/commands/costs.ts +599 -0
- package/src/commands/dashboard.test.ts +954 -0
- package/src/commands/dashboard.ts +1212 -0
- package/src/commands/discover.test.ts +288 -0
- package/src/commands/discover.ts +202 -0
- package/src/commands/doctor.test.ts +303 -0
- package/src/commands/doctor.ts +311 -0
- package/src/commands/ecosystem.test.ts +226 -0
- package/src/commands/ecosystem.ts +248 -0
- package/src/commands/errors.test.ts +654 -0
- package/src/commands/errors.ts +197 -0
- package/src/commands/feed.test.ts +709 -0
- package/src/commands/feed.ts +260 -0
- package/src/commands/group.test.ts +475 -0
- package/src/commands/group.ts +546 -0
- package/src/commands/hooks.test.ts +458 -0
- package/src/commands/hooks.ts +263 -0
- package/src/commands/init.test.ts +1011 -0
- package/src/commands/init.ts +967 -0
- package/src/commands/inspect.test.ts +1239 -0
- package/src/commands/inspect.ts +648 -0
- package/src/commands/log.test.ts +1913 -0
- package/src/commands/log.ts +958 -0
- package/src/commands/logs.test.ts +801 -0
- package/src/commands/logs.ts +483 -0
- package/src/commands/mail.test.ts +1501 -0
- package/src/commands/mail.ts +848 -0
- package/src/commands/merge.test.ts +864 -0
- package/src/commands/merge.ts +381 -0
- package/src/commands/metrics.test.ts +458 -0
- package/src/commands/metrics.ts +129 -0
- package/src/commands/monitor.test.ts +191 -0
- package/src/commands/monitor.ts +409 -0
- package/src/commands/nudge.test.ts +579 -0
- package/src/commands/nudge.ts +646 -0
- package/src/commands/orchestrator.ts +42 -0
- package/src/commands/prime.test.ts +612 -0
- package/src/commands/prime.ts +359 -0
- package/src/commands/replay.test.ts +757 -0
- package/src/commands/replay.ts +231 -0
- package/src/commands/run.test.ts +469 -0
- package/src/commands/run.ts +353 -0
- package/src/commands/serve/agent-actions.test.ts +210 -0
- package/src/commands/serve/agent-actions.ts +192 -0
- package/src/commands/serve/build.test.ts +202 -0
- package/src/commands/serve/build.ts +206 -0
- package/src/commands/serve/coordinator-actions.test.ts +339 -0
- package/src/commands/serve/coordinator-actions.ts +410 -0
- package/src/commands/serve/dev.test.ts +168 -0
- package/src/commands/serve/dev.ts +117 -0
- package/src/commands/serve/mail-actions.test.ts +312 -0
- package/src/commands/serve/mail-actions.ts +167 -0
- package/src/commands/serve/rest.test.ts +1680 -0
- package/src/commands/serve/rest.ts +1130 -0
- package/src/commands/serve/static.ts +51 -0
- package/src/commands/serve/ws.test.ts +361 -0
- package/src/commands/serve/ws.ts +332 -0
- package/src/commands/serve.test.ts +459 -0
- package/src/commands/serve.ts +654 -0
- package/src/commands/sling.test.ts +1583 -0
- package/src/commands/sling.ts +1351 -0
- package/src/commands/spec.test.ts +179 -0
- package/src/commands/spec.ts +105 -0
- package/src/commands/status.test.ts +614 -0
- package/src/commands/status.ts +403 -0
- package/src/commands/stop.test.ts +964 -0
- package/src/commands/stop.ts +319 -0
- package/src/commands/supervisor.test.ts +185 -0
- package/src/commands/supervisor.ts +537 -0
- package/src/commands/trace.test.ts +762 -0
- package/src/commands/trace.ts +205 -0
- package/src/commands/update.test.ts +466 -0
- package/src/commands/update.ts +263 -0
- package/src/commands/upgrade.test.ts +48 -0
- package/src/commands/upgrade.ts +240 -0
- package/src/commands/watch.test.ts +257 -0
- package/src/commands/watch.ts +308 -0
- package/src/commands/worktree.test.ts +1297 -0
- package/src/commands/worktree.ts +451 -0
- package/src/config.test.ts +1535 -0
- package/src/config.ts +1064 -0
- package/src/doctor/agents.test.ts +523 -0
- package/src/doctor/agents.ts +399 -0
- package/src/doctor/config-check.test.ts +191 -0
- package/src/doctor/config-check.ts +183 -0
- package/src/doctor/consistency.test.ts +807 -0
- package/src/doctor/consistency.ts +347 -0
- package/src/doctor/databases.test.ts +350 -0
- package/src/doctor/databases.ts +243 -0
- package/src/doctor/dependencies.test.ts +296 -0
- package/src/doctor/dependencies.ts +272 -0
- package/src/doctor/ecosystem.test.ts +308 -0
- package/src/doctor/ecosystem.ts +156 -0
- package/src/doctor/logs.test.ts +253 -0
- package/src/doctor/logs.ts +295 -0
- package/src/doctor/merge-queue.test.ts +315 -0
- package/src/doctor/merge-queue.ts +167 -0
- package/src/doctor/providers.test.ts +409 -0
- package/src/doctor/providers.ts +250 -0
- package/src/doctor/serve.test.ts +95 -0
- package/src/doctor/serve.ts +86 -0
- package/src/doctor/structure.test.ts +423 -0
- package/src/doctor/structure.ts +285 -0
- package/src/doctor/types.ts +43 -0
- package/src/doctor/version.test.ts +241 -0
- package/src/doctor/version.ts +132 -0
- package/src/doctor/watchdog.test.ts +167 -0
- package/src/doctor/watchdog.ts +214 -0
- package/src/e2e/init-sling-lifecycle.test.ts +283 -0
- package/src/errors.test.ts +350 -0
- package/src/errors.ts +217 -0
- package/src/events/store.test.ts +660 -0
- package/src/events/store.ts +369 -0
- package/src/events/tailer.test.ts +719 -0
- package/src/events/tailer.ts +332 -0
- package/src/events/tool-filter.test.ts +330 -0
- package/src/events/tool-filter.ts +126 -0
- package/src/index.ts +533 -0
- package/src/insights/analyzer.test.ts +466 -0
- package/src/insights/analyzer.ts +203 -0
- package/src/insights/quality-gates.test.ts +141 -0
- package/src/insights/quality-gates.ts +156 -0
- package/src/json.test.ts +72 -0
- package/src/json.ts +53 -0
- package/src/loam/client.test.ts +752 -0
- package/src/loam/client.ts +664 -0
- package/src/logging/color.test.ts +252 -0
- package/src/logging/color.ts +105 -0
- package/src/logging/format.test.ts +110 -0
- package/src/logging/format.ts +255 -0
- package/src/logging/logger.test.ts +814 -0
- package/src/logging/logger.ts +266 -0
- package/src/logging/reporter.test.ts +259 -0
- package/src/logging/reporter.ts +110 -0
- package/src/logging/sanitizer.test.ts +190 -0
- package/src/logging/sanitizer.ts +57 -0
- package/src/logging/theme.ts +140 -0
- package/src/mail/broadcast.test.ts +204 -0
- package/src/mail/broadcast.ts +92 -0
- package/src/mail/client.test.ts +774 -0
- package/src/mail/client.ts +236 -0
- package/src/mail/store.test.ts +898 -0
- package/src/mail/store.ts +425 -0
- package/src/merge/lock.test.ts +149 -0
- package/src/merge/lock.ts +140 -0
- package/src/merge/predict.test.ts +387 -0
- package/src/merge/predict.ts +249 -0
- package/src/merge/queue.test.ts +426 -0
- package/src/merge/queue.ts +246 -0
- package/src/merge/resolver.test.ts +1993 -0
- package/src/merge/resolver.ts +926 -0
- package/src/metrics/pricing.test.ts +258 -0
- package/src/metrics/pricing.ts +135 -0
- package/src/metrics/store.test.ts +978 -0
- package/src/metrics/store.ts +501 -0
- package/src/metrics/summary.test.ts +398 -0
- package/src/metrics/summary.ts +178 -0
- package/src/metrics/transcript.test.ts +483 -0
- package/src/metrics/transcript.ts +114 -0
- package/src/runtimes/__fixtures__/claude-stream-fixture.ts +22 -0
- package/src/runtimes/aider.test.ts +124 -0
- package/src/runtimes/aider.ts +147 -0
- package/src/runtimes/amp.test.ts +164 -0
- package/src/runtimes/amp.ts +154 -0
- package/src/runtimes/claude.test.ts +1474 -0
- package/src/runtimes/claude.ts +579 -0
- package/src/runtimes/codex.test.ts +805 -0
- package/src/runtimes/codex.ts +273 -0
- package/src/runtimes/connections.test.ts +214 -0
- package/src/runtimes/connections.ts +103 -0
- package/src/runtimes/copilot.test.ts +707 -0
- package/src/runtimes/copilot.ts +316 -0
- package/src/runtimes/cursor.test.ts +497 -0
- package/src/runtimes/cursor.ts +205 -0
- package/src/runtimes/gemini.test.ts +537 -0
- package/src/runtimes/gemini.ts +243 -0
- package/src/runtimes/goose.test.ts +133 -0
- package/src/runtimes/goose.ts +157 -0
- package/src/runtimes/headless-connection.test.ts +264 -0
- package/src/runtimes/headless-connection.ts +158 -0
- package/src/runtimes/opencode.test.ts +325 -0
- package/src/runtimes/opencode.ts +188 -0
- package/src/runtimes/pi-guards.test.ts +486 -0
- package/src/runtimes/pi-guards.ts +367 -0
- package/src/runtimes/pi.test.ts +789 -0
- package/src/runtimes/pi.ts +305 -0
- package/src/runtimes/registry.test.ts +196 -0
- package/src/runtimes/registry.ts +99 -0
- package/src/runtimes/sapling.test.ts +1267 -0
- package/src/runtimes/sapling.ts +710 -0
- package/src/runtimes/types.ts +266 -0
- package/src/schema-consistency.test.ts +246 -0
- package/src/sessions/compat.test.ts +281 -0
- package/src/sessions/compat.ts +105 -0
- package/src/sessions/store.test.ts +1748 -0
- package/src/sessions/store.ts +858 -0
- package/src/test-helpers.test.ts +124 -0
- package/src/test-helpers.ts +145 -0
- package/src/test-setup.test.ts +31 -0
- package/src/test-setup.ts +28 -0
- package/src/tools/loam/api.ts +368 -0
- package/src/tools/loam/cli.ts +278 -0
- package/src/tools/loam/commands/add.ts +52 -0
- package/src/tools/loam/commands/archive.ts +214 -0
- package/src/tools/loam/commands/audit.ts +276 -0
- package/src/tools/loam/commands/compact.ts +1062 -0
- package/src/tools/loam/commands/completions.ts +79 -0
- package/src/tools/loam/commands/config.ts +381 -0
- package/src/tools/loam/commands/delete-domain.ts +121 -0
- package/src/tools/loam/commands/delete.ts +316 -0
- package/src/tools/loam/commands/diff.ts +200 -0
- package/src/tools/loam/commands/doctor.ts +1113 -0
- package/src/tools/loam/commands/edit.ts +226 -0
- package/src/tools/loam/commands/init.ts +31 -0
- package/src/tools/loam/commands/learn.ts +179 -0
- package/src/tools/loam/commands/move.ts +323 -0
- package/src/tools/loam/commands/onboard.ts +374 -0
- package/src/tools/loam/commands/outcome.ts +185 -0
- package/src/tools/loam/commands/prime.ts +688 -0
- package/src/tools/loam/commands/prune.ts +614 -0
- package/src/tools/loam/commands/query.ts +218 -0
- package/src/tools/loam/commands/rank.ts +180 -0
- package/src/tools/loam/commands/ready.ts +189 -0
- package/src/tools/loam/commands/record.ts +1210 -0
- package/src/tools/loam/commands/restore.ts +166 -0
- package/src/tools/loam/commands/search.ts +327 -0
- package/src/tools/loam/commands/setup.ts +887 -0
- package/src/tools/loam/commands/status.ts +103 -0
- package/src/tools/loam/commands/sync.ts +298 -0
- package/src/tools/loam/commands/update.ts +19 -0
- package/src/tools/loam/commands/upgrade.ts +93 -0
- package/src/tools/loam/commands/validate.ts +190 -0
- package/src/tools/loam/index.ts +62 -0
- package/src/tools/loam/log.ts +127 -0
- package/src/tools/loam/registry/builtins.ts +409 -0
- package/src/tools/loam/registry/custom.ts +431 -0
- package/src/tools/loam/registry/init.ts +55 -0
- package/src/tools/loam/registry/template.ts +40 -0
- package/src/tools/loam/registry/type-registry.ts +113 -0
- package/src/tools/loam/schemas/config-schema.ts +489 -0
- package/src/tools/loam/schemas/config.ts +245 -0
- package/src/tools/loam/schemas/index.ts +18 -0
- package/src/tools/loam/schemas/record-schema.ts +191 -0
- package/src/tools/loam/schemas/record.ts +115 -0
- package/src/tools/loam/utils/active-work.ts +205 -0
- package/src/tools/loam/utils/anchor-validity.ts +80 -0
- package/src/tools/loam/utils/archive.ts +146 -0
- package/src/tools/loam/utils/audit.ts +667 -0
- package/src/tools/loam/utils/bm25.ts +238 -0
- package/src/tools/loam/utils/budget.ts +142 -0
- package/src/tools/loam/utils/config.ts +344 -0
- package/src/tools/loam/utils/dir-anchors.ts +62 -0
- package/src/tools/loam/utils/domain-rules.ts +114 -0
- package/src/tools/loam/utils/expertise.ts +393 -0
- package/src/tools/loam/utils/format-helpers.ts +96 -0
- package/src/tools/loam/utils/format.ts +1234 -0
- package/src/tools/loam/utils/git-context.ts +50 -0
- package/src/tools/loam/utils/git.ts +183 -0
- package/src/tools/loam/utils/hooks.ts +299 -0
- package/src/tools/loam/utils/index.ts +52 -0
- package/src/tools/loam/utils/json-output.ts +13 -0
- package/src/tools/loam/utils/lock.ts +76 -0
- package/src/tools/loam/utils/markers.ts +48 -0
- package/src/tools/loam/utils/numeric-flags.ts +20 -0
- package/src/tools/loam/utils/palette.ts +44 -0
- package/src/tools/loam/utils/prime-ranking.ts +135 -0
- package/src/tools/loam/utils/recipe-discovery.ts +195 -0
- package/src/tools/loam/utils/runtime-flags.ts +28 -0
- package/src/tools/loam/utils/scoring.ts +94 -0
- package/src/tools/loam/utils/version.ts +116 -0
- package/src/tools/sprout/commands/block.ts +64 -0
- package/src/tools/sprout/commands/blocked.ts +86 -0
- package/src/tools/sprout/commands/close.ts +129 -0
- package/src/tools/sprout/commands/completions.ts +198 -0
- package/src/tools/sprout/commands/config.ts +238 -0
- package/src/tools/sprout/commands/create.ts +164 -0
- package/src/tools/sprout/commands/dep.ts +148 -0
- package/src/tools/sprout/commands/doctor.ts +979 -0
- package/src/tools/sprout/commands/init.ts +83 -0
- package/src/tools/sprout/commands/label.ts +178 -0
- package/src/tools/sprout/commands/list.ts +210 -0
- package/src/tools/sprout/commands/migrate.ts +133 -0
- package/src/tools/sprout/commands/onboard.ts +207 -0
- package/src/tools/sprout/commands/plan-show.ts +278 -0
- package/src/tools/sprout/commands/plan.ts +2526 -0
- package/src/tools/sprout/commands/prime.ts +399 -0
- package/src/tools/sprout/commands/ready.ts +245 -0
- package/src/tools/sprout/commands/search.ts +221 -0
- package/src/tools/sprout/commands/show.ts +277 -0
- package/src/tools/sprout/commands/stats.ts +146 -0
- package/src/tools/sprout/commands/sync.ts +134 -0
- package/src/tools/sprout/commands/tpl.ts +364 -0
- package/src/tools/sprout/commands/unblock.ts +115 -0
- package/src/tools/sprout/commands/update.ts +257 -0
- package/src/tools/sprout/commands/upgrade.ts +91 -0
- package/src/tools/sprout/config-schema.ts +152 -0
- package/src/tools/sprout/config.ts +355 -0
- package/src/tools/sprout/filter.ts +107 -0
- package/src/tools/sprout/format.ts +43 -0
- package/src/tools/sprout/id.ts +22 -0
- package/src/tools/sprout/index.ts +204 -0
- package/src/tools/sprout/log.ts +76 -0
- package/src/tools/sprout/markers.ts +22 -0
- package/src/tools/sprout/output.ts +121 -0
- package/src/tools/sprout/plan-backref.ts +93 -0
- package/src/tools/sprout/plan-context.ts +81 -0
- package/src/tools/sprout/plan-domain.ts +139 -0
- package/src/tools/sprout/plan-lifecycle.ts +65 -0
- package/src/tools/sprout/plan-loam.ts +207 -0
- package/src/tools/sprout/plan-schema.ts +209 -0
- package/src/tools/sprout/sort.ts +31 -0
- package/src/tools/sprout/store.ts +172 -0
- package/src/tools/sprout/types.ts +118 -0
- package/src/tools/sprout/validation.ts +119 -0
- package/src/tools/sprout/version.ts +1 -0
- package/src/tools/sprout/yaml.ts +387 -0
- package/src/tools/trellis/commands/archive.ts +87 -0
- package/src/tools/trellis/commands/completions.ts +610 -0
- package/src/tools/trellis/commands/config.ts +382 -0
- package/src/tools/trellis/commands/create.ts +252 -0
- package/src/tools/trellis/commands/diff.ts +150 -0
- package/src/tools/trellis/commands/doctor.ts +771 -0
- package/src/tools/trellis/commands/emit.ts +365 -0
- package/src/tools/trellis/commands/history.ts +83 -0
- package/src/tools/trellis/commands/import.ts +198 -0
- package/src/tools/trellis/commands/init.ts +81 -0
- package/src/tools/trellis/commands/list.ts +103 -0
- package/src/tools/trellis/commands/onboard.ts +156 -0
- package/src/tools/trellis/commands/pin.ts +172 -0
- package/src/tools/trellis/commands/prime.ts +193 -0
- package/src/tools/trellis/commands/render.ts +122 -0
- package/src/tools/trellis/commands/schema.ts +353 -0
- package/src/tools/trellis/commands/show.ts +115 -0
- package/src/tools/trellis/commands/stats.ts +65 -0
- package/src/tools/trellis/commands/sync.ts +112 -0
- package/src/tools/trellis/commands/tree.ts +123 -0
- package/src/tools/trellis/commands/update.ts +330 -0
- package/src/tools/trellis/commands/upgrade.ts +95 -0
- package/src/tools/trellis/commands/validate.ts +166 -0
- package/src/tools/trellis/config-schema.ts +81 -0
- package/src/tools/trellis/config.ts +108 -0
- package/src/tools/trellis/frontmatter.ts +348 -0
- package/src/tools/trellis/id.ts +24 -0
- package/src/tools/trellis/index.ts +209 -0
- package/src/tools/trellis/markers.ts +28 -0
- package/src/tools/trellis/output.ts +84 -0
- package/src/tools/trellis/render.ts +212 -0
- package/src/tools/trellis/store.ts +144 -0
- package/src/tools/trellis/types.ts +82 -0
- package/src/tools/trellis/validate.ts +199 -0
- package/src/tools/trellis/yaml.ts +309 -0
- package/src/tracker/beads.test.ts +454 -0
- package/src/tracker/beads.ts +56 -0
- package/src/tracker/factory.test.ts +90 -0
- package/src/tracker/factory.ts +65 -0
- package/src/tracker/sprout.test.ts +461 -0
- package/src/tracker/sprout.ts +182 -0
- package/src/tracker/types.ts +52 -0
- package/src/trellis/client.test.ts +107 -0
- package/src/trellis/client.ts +179 -0
- package/src/types.ts +970 -0
- package/src/utils/bin.test.ts +10 -0
- package/src/utils/bin.ts +37 -0
- package/src/utils/browser.test.ts +49 -0
- package/src/utils/browser.ts +48 -0
- package/src/utils/fs.test.ts +119 -0
- package/src/utils/fs.ts +62 -0
- package/src/utils/pid.test.ts +152 -0
- package/src/utils/pid.ts +130 -0
- package/src/utils/process-scan.test.ts +53 -0
- package/src/utils/process-scan.ts +76 -0
- package/src/utils/time.test.ts +43 -0
- package/src/utils/time.ts +37 -0
- package/src/utils/version.test.ts +33 -0
- package/src/utils/version.ts +70 -0
- package/src/version.ts +5 -0
- package/src/watchdog/daemon.test.ts +3721 -0
- package/src/watchdog/daemon.ts +1257 -0
- package/src/watchdog/health.test.ts +830 -0
- package/src/watchdog/health.ts +434 -0
- package/src/watchdog/triage.test.ts +205 -0
- package/src/watchdog/triage.ts +205 -0
- package/src/worktree/manager.test.ts +720 -0
- package/src/worktree/manager.ts +405 -0
- package/src/worktree/process.test.ts +172 -0
- package/src/worktree/process.ts +131 -0
- package/src/worktree/tmux.test.ts +1616 -0
- package/src/worktree/tmux.ts +721 -0
- package/templates/CLAUDE.md.tmpl +100 -0
- package/templates/copilot-hooks.json.tmpl +13 -0
- package/templates/hooks.json.tmpl +109 -0
- package/templates/overlay.md.tmpl +88 -0
- package/ui/dist/apple-touch-icon-bdy6teep.png +0 -0
- package/ui/dist/chunk-8s31f05k.css +1 -0
- package/ui/dist/chunk-vm5rz679.js +300 -0
- package/ui/dist/favicon-nzb39vza.svg +4 -0
- package/ui/dist/index.html +17 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the agents command.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
|
|
6
|
+
import { mkdtemp } from "node:fs/promises";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { createSessionStore } from "../sessions/store.ts";
|
|
10
|
+
import { cleanupTempDir } from "../test-helpers.ts";
|
|
11
|
+
import type { AgentSession } from "../types.ts";
|
|
12
|
+
import { agentsCommand, discoverAgents, extractFileScope } from "./agents.ts";
|
|
13
|
+
|
|
14
|
+
describe("extractFileScope", () => {
|
|
15
|
+
let tempDir: string;
|
|
16
|
+
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
tempDir = await mkdtemp(join(tmpdir(), "agentplate-test-"));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should return empty array when overlay doesn't exist", async () => {
|
|
22
|
+
const scope = await extractFileScope(tempDir);
|
|
23
|
+
expect(scope).toEqual([]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should return empty array when 'No file scope restrictions'", async () => {
|
|
27
|
+
const overlayPath = join(tempDir, ".claude", "CLAUDE.md");
|
|
28
|
+
const content = `# Agent Overlay
|
|
29
|
+
|
|
30
|
+
## File Scope (exclusive ownership)
|
|
31
|
+
|
|
32
|
+
No file scope restrictions. You may modify any file in the worktree.
|
|
33
|
+
|
|
34
|
+
## Expertise
|
|
35
|
+
|
|
36
|
+
Some expertise here.
|
|
37
|
+
`;
|
|
38
|
+
await Bun.write(overlayPath, content);
|
|
39
|
+
const scope = await extractFileScope(tempDir);
|
|
40
|
+
expect(scope).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should extract file paths from valid overlay", async () => {
|
|
44
|
+
const overlayPath = join(tempDir, ".claude", "CLAUDE.md");
|
|
45
|
+
const content = `# Agent Overlay
|
|
46
|
+
|
|
47
|
+
## File Scope (exclusive ownership)
|
|
48
|
+
|
|
49
|
+
These files are yours to modify:
|
|
50
|
+
|
|
51
|
+
- \`src/commands/agents.ts\`
|
|
52
|
+
- \`src/commands/agents.test.ts\`
|
|
53
|
+
- \`src/index.ts\`
|
|
54
|
+
|
|
55
|
+
## Expertise
|
|
56
|
+
|
|
57
|
+
Some expertise here.
|
|
58
|
+
`;
|
|
59
|
+
await Bun.write(overlayPath, content);
|
|
60
|
+
const scope = await extractFileScope(tempDir);
|
|
61
|
+
expect(scope).toEqual([
|
|
62
|
+
"src/commands/agents.ts",
|
|
63
|
+
"src/commands/agents.test.ts",
|
|
64
|
+
"src/index.ts",
|
|
65
|
+
]);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterEach(async () => {
|
|
69
|
+
await cleanupTempDir(tempDir);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("discoverAgents", () => {
|
|
74
|
+
let tempDir: string;
|
|
75
|
+
let dbPath: string;
|
|
76
|
+
|
|
77
|
+
beforeEach(async () => {
|
|
78
|
+
tempDir = await mkdtemp(join(tmpdir(), "agentplate-test-"));
|
|
79
|
+
const agentplateDir = join(tempDir, ".agentplate");
|
|
80
|
+
await Bun.write(join(agentplateDir, ".gitkeep"), "");
|
|
81
|
+
dbPath = join(agentplateDir, "sessions.db");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should return empty when no sessions", async () => {
|
|
85
|
+
const store = createSessionStore(dbPath);
|
|
86
|
+
store.close();
|
|
87
|
+
|
|
88
|
+
const agents = await discoverAgents(tempDir);
|
|
89
|
+
expect(agents).toEqual([]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should return active agents", async () => {
|
|
93
|
+
const store = createSessionStore(dbPath);
|
|
94
|
+
|
|
95
|
+
const session: AgentSession = {
|
|
96
|
+
id: "session-1",
|
|
97
|
+
agentName: "builder-test",
|
|
98
|
+
capability: "builder",
|
|
99
|
+
worktreePath: join(tempDir, ".agentplate", "worktrees", "builder-test"),
|
|
100
|
+
branchName: "agentplate/builder-test/task-123",
|
|
101
|
+
taskId: "task-123",
|
|
102
|
+
tmuxSession: "agentplate-test-builder",
|
|
103
|
+
state: "working",
|
|
104
|
+
pid: 12345,
|
|
105
|
+
parentAgent: null,
|
|
106
|
+
depth: 0,
|
|
107
|
+
runId: "run-1",
|
|
108
|
+
startedAt: "2024-01-01T00:00:00Z",
|
|
109
|
+
lastActivity: "2024-01-01T00:01:00Z",
|
|
110
|
+
escalationLevel: 0,
|
|
111
|
+
stalledSince: null,
|
|
112
|
+
transcriptPath: null,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
store.upsert(session);
|
|
116
|
+
store.close();
|
|
117
|
+
|
|
118
|
+
const agents = await discoverAgents(tempDir);
|
|
119
|
+
expect(agents).toHaveLength(1);
|
|
120
|
+
expect(agents[0]?.agentName).toBe("builder-test");
|
|
121
|
+
expect(agents[0]?.capability).toBe("builder");
|
|
122
|
+
expect(agents[0]?.state).toBe("working");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("should filter by capability", async () => {
|
|
126
|
+
const store = createSessionStore(dbPath);
|
|
127
|
+
|
|
128
|
+
const builder: AgentSession = {
|
|
129
|
+
id: "session-1",
|
|
130
|
+
agentName: "builder-test",
|
|
131
|
+
capability: "builder",
|
|
132
|
+
worktreePath: join(tempDir, ".agentplate", "worktrees", "builder-test"),
|
|
133
|
+
branchName: "agentplate/builder-test/task-123",
|
|
134
|
+
taskId: "task-123",
|
|
135
|
+
tmuxSession: "agentplate-test-builder",
|
|
136
|
+
state: "working",
|
|
137
|
+
pid: 12345,
|
|
138
|
+
parentAgent: null,
|
|
139
|
+
depth: 0,
|
|
140
|
+
runId: "run-1",
|
|
141
|
+
startedAt: "2024-01-01T00:00:00Z",
|
|
142
|
+
lastActivity: "2024-01-01T00:01:00Z",
|
|
143
|
+
escalationLevel: 0,
|
|
144
|
+
stalledSince: null,
|
|
145
|
+
transcriptPath: null,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const scout: AgentSession = {
|
|
149
|
+
id: "session-2",
|
|
150
|
+
agentName: "scout-test",
|
|
151
|
+
capability: "scout",
|
|
152
|
+
worktreePath: join(tempDir, ".agentplate", "worktrees", "scout-test"),
|
|
153
|
+
branchName: "agentplate/scout-test/task-456",
|
|
154
|
+
taskId: "task-456",
|
|
155
|
+
tmuxSession: "agentplate-test-scout",
|
|
156
|
+
state: "working",
|
|
157
|
+
pid: 12346,
|
|
158
|
+
parentAgent: null,
|
|
159
|
+
depth: 0,
|
|
160
|
+
runId: "run-1",
|
|
161
|
+
startedAt: "2024-01-01T00:00:00Z",
|
|
162
|
+
lastActivity: "2024-01-01T00:01:00Z",
|
|
163
|
+
escalationLevel: 0,
|
|
164
|
+
stalledSince: null,
|
|
165
|
+
transcriptPath: null,
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
store.upsert(builder);
|
|
169
|
+
store.upsert(scout);
|
|
170
|
+
store.close();
|
|
171
|
+
|
|
172
|
+
const agents = await discoverAgents(tempDir, { capability: "builder" });
|
|
173
|
+
expect(agents).toHaveLength(1);
|
|
174
|
+
expect(agents[0]?.agentName).toBe("builder-test");
|
|
175
|
+
expect(agents[0]?.capability).toBe("builder");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("should includeAll returns completed agents too", async () => {
|
|
179
|
+
const store = createSessionStore(dbPath);
|
|
180
|
+
|
|
181
|
+
const working: AgentSession = {
|
|
182
|
+
id: "session-1",
|
|
183
|
+
agentName: "builder-working",
|
|
184
|
+
capability: "builder",
|
|
185
|
+
worktreePath: join(tempDir, ".agentplate", "worktrees", "builder-working"),
|
|
186
|
+
branchName: "agentplate/builder-working/task-123",
|
|
187
|
+
taskId: "task-123",
|
|
188
|
+
tmuxSession: "agentplate-test-working",
|
|
189
|
+
state: "working",
|
|
190
|
+
pid: 12345,
|
|
191
|
+
parentAgent: null,
|
|
192
|
+
depth: 0,
|
|
193
|
+
runId: "run-1",
|
|
194
|
+
startedAt: "2024-01-01T00:00:00Z",
|
|
195
|
+
lastActivity: "2024-01-01T00:01:00Z",
|
|
196
|
+
escalationLevel: 0,
|
|
197
|
+
stalledSince: null,
|
|
198
|
+
transcriptPath: null,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const completed: AgentSession = {
|
|
202
|
+
id: "session-2",
|
|
203
|
+
agentName: "builder-completed",
|
|
204
|
+
capability: "builder",
|
|
205
|
+
worktreePath: join(tempDir, ".agentplate", "worktrees", "builder-completed"),
|
|
206
|
+
branchName: "agentplate/builder-completed/task-456",
|
|
207
|
+
taskId: "task-456",
|
|
208
|
+
tmuxSession: "agentplate-test-completed",
|
|
209
|
+
state: "completed",
|
|
210
|
+
pid: null,
|
|
211
|
+
parentAgent: null,
|
|
212
|
+
depth: 0,
|
|
213
|
+
runId: "run-1",
|
|
214
|
+
startedAt: "2024-01-01T00:00:00Z",
|
|
215
|
+
lastActivity: "2024-01-01T00:02:00Z",
|
|
216
|
+
escalationLevel: 0,
|
|
217
|
+
stalledSince: null,
|
|
218
|
+
transcriptPath: null,
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
store.upsert(working);
|
|
222
|
+
store.upsert(completed);
|
|
223
|
+
store.close();
|
|
224
|
+
|
|
225
|
+
// Without includeAll, only active agents
|
|
226
|
+
const activeAgents = await discoverAgents(tempDir);
|
|
227
|
+
expect(activeAgents).toHaveLength(1);
|
|
228
|
+
expect(activeAgents[0]?.agentName).toBe("builder-working");
|
|
229
|
+
|
|
230
|
+
// With includeAll, both working and completed
|
|
231
|
+
const allAgents = await discoverAgents(tempDir, { includeAll: true });
|
|
232
|
+
expect(allAgents).toHaveLength(2);
|
|
233
|
+
const names = allAgents.map((a) => a.agentName);
|
|
234
|
+
expect(names).toContain("builder-working");
|
|
235
|
+
expect(names).toContain("builder-completed");
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
afterEach(async () => {
|
|
239
|
+
await cleanupTempDir(tempDir);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
describe("agentsCommand", () => {
|
|
244
|
+
let tempDir: string;
|
|
245
|
+
let originalCwd: string;
|
|
246
|
+
let originalStdoutWrite: typeof process.stdout.write;
|
|
247
|
+
let stdoutBuffer: string;
|
|
248
|
+
|
|
249
|
+
beforeEach(async () => {
|
|
250
|
+
tempDir = await mkdtemp(join(tmpdir(), "agentplate-test-"));
|
|
251
|
+
const agentplateDir = join(tempDir, ".agentplate");
|
|
252
|
+
|
|
253
|
+
// Create config.yaml
|
|
254
|
+
const configContent = `project:
|
|
255
|
+
name: test-project
|
|
256
|
+
root: ${tempDir}
|
|
257
|
+
canonicalBranch: main
|
|
258
|
+
agents:
|
|
259
|
+
manifestPath: .agentplate/agent-manifest.json
|
|
260
|
+
baseDir: agents
|
|
261
|
+
maxConcurrent: 5
|
|
262
|
+
staggerDelayMs: 100
|
|
263
|
+
maxDepth: 2
|
|
264
|
+
worktrees:
|
|
265
|
+
baseDir: .agentplate/worktrees
|
|
266
|
+
beads:
|
|
267
|
+
enabled: true
|
|
268
|
+
loam:
|
|
269
|
+
enabled: true
|
|
270
|
+
domains: []
|
|
271
|
+
primeFormat: markdown
|
|
272
|
+
merge:
|
|
273
|
+
aiResolveEnabled: false
|
|
274
|
+
reimagineEnabled: false
|
|
275
|
+
watchdog:
|
|
276
|
+
tier0Enabled: false
|
|
277
|
+
tier0IntervalMs: 30000
|
|
278
|
+
tier1Enabled: false
|
|
279
|
+
tier2Enabled: false
|
|
280
|
+
staleThresholdMs: 300000
|
|
281
|
+
zombieThresholdMs: 600000
|
|
282
|
+
nudgeIntervalMs: 60000
|
|
283
|
+
logging:
|
|
284
|
+
verbose: false
|
|
285
|
+
redactSecrets: true
|
|
286
|
+
`;
|
|
287
|
+
await Bun.write(join(agentplateDir, "config.yaml"), configContent);
|
|
288
|
+
|
|
289
|
+
// Create sessions.db
|
|
290
|
+
const dbPath = join(agentplateDir, "sessions.db");
|
|
291
|
+
const store = createSessionStore(dbPath);
|
|
292
|
+
store.close();
|
|
293
|
+
|
|
294
|
+
// Mock stdout.write
|
|
295
|
+
stdoutBuffer = "";
|
|
296
|
+
originalStdoutWrite = process.stdout.write;
|
|
297
|
+
process.stdout.write = mock((chunk: unknown) => {
|
|
298
|
+
stdoutBuffer += String(chunk);
|
|
299
|
+
return true;
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// Change to temp dir
|
|
303
|
+
originalCwd = process.cwd();
|
|
304
|
+
process.chdir(tempDir);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it("should show help with --help flag", async () => {
|
|
308
|
+
await agentsCommand(["--help"]);
|
|
309
|
+
expect(stdoutBuffer).toContain("agents");
|
|
310
|
+
expect(stdoutBuffer).toContain("discover");
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it("should show help with no subcommand", async () => {
|
|
314
|
+
await agentsCommand([]);
|
|
315
|
+
expect(stdoutBuffer).toContain("agents");
|
|
316
|
+
expect(stdoutBuffer).toContain("discover");
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it("should error on unknown subcommand", async () => {
|
|
320
|
+
await expect(agentsCommand(["unknown"])).rejects.toThrow("unknown command");
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
afterEach(async () => {
|
|
324
|
+
process.stdout.write = originalStdoutWrite;
|
|
325
|
+
process.chdir(originalCwd);
|
|
326
|
+
await cleanupTempDir(tempDir);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command: ap agents <sub> [--json]
|
|
3
|
+
*
|
|
4
|
+
* Discover and query agents by capability.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
import { loadConfig } from "../config.ts";
|
|
10
|
+
import { ValidationError } from "../errors.ts";
|
|
11
|
+
import { jsonOutput } from "../json.ts";
|
|
12
|
+
import { accent, color } from "../logging/color.ts";
|
|
13
|
+
import { getAllRuntimes, getRuntime } from "../runtimes/registry.ts";
|
|
14
|
+
import { openSessionStore } from "../sessions/compat.ts";
|
|
15
|
+
import { type AgentSession, SUPPORTED_CAPABILITIES } from "../types.ts";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Discovered agent information including file scope.
|
|
19
|
+
*/
|
|
20
|
+
export interface DiscoveredAgent {
|
|
21
|
+
agentName: string;
|
|
22
|
+
capability: string;
|
|
23
|
+
state: string;
|
|
24
|
+
taskId: string;
|
|
25
|
+
branchName: string;
|
|
26
|
+
parentAgent: string | null;
|
|
27
|
+
depth: number;
|
|
28
|
+
fileScope: string[];
|
|
29
|
+
startedAt: string;
|
|
30
|
+
lastActivity: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Build the list of known instruction file paths from all registered runtimes. */
|
|
34
|
+
function getKnownInstructionPaths(): string[] {
|
|
35
|
+
return [...new Set(getAllRuntimes().map((r) => r.instructionPath))];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Extract file scope from an agent's overlay instruction file.
|
|
40
|
+
* Returns empty array if no overlay exists, has no file scope restrictions,
|
|
41
|
+
* or can't be read.
|
|
42
|
+
*
|
|
43
|
+
* @param worktreePath - Absolute path to the agent's worktree
|
|
44
|
+
* @param runtimeInstructionPath - Optional runtime-specific instruction path to try first
|
|
45
|
+
* @returns Array of file paths (relative to worktree root)
|
|
46
|
+
*/
|
|
47
|
+
export async function extractFileScope(
|
|
48
|
+
worktreePath: string,
|
|
49
|
+
runtimeInstructionPath?: string,
|
|
50
|
+
): Promise<string[]> {
|
|
51
|
+
try {
|
|
52
|
+
let content: string | null = null;
|
|
53
|
+
const knownPaths = getKnownInstructionPaths();
|
|
54
|
+
const pathsToTry = runtimeInstructionPath
|
|
55
|
+
? [runtimeInstructionPath, ...knownPaths]
|
|
56
|
+
: knownPaths;
|
|
57
|
+
for (const relPath of pathsToTry) {
|
|
58
|
+
const overlayPath = join(worktreePath, relPath);
|
|
59
|
+
const overlayFile = Bun.file(overlayPath);
|
|
60
|
+
if (await overlayFile.exists()) {
|
|
61
|
+
content = await overlayFile.text();
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (content === null) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Find the section between "## File Scope (exclusive ownership)" and "## Expertise"
|
|
70
|
+
const startMarker = "## File Scope (exclusive ownership)";
|
|
71
|
+
const endMarker = "## Expertise";
|
|
72
|
+
|
|
73
|
+
const startIdx = content.indexOf(startMarker);
|
|
74
|
+
if (startIdx === -1) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const endIdx = content.indexOf(endMarker, startIdx);
|
|
79
|
+
if (endIdx === -1) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const section = content.slice(startIdx, endIdx);
|
|
84
|
+
|
|
85
|
+
// Check for "No file scope restrictions"
|
|
86
|
+
if (section.includes("No file scope restrictions")) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Extract file paths from markdown list items: - `path`
|
|
91
|
+
const paths: string[] = [];
|
|
92
|
+
const regex = /^- `(.+)`$/gm;
|
|
93
|
+
let match = regex.exec(section);
|
|
94
|
+
|
|
95
|
+
while (match !== null) {
|
|
96
|
+
if (match[1]) {
|
|
97
|
+
paths.push(match[1]);
|
|
98
|
+
}
|
|
99
|
+
match = regex.exec(section);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return paths;
|
|
103
|
+
} catch {
|
|
104
|
+
// Best effort: return empty array if anything fails
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Discover agents in the project.
|
|
111
|
+
*
|
|
112
|
+
* @param root - Absolute path to project root
|
|
113
|
+
* @param opts - Filter options
|
|
114
|
+
* @returns Array of discovered agents with file scopes
|
|
115
|
+
*/
|
|
116
|
+
export async function discoverAgents(
|
|
117
|
+
root: string,
|
|
118
|
+
opts?: { capability?: string; includeAll?: boolean },
|
|
119
|
+
): Promise<DiscoveredAgent[]> {
|
|
120
|
+
const agentplateDir = join(root, ".agentplate");
|
|
121
|
+
const { store } = openSessionStore(agentplateDir);
|
|
122
|
+
|
|
123
|
+
// Resolve runtime instruction path from config; fall back gracefully if config is absent.
|
|
124
|
+
let runtimeInstructionPath: string | undefined;
|
|
125
|
+
try {
|
|
126
|
+
const config = await loadConfig(root);
|
|
127
|
+
const runtime = getRuntime(undefined, config);
|
|
128
|
+
runtimeInstructionPath = runtime.instructionPath;
|
|
129
|
+
} catch {
|
|
130
|
+
// Config may not exist in all contexts; KNOWN_INSTRUCTION_PATHS will be used as fallback.
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const sessions: AgentSession[] = opts?.includeAll ? store.getAll() : store.getActive();
|
|
135
|
+
|
|
136
|
+
// Filter by capability if specified
|
|
137
|
+
let filteredSessions = sessions;
|
|
138
|
+
if (opts?.capability) {
|
|
139
|
+
filteredSessions = sessions.filter((s) => s.capability === opts.capability);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Extract file scopes for each agent
|
|
143
|
+
const agents: DiscoveredAgent[] = await Promise.all(
|
|
144
|
+
filteredSessions.map(async (session) => {
|
|
145
|
+
const fileScope = await extractFileScope(session.worktreePath, runtimeInstructionPath);
|
|
146
|
+
return {
|
|
147
|
+
agentName: session.agentName,
|
|
148
|
+
capability: session.capability,
|
|
149
|
+
state: session.state,
|
|
150
|
+
taskId: session.taskId,
|
|
151
|
+
branchName: session.branchName,
|
|
152
|
+
parentAgent: session.parentAgent,
|
|
153
|
+
depth: session.depth,
|
|
154
|
+
fileScope,
|
|
155
|
+
startedAt: session.startedAt,
|
|
156
|
+
lastActivity: session.lastActivity,
|
|
157
|
+
};
|
|
158
|
+
}),
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
return agents;
|
|
162
|
+
} finally {
|
|
163
|
+
store.close();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Format the state icon for display.
|
|
169
|
+
*
|
|
170
|
+
* `in_turn` and `between_turns` (agentplate-3087) render with the same cyan
|
|
171
|
+
* accent as `working` so a spawn-per-turn worker is visually grouped with
|
|
172
|
+
* other healthy/active agents in `ap agents` output. They use distinct
|
|
173
|
+
* glyphs ('>' vs '~') to mirror the dashboard / theme.ts mapping.
|
|
174
|
+
*/
|
|
175
|
+
function getStateIcon(state: string): string {
|
|
176
|
+
switch (state) {
|
|
177
|
+
case "working":
|
|
178
|
+
return color.cyan(">");
|
|
179
|
+
case "in_turn":
|
|
180
|
+
return color.cyan(">");
|
|
181
|
+
case "between_turns":
|
|
182
|
+
return color.cyan("~");
|
|
183
|
+
case "booting":
|
|
184
|
+
return color.green("-");
|
|
185
|
+
case "stalled":
|
|
186
|
+
return color.yellow("!");
|
|
187
|
+
default:
|
|
188
|
+
return " ";
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Print discovered agents in human-readable format.
|
|
194
|
+
*/
|
|
195
|
+
function printAgents(agents: DiscoveredAgent[]): void {
|
|
196
|
+
const w = process.stdout.write.bind(process.stdout);
|
|
197
|
+
|
|
198
|
+
if (agents.length === 0) {
|
|
199
|
+
w("No agents found.\n");
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
w(`Found ${agents.length} agent${agents.length === 1 ? "" : "s"}:\n\n`);
|
|
204
|
+
|
|
205
|
+
for (const agent of agents) {
|
|
206
|
+
const icon = getStateIcon(agent.state);
|
|
207
|
+
w(` ${icon} ${accent(agent.agentName)} [${agent.capability}]\n`);
|
|
208
|
+
w(` State: ${agent.state} | Task: ${accent(agent.taskId)}\n`);
|
|
209
|
+
w(` Branch: ${accent(agent.branchName)}\n`);
|
|
210
|
+
w(
|
|
211
|
+
` Parent: ${agent.parentAgent ? accent(agent.parentAgent) : "none"} | Depth: ${agent.depth}\n`,
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
if (agent.fileScope.length === 0) {
|
|
215
|
+
w(" Files: (unrestricted)\n");
|
|
216
|
+
} else {
|
|
217
|
+
w(` Files: ${agent.fileScope.join(", ")}\n`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
w("\n");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Create the Commander command for `ap agents`.
|
|
226
|
+
*/
|
|
227
|
+
export function createAgentsCommand(): Command {
|
|
228
|
+
const cmd = new Command("agents").description("Discover and query agents");
|
|
229
|
+
|
|
230
|
+
cmd
|
|
231
|
+
.command("discover")
|
|
232
|
+
.description("Find active agents by capability")
|
|
233
|
+
.option(
|
|
234
|
+
"--capability <type>",
|
|
235
|
+
"Filter by capability (builder, scout, reviewer, lead, merger, orchestrator, coordinator, supervisor)",
|
|
236
|
+
)
|
|
237
|
+
.option("--all", "Include completed and zombie agents (default: active only)")
|
|
238
|
+
.option("--json", "Output as JSON")
|
|
239
|
+
.action(async (opts: { capability?: string; all?: boolean; json?: boolean }) => {
|
|
240
|
+
const capability = opts.capability;
|
|
241
|
+
|
|
242
|
+
// Validate capability if provided
|
|
243
|
+
if (capability && !SUPPORTED_CAPABILITIES.includes(capability as never)) {
|
|
244
|
+
throw new ValidationError(
|
|
245
|
+
`Invalid capability: ${capability}. Must be one of: ${SUPPORTED_CAPABILITIES.join(", ")}`,
|
|
246
|
+
{
|
|
247
|
+
field: "capability",
|
|
248
|
+
value: capability,
|
|
249
|
+
},
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const cwd = process.cwd();
|
|
254
|
+
const config = await loadConfig(cwd);
|
|
255
|
+
const root = config.project.root;
|
|
256
|
+
|
|
257
|
+
const agents = await discoverAgents(root, {
|
|
258
|
+
capability,
|
|
259
|
+
includeAll: opts.all ?? false,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
if (opts.json) {
|
|
263
|
+
jsonOutput("agents discover", { agents });
|
|
264
|
+
} else {
|
|
265
|
+
printAgents(agents);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
return cmd;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Entry point for `ap agents <subcommand>`.
|
|
274
|
+
*/
|
|
275
|
+
export async function agentsCommand(args: string[]): Promise<void> {
|
|
276
|
+
const cmd = createAgentsCommand();
|
|
277
|
+
cmd.exitOverride();
|
|
278
|
+
|
|
279
|
+
if (args.length === 0) {
|
|
280
|
+
process.stdout.write(cmd.helpInformation());
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
await cmd.parseAsync(args, { from: "user" });
|
|
286
|
+
} catch (err: unknown) {
|
|
287
|
+
if (err && typeof err === "object" && "code" in err) {
|
|
288
|
+
const code = (err as { code: string }).code;
|
|
289
|
+
if (code === "commander.helpDisplayed" || code === "commander.version") {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (code === "commander.unknownCommand") {
|
|
293
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
294
|
+
throw new ValidationError(message, { field: "subcommand" });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
throw err;
|
|
298
|
+
}
|
|
299
|
+
}
|