@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,124 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
+
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { AiderRuntime } from "./aider.ts";
|
|
6
|
+
|
|
7
|
+
describe("AiderRuntime", () => {
|
|
8
|
+
const runtime = new AiderRuntime();
|
|
9
|
+
let testDir: string;
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
testDir = await mkdtemp(join(tmpdir(), "agentplate-aider-test-"));
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await rm(testDir, { recursive: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("has correct id and instruction path", () => {
|
|
20
|
+
expect(runtime.id).toBe("aider");
|
|
21
|
+
expect(runtime.instructionPath).toBe("CONVENTIONS.md");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("buildSpawnCommand includes --yes-always --no-auto-commits and model", () => {
|
|
25
|
+
const cmd = runtime.buildSpawnCommand({
|
|
26
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
27
|
+
permissionMode: "bypass",
|
|
28
|
+
cwd: "/tmp/test",
|
|
29
|
+
env: {},
|
|
30
|
+
});
|
|
31
|
+
expect(cmd).toContain("aider --yes-always --no-auto-commits");
|
|
32
|
+
expect(cmd).toContain("--model anthropic/claude-sonnet-4-6");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("buildSpawnCommand includes append system prompt as --message", () => {
|
|
36
|
+
const cmd = runtime.buildSpawnCommand({
|
|
37
|
+
model: "sonnet",
|
|
38
|
+
permissionMode: "bypass",
|
|
39
|
+
appendSystemPrompt: "You are a scout.",
|
|
40
|
+
cwd: "/tmp/test",
|
|
41
|
+
env: {},
|
|
42
|
+
});
|
|
43
|
+
expect(cmd).toContain("--message");
|
|
44
|
+
expect(cmd).toContain("You are a scout.");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("buildSpawnCommand uses --read for appendSystemPromptFile", () => {
|
|
48
|
+
const cmd = runtime.buildSpawnCommand({
|
|
49
|
+
model: "sonnet",
|
|
50
|
+
permissionMode: "bypass",
|
|
51
|
+
appendSystemPromptFile: "/tmp/role.md",
|
|
52
|
+
cwd: "/tmp/test",
|
|
53
|
+
env: {},
|
|
54
|
+
});
|
|
55
|
+
expect(cmd).toContain("--read '/tmp/role.md'");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("buildPrintCommand returns correct argv", () => {
|
|
59
|
+
const argv = runtime.buildPrintCommand("fix the bug");
|
|
60
|
+
expect(argv[0]).toBe("aider");
|
|
61
|
+
expect(argv).toContain("--message");
|
|
62
|
+
expect(argv).toContain("fix the bug");
|
|
63
|
+
expect(argv).toContain("--yes-always");
|
|
64
|
+
expect(argv).toContain("--no-auto-commits");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("buildPrintCommand includes model when provided", () => {
|
|
68
|
+
const argv = runtime.buildPrintCommand("fix the bug", "gpt-4o");
|
|
69
|
+
expect(argv).toContain("--model");
|
|
70
|
+
expect(argv).toContain("gpt-4o");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("deployConfig writes CONVENTIONS.md", async () => {
|
|
74
|
+
await runtime.deployConfig(
|
|
75
|
+
testDir,
|
|
76
|
+
{ content: "# Scout instructions" },
|
|
77
|
+
{
|
|
78
|
+
agentName: "scout-1",
|
|
79
|
+
capability: "scout",
|
|
80
|
+
worktreePath: testDir,
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
const content = await readFile(join(testDir, "CONVENTIONS.md"), "utf-8");
|
|
84
|
+
expect(content).toBe("# Scout instructions");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("deployConfig is no-op when overlay is undefined", async () => {
|
|
88
|
+
await runtime.deployConfig(testDir, undefined, {
|
|
89
|
+
agentName: "scout-1",
|
|
90
|
+
capability: "scout",
|
|
91
|
+
worktreePath: testDir,
|
|
92
|
+
});
|
|
93
|
+
const file = Bun.file(join(testDir, "CONVENTIONS.md"));
|
|
94
|
+
expect(await file.exists()).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("detectReady recognizes aider prompt", () => {
|
|
98
|
+
expect(runtime.detectReady("some output\naider> ").phase).toBe("ready");
|
|
99
|
+
expect(runtime.detectReady("> ").phase).toBe("ready");
|
|
100
|
+
expect(runtime.detectReady("Loading...").phase).toBe("loading");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("does not require beacon verification", () => {
|
|
104
|
+
expect(runtime.requiresBeaconVerification()).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("parseTranscript returns null", async () => {
|
|
108
|
+
expect(await runtime.parseTranscript("/nonexistent")).toBeNull();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("buildEnv returns model env vars", () => {
|
|
112
|
+
expect(runtime.buildEnv({ model: "sonnet", env: { OPENAI_API_KEY: "sk-test" } })).toEqual({
|
|
113
|
+
OPENAI_API_KEY: "sk-test",
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("buildEnv returns empty object when no env", () => {
|
|
118
|
+
expect(runtime.buildEnv({ model: "sonnet" })).toEqual({});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("getTranscriptDir returns null", () => {
|
|
122
|
+
expect(runtime.getTranscriptDir("/tmp/project")).toBeNull();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// Aider runtime adapter for agentplate's AgentRuntime interface.
|
|
2
|
+
// Implements the AgentRuntime contract for the `aider` CLI (Paul Gauthier's AI pair programming tool).
|
|
3
|
+
//
|
|
4
|
+
// Key differences from Claude/Pi adapters:
|
|
5
|
+
// - Interactive: `aider` stays alive in tmux as a REPL-like session
|
|
6
|
+
// - Instruction file: .aider.conf.yml or CONVENTIONS.md (we use CONVENTIONS.md for overlay)
|
|
7
|
+
// - No hooks: Aider has no PreToolUse/PostToolUse hook system
|
|
8
|
+
// - One-shot calls use `aider --message <prompt> --yes-always`
|
|
9
|
+
// - Model is passed via `--model <model>` (supports litellm model strings)
|
|
10
|
+
|
|
11
|
+
import { mkdir } from "node:fs/promises";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import type { ResolvedModel } from "../types.ts";
|
|
14
|
+
import type {
|
|
15
|
+
AgentRuntime,
|
|
16
|
+
HooksDef,
|
|
17
|
+
OverlayContent,
|
|
18
|
+
ReadyState,
|
|
19
|
+
SpawnOpts,
|
|
20
|
+
TranscriptSummary,
|
|
21
|
+
} from "./types.ts";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Aider runtime adapter.
|
|
25
|
+
*
|
|
26
|
+
* Implements AgentRuntime for Paul Gauthier's `aider` CLI. Tmux-spawned
|
|
27
|
+
* Aider agents run in interactive mode with `--yes-always` for automatic
|
|
28
|
+
* confirmation of file edits.
|
|
29
|
+
*
|
|
30
|
+
* Security relies on Aider's built-in file-scope limiting — it only edits
|
|
31
|
+
* files explicitly added to its context. No OS-level sandbox or hook guards.
|
|
32
|
+
*/
|
|
33
|
+
export class AiderRuntime implements AgentRuntime {
|
|
34
|
+
readonly id = "aider";
|
|
35
|
+
|
|
36
|
+
/** Experimental — community-contributed adapter, not yet battle-tested in production. */
|
|
37
|
+
readonly stability = "experimental" as const;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Aider reads CONVENTIONS.md from the repo root for project-level instructions.
|
|
41
|
+
* We write the overlay here so Aider picks it up natively.
|
|
42
|
+
*/
|
|
43
|
+
readonly instructionPath = "CONVENTIONS.md";
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Build the shell command string to spawn an Aider agent in a tmux pane.
|
|
47
|
+
*
|
|
48
|
+
* Uses `--yes-always` for automatic approval of file edits and
|
|
49
|
+
* `--no-auto-commits` so agentplate controls git operations.
|
|
50
|
+
*
|
|
51
|
+
* @param opts - Spawn options
|
|
52
|
+
* @returns Shell command string suitable for tmux new-session
|
|
53
|
+
*/
|
|
54
|
+
buildSpawnCommand(opts: SpawnOpts): string {
|
|
55
|
+
let cmd = "aider --yes-always --no-auto-commits";
|
|
56
|
+
|
|
57
|
+
// Aider accepts litellm model strings: provider/model-name
|
|
58
|
+
cmd += ` --model ${opts.model}`;
|
|
59
|
+
|
|
60
|
+
if (opts.appendSystemPromptFile) {
|
|
61
|
+
const escaped = opts.appendSystemPromptFile.replace(/'/g, "'\\''");
|
|
62
|
+
cmd += ` --read '${escaped}'`;
|
|
63
|
+
} else if (opts.appendSystemPrompt) {
|
|
64
|
+
const escaped = opts.appendSystemPrompt.replace(/'/g, "'\\''");
|
|
65
|
+
cmd += ` --message '${escaped} Read CONVENTIONS.md for your task assignment and begin.'`;
|
|
66
|
+
} else {
|
|
67
|
+
cmd += ` --message 'Read CONVENTIONS.md for your task assignment and begin immediately.'`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return cmd;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Build argv for a headless one-shot Aider invocation.
|
|
75
|
+
*
|
|
76
|
+
* Uses `--message` for the prompt with `--yes-always` for non-interactive mode.
|
|
77
|
+
*
|
|
78
|
+
* @param prompt - The prompt to pass
|
|
79
|
+
* @param model - Optional model override
|
|
80
|
+
* @returns Argv array for Bun.spawn
|
|
81
|
+
*/
|
|
82
|
+
buildPrintCommand(prompt: string, model?: string): string[] {
|
|
83
|
+
const cmd = ["aider", "--message", prompt, "--yes-always", "--no-auto-commits"];
|
|
84
|
+
if (model !== undefined) {
|
|
85
|
+
cmd.push("--model", model);
|
|
86
|
+
}
|
|
87
|
+
return cmd;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Deploy per-agent instructions to a worktree.
|
|
92
|
+
*
|
|
93
|
+
* Writes the overlay to CONVENTIONS.md (Aider's native conventions file).
|
|
94
|
+
* No hooks or guard extensions — Aider has no hook system.
|
|
95
|
+
*
|
|
96
|
+
* @param worktreePath - Absolute path to the agent's git worktree
|
|
97
|
+
* @param overlay - Overlay content, or undefined for no-op
|
|
98
|
+
* @param _hooks - Unused — Aider has no hook system
|
|
99
|
+
*/
|
|
100
|
+
async deployConfig(
|
|
101
|
+
worktreePath: string,
|
|
102
|
+
overlay: OverlayContent | undefined,
|
|
103
|
+
_hooks: HooksDef,
|
|
104
|
+
): Promise<void> {
|
|
105
|
+
if (!overlay) return;
|
|
106
|
+
await mkdir(worktreePath, { recursive: true });
|
|
107
|
+
await Bun.write(join(worktreePath, this.instructionPath), overlay.content);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Detect Aider TUI readiness from tmux pane content.
|
|
112
|
+
*
|
|
113
|
+
* Aider shows a prompt like "aider>" or "> " when ready for input.
|
|
114
|
+
*
|
|
115
|
+
* @param paneContent - Captured tmux pane content
|
|
116
|
+
* @returns Readiness phase
|
|
117
|
+
*/
|
|
118
|
+
detectReady(paneContent: string): ReadyState {
|
|
119
|
+
// Aider shows its prompt when ready: "aider> " or "> "
|
|
120
|
+
if (/(?:aider)?>\s*$/.test(paneContent)) {
|
|
121
|
+
return { phase: "ready" };
|
|
122
|
+
}
|
|
123
|
+
return { phase: "loading" };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Aider does not require beacon verification — accepts input reliably. */
|
|
127
|
+
requiresBeaconVerification(): boolean {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Aider does not produce machine-readable transcripts.
|
|
133
|
+
* Returns null — cost tracking relies on provider billing.
|
|
134
|
+
*/
|
|
135
|
+
async parseTranscript(_path: string): Promise<TranscriptSummary | null> {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
buildEnv(model: ResolvedModel): Record<string, string> {
|
|
140
|
+
return model.env ?? {};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Aider logs to .aider.chat.history.md but not in a parseable transcript format. */
|
|
144
|
+
getTranscriptDir(_projectRoot: string): string | null {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
+
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { AmpRuntime } from "./amp.ts";
|
|
6
|
+
|
|
7
|
+
describe("AmpRuntime", () => {
|
|
8
|
+
const runtime = new AmpRuntime();
|
|
9
|
+
let testDir: string;
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
testDir = await mkdtemp(join(tmpdir(), "agentplate-amp-test-"));
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await rm(testDir, { recursive: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("has correct id and instruction path", () => {
|
|
20
|
+
expect(runtime.id).toBe("amp");
|
|
21
|
+
expect(runtime.instructionPath).toBe(".amp/AGENT.md");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("buildSpawnCommand includes --model and --yes", () => {
|
|
25
|
+
const cmd = runtime.buildSpawnCommand({
|
|
26
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
27
|
+
permissionMode: "bypass",
|
|
28
|
+
cwd: "/tmp/test",
|
|
29
|
+
env: {},
|
|
30
|
+
});
|
|
31
|
+
expect(cmd).toContain("amp --model anthropic/claude-sonnet-4-6 --yes");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("buildSpawnCommand includes append system prompt as --prompt", () => {
|
|
35
|
+
const cmd = runtime.buildSpawnCommand({
|
|
36
|
+
model: "sonnet",
|
|
37
|
+
permissionMode: "bypass",
|
|
38
|
+
appendSystemPrompt: "You are a reviewer.",
|
|
39
|
+
cwd: "/tmp/test",
|
|
40
|
+
env: {},
|
|
41
|
+
});
|
|
42
|
+
expect(cmd).toContain("--prompt");
|
|
43
|
+
expect(cmd).toContain("You are a reviewer.");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("buildSpawnCommand uses cat for appendSystemPromptFile", () => {
|
|
47
|
+
const cmd = runtime.buildSpawnCommand({
|
|
48
|
+
model: "sonnet",
|
|
49
|
+
permissionMode: "bypass",
|
|
50
|
+
appendSystemPromptFile: "/tmp/role.md",
|
|
51
|
+
cwd: "/tmp/test",
|
|
52
|
+
env: {},
|
|
53
|
+
});
|
|
54
|
+
expect(cmd).toContain("--prompt");
|
|
55
|
+
expect(cmd).toContain("cat '/tmp/role.md'");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("buildSpawnCommand includes default prompt when no append", () => {
|
|
59
|
+
const cmd = runtime.buildSpawnCommand({
|
|
60
|
+
model: "sonnet",
|
|
61
|
+
permissionMode: "bypass",
|
|
62
|
+
cwd: "/tmp/test",
|
|
63
|
+
env: {},
|
|
64
|
+
});
|
|
65
|
+
expect(cmd).toContain("--prompt");
|
|
66
|
+
expect(cmd).toContain("Read .amp/AGENT.md");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("buildPrintCommand returns correct argv", () => {
|
|
70
|
+
const argv = runtime.buildPrintCommand("review the diff");
|
|
71
|
+
expect(argv[0]).toBe("amp");
|
|
72
|
+
expect(argv).toContain("--prompt");
|
|
73
|
+
expect(argv).toContain("review the diff");
|
|
74
|
+
expect(argv).toContain("--no-input");
|
|
75
|
+
expect(argv).toContain("--yes");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("buildPrintCommand includes model when provided", () => {
|
|
79
|
+
const argv = runtime.buildPrintCommand("review the diff", "gpt-4o");
|
|
80
|
+
expect(argv).toContain("--model");
|
|
81
|
+
expect(argv).toContain("gpt-4o");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("deployConfig writes .amp/AGENT.md", async () => {
|
|
85
|
+
await runtime.deployConfig(
|
|
86
|
+
testDir,
|
|
87
|
+
{ content: "# Reviewer instructions" },
|
|
88
|
+
{
|
|
89
|
+
agentName: "reviewer-1",
|
|
90
|
+
capability: "reviewer",
|
|
91
|
+
worktreePath: testDir,
|
|
92
|
+
},
|
|
93
|
+
);
|
|
94
|
+
const content = await readFile(join(testDir, ".amp", "AGENT.md"), "utf-8");
|
|
95
|
+
expect(content).toBe("# Reviewer instructions");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("deployConfig creates parent .amp directory", async () => {
|
|
99
|
+
await runtime.deployConfig(
|
|
100
|
+
testDir,
|
|
101
|
+
{ content: "# Test" },
|
|
102
|
+
{
|
|
103
|
+
agentName: "test",
|
|
104
|
+
capability: "scout",
|
|
105
|
+
worktreePath: testDir,
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
const file = Bun.file(join(testDir, ".amp", "AGENT.md"));
|
|
109
|
+
expect(await file.exists()).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("deployConfig is no-op when overlay is undefined", async () => {
|
|
113
|
+
await runtime.deployConfig(testDir, undefined, {
|
|
114
|
+
agentName: "test",
|
|
115
|
+
capability: "scout",
|
|
116
|
+
worktreePath: testDir,
|
|
117
|
+
});
|
|
118
|
+
const file = Bun.file(join(testDir, ".amp", "AGENT.md"));
|
|
119
|
+
expect(await file.exists()).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("detectReady requires both prompt AND branding (AND logic)", () => {
|
|
123
|
+
// Both prompt and branding → ready
|
|
124
|
+
expect(runtime.detectReady("some output\namp> ").phase).toBe("ready");
|
|
125
|
+
expect(runtime.detectReady("amp v1.0.0\n> ").phase).toBe("ready");
|
|
126
|
+
expect(runtime.detectReady("AMP CLI\n> ").phase).toBe("ready");
|
|
127
|
+
|
|
128
|
+
// Prompt only (no branding) → loading
|
|
129
|
+
expect(runtime.detectReady("some output\n> ").phase).toBe("loading");
|
|
130
|
+
|
|
131
|
+
// Branding only (no prompt) → loading
|
|
132
|
+
expect(runtime.detectReady("amp v1.0.0").phase).toBe("loading");
|
|
133
|
+
expect(runtime.detectReady("amp v1.2.3 starting...").phase).toBe("loading");
|
|
134
|
+
|
|
135
|
+
// Neither → loading
|
|
136
|
+
expect(runtime.detectReady("Initializing...").phase).toBe("loading");
|
|
137
|
+
|
|
138
|
+
// Substring false-positive prevention: "amp" inside other words must NOT match branding
|
|
139
|
+
expect(runtime.detectReady("this is an example output\n> ").phase).toBe("loading");
|
|
140
|
+
expect(runtime.detectReady("stamped result\n> ").phase).toBe("loading");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("does not require beacon verification", () => {
|
|
144
|
+
expect(runtime.requiresBeaconVerification()).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("parseTranscript returns null", async () => {
|
|
148
|
+
expect(await runtime.parseTranscript("/nonexistent")).toBeNull();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("buildEnv returns model env vars", () => {
|
|
152
|
+
expect(runtime.buildEnv({ model: "sonnet", env: { SRC_ACCESS_TOKEN: "token" } })).toEqual({
|
|
153
|
+
SRC_ACCESS_TOKEN: "token",
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("buildEnv returns empty object when no env", () => {
|
|
158
|
+
expect(runtime.buildEnv({ model: "sonnet" })).toEqual({});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("getTranscriptDir returns null", () => {
|
|
162
|
+
expect(runtime.getTranscriptDir("/tmp/project")).toBeNull();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Amp runtime adapter for agentplate's AgentRuntime interface.
|
|
2
|
+
// Implements the AgentRuntime contract for Sourcegraph's `amp` CLI (AI coding agent).
|
|
3
|
+
//
|
|
4
|
+
// Key differences from Claude/Pi adapters:
|
|
5
|
+
// - Interactive: `amp` runs as an interactive chat session in tmux
|
|
6
|
+
// - Instruction file: .amp/AGENT.md (Amp's native instruction file)
|
|
7
|
+
// - No hooks: Amp manages permissions via its own approval system
|
|
8
|
+
// - One-shot calls use `amp --prompt <prompt> --no-input`
|
|
9
|
+
// - Model is passed via `--model <model>`
|
|
10
|
+
|
|
11
|
+
import { mkdir } from "node:fs/promises";
|
|
12
|
+
import { dirname, join } from "node:path";
|
|
13
|
+
import type { ResolvedModel } from "../types.ts";
|
|
14
|
+
import type {
|
|
15
|
+
AgentRuntime,
|
|
16
|
+
HooksDef,
|
|
17
|
+
OverlayContent,
|
|
18
|
+
ReadyState,
|
|
19
|
+
SpawnOpts,
|
|
20
|
+
TranscriptSummary,
|
|
21
|
+
} from "./types.ts";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Amp runtime adapter.
|
|
25
|
+
*
|
|
26
|
+
* Implements AgentRuntime for Sourcegraph's `amp` CLI. Amp agents run
|
|
27
|
+
* as interactive chat sessions with configurable models and tools.
|
|
28
|
+
*
|
|
29
|
+
* Security is managed by Amp's built-in approval system for file
|
|
30
|
+
* modifications and command execution.
|
|
31
|
+
*/
|
|
32
|
+
export class AmpRuntime implements AgentRuntime {
|
|
33
|
+
readonly id = "amp";
|
|
34
|
+
|
|
35
|
+
/** Experimental — community-contributed adapter, not yet battle-tested in production. */
|
|
36
|
+
readonly stability = "experimental" as const;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Amp reads .amp/AGENT.md from the repo for project-level instructions.
|
|
40
|
+
*/
|
|
41
|
+
readonly instructionPath = ".amp/AGENT.md";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Build the shell command string to spawn an Amp agent in a tmux pane.
|
|
45
|
+
*
|
|
46
|
+
* Uses `amp` in interactive mode with `--model` for model selection
|
|
47
|
+
* and `--yes` for automatic approval.
|
|
48
|
+
*
|
|
49
|
+
* @param opts - Spawn options
|
|
50
|
+
* @returns Shell command string suitable for tmux new-session
|
|
51
|
+
*/
|
|
52
|
+
buildSpawnCommand(opts: SpawnOpts): string {
|
|
53
|
+
let cmd = `amp --model ${opts.model} --yes`;
|
|
54
|
+
|
|
55
|
+
if (opts.appendSystemPromptFile) {
|
|
56
|
+
const escaped = opts.appendSystemPromptFile.replace(/'/g, "'\\''");
|
|
57
|
+
cmd += ` --prompt "$(cat '${escaped}') Read .amp/AGENT.md for your task assignment."`;
|
|
58
|
+
} else if (opts.appendSystemPrompt) {
|
|
59
|
+
const escaped =
|
|
60
|
+
`${opts.appendSystemPrompt}\n\nRead .amp/AGENT.md for your task assignment and begin.`.replace(
|
|
61
|
+
/'/g,
|
|
62
|
+
"'\\''",
|
|
63
|
+
);
|
|
64
|
+
cmd += ` --prompt '${escaped}'`;
|
|
65
|
+
} else {
|
|
66
|
+
cmd += ` --prompt 'Read .amp/AGENT.md for your task assignment and begin immediately.'`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return cmd;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Build argv for a headless one-shot Amp invocation.
|
|
74
|
+
*
|
|
75
|
+
* Uses `amp --prompt <prompt> --no-input --yes` for non-interactive execution.
|
|
76
|
+
*
|
|
77
|
+
* @param prompt - The prompt to pass
|
|
78
|
+
* @param model - Optional model override
|
|
79
|
+
* @returns Argv array for Bun.spawn
|
|
80
|
+
*/
|
|
81
|
+
buildPrintCommand(prompt: string, model?: string): string[] {
|
|
82
|
+
const cmd = ["amp", "--prompt", prompt, "--no-input", "--yes"];
|
|
83
|
+
if (model !== undefined) {
|
|
84
|
+
cmd.push("--model", model);
|
|
85
|
+
}
|
|
86
|
+
return cmd;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Deploy per-agent instructions to a worktree.
|
|
91
|
+
*
|
|
92
|
+
* Writes the overlay to .amp/AGENT.md (Amp's native instruction file).
|
|
93
|
+
* No hooks — Amp manages approvals internally.
|
|
94
|
+
*
|
|
95
|
+
* @param worktreePath - Absolute path to the agent's git worktree
|
|
96
|
+
* @param overlay - Overlay content, or undefined for no-op
|
|
97
|
+
* @param _hooks - Unused — Amp has no hook system
|
|
98
|
+
*/
|
|
99
|
+
async deployConfig(
|
|
100
|
+
worktreePath: string,
|
|
101
|
+
overlay: OverlayContent | undefined,
|
|
102
|
+
_hooks: HooksDef,
|
|
103
|
+
): Promise<void> {
|
|
104
|
+
if (!overlay) return;
|
|
105
|
+
const agentPath = join(worktreePath, this.instructionPath);
|
|
106
|
+
await mkdir(dirname(agentPath), { recursive: true });
|
|
107
|
+
await Bun.write(agentPath, overlay.content);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Detect Amp TUI readiness from tmux pane content.
|
|
112
|
+
*
|
|
113
|
+
* Amp shows a prompt indicator when ready for input.
|
|
114
|
+
*
|
|
115
|
+
* @param paneContent - Captured tmux pane content
|
|
116
|
+
* @returns Readiness phase
|
|
117
|
+
*/
|
|
118
|
+
detectReady(paneContent: string): ReadyState {
|
|
119
|
+
const lower = paneContent.toLowerCase();
|
|
120
|
+
|
|
121
|
+
// Prompt indicator: ">" or "amp>" at end of a line
|
|
122
|
+
const hasPrompt = /(?:amp)?>\s*$/.test(paneContent);
|
|
123
|
+
|
|
124
|
+
// Branding indicator: "amp" as a standalone word (word boundary prevents
|
|
125
|
+
// matching inside "example", "stamp", "&", etc.)
|
|
126
|
+
const hasBranding = /\bamp\b/.test(lower);
|
|
127
|
+
|
|
128
|
+
// Both required (AND logic) to prevent premature ready detection
|
|
129
|
+
// during startup messages like "amp v1.2.3 starting..."
|
|
130
|
+
if (hasPrompt && hasBranding) {
|
|
131
|
+
return { phase: "ready" };
|
|
132
|
+
}
|
|
133
|
+
return { phase: "loading" };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Amp does not require beacon verification. */
|
|
137
|
+
requiresBeaconVerification(): boolean {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Amp does not produce machine-readable transcripts. */
|
|
142
|
+
async parseTranscript(_path: string): Promise<TranscriptSummary | null> {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
buildEnv(model: ResolvedModel): Record<string, string> {
|
|
147
|
+
return model.env ?? {};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Amp does not expose a transcript directory. */
|
|
151
|
+
getTranscriptDir(_projectRoot: string): string | null {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|