@proletariat/cli 0.2.0 → 0.3.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/README.md +512 -253
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +5 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +23 -0
- package/dist/commands/action/create.d.ts +21 -0
- package/dist/commands/action/create.js +126 -0
- package/dist/commands/action/delete.d.ts +17 -0
- package/dist/commands/action/delete.js +78 -0
- package/dist/commands/action/index.d.ts +15 -0
- package/dist/commands/action/index.js +107 -0
- package/dist/commands/action/list.d.ts +14 -0
- package/dist/commands/action/list.js +89 -0
- package/dist/commands/action/run.d.ts +19 -0
- package/dist/commands/action/run.js +179 -0
- package/dist/commands/action/show.d.ts +15 -0
- package/dist/commands/action/show.js +47 -0
- package/dist/commands/action/update.d.ts +22 -0
- package/dist/commands/action/update.js +168 -0
- package/dist/commands/agent/index.d.ts +13 -0
- package/dist/commands/agent/index.js +131 -0
- package/dist/commands/agent/list.d.ts +7 -0
- package/dist/commands/agent/list.js +126 -0
- package/dist/commands/agent/login.d.ts +16 -0
- package/dist/commands/agent/login.js +146 -0
- package/dist/commands/agent/rebuild.d.ts +18 -0
- package/dist/commands/agent/rebuild.js +133 -0
- package/dist/commands/agent/restart.d.ts +17 -0
- package/dist/commands/agent/restart.js +116 -0
- package/dist/commands/agent/shell.d.ts +23 -0
- package/dist/commands/agent/shell.js +378 -0
- package/dist/commands/agent/staff/add.d.ts +15 -0
- package/dist/commands/agent/staff/add.js +281 -0
- package/dist/commands/agent/staff/index.d.ts +14 -0
- package/dist/commands/agent/staff/index.js +90 -0
- package/dist/commands/agent/staff/list.d.ts +7 -0
- package/dist/commands/agent/staff/list.js +90 -0
- package/dist/commands/agent/staff/remove.d.ts +16 -0
- package/dist/commands/agent/staff/remove.js +137 -0
- package/dist/commands/agent/status.d.ts +17 -0
- package/dist/commands/agent/status.js +139 -0
- package/dist/commands/agent/temp/cleanup.d.ts +23 -0
- package/dist/commands/agent/temp/cleanup.js +388 -0
- package/dist/commands/agent/temp/index.d.ts +14 -0
- package/dist/commands/agent/temp/index.js +82 -0
- package/dist/commands/agent/temp/list.d.ts +7 -0
- package/dist/commands/agent/temp/list.js +108 -0
- package/dist/commands/agent/themes/add-names.d.ts +10 -0
- package/dist/commands/agent/themes/add-names.js +67 -0
- package/dist/commands/agent/themes/create.d.ts +13 -0
- package/dist/commands/agent/themes/create.js +66 -0
- package/dist/commands/agent/themes/index.d.ts +9 -0
- package/dist/commands/agent/themes/index.js +194 -0
- package/dist/commands/agent/themes/list.d.ts +6 -0
- package/dist/commands/agent/themes/list.js +41 -0
- package/dist/commands/agent/themes/set.d.ts +12 -0
- package/dist/commands/agent/themes/set.js +77 -0
- package/dist/commands/agent/visit.d.ts +16 -0
- package/dist/commands/agent/visit.js +88 -0
- package/dist/commands/autocomplete/setup.d.ts +14 -0
- package/dist/commands/autocomplete/setup.js +154 -0
- package/dist/commands/board/index.d.ts +17 -0
- package/dist/commands/board/index.js +255 -0
- package/dist/commands/board/watch.d.ts +13 -0
- package/dist/commands/board/watch.js +52 -0
- package/dist/commands/branch/create.d.ts +50 -0
- package/dist/commands/branch/create.js +624 -0
- package/dist/commands/branch/index.d.ts +13 -0
- package/dist/commands/branch/index.js +50 -0
- package/dist/commands/branch/list.d.ts +17 -0
- package/dist/commands/branch/list.js +120 -0
- package/dist/commands/branch/validate.d.ts +15 -0
- package/dist/commands/branch/validate.js +73 -0
- package/dist/commands/commit.d.ts +71 -0
- package/dist/commands/commit.js +499 -0
- package/dist/commands/docker/clean.d.ts +13 -0
- package/dist/commands/docker/clean.js +224 -0
- package/dist/commands/docker/index.d.ts +19 -0
- package/dist/commands/docker/index.js +274 -0
- package/dist/commands/docker/list.d.ts +16 -0
- package/dist/commands/docker/list.js +200 -0
- package/dist/commands/docker/logs.d.ts +14 -0
- package/dist/commands/docker/logs.js +118 -0
- package/dist/commands/docker/prune.d.ts +14 -0
- package/dist/commands/docker/prune.js +211 -0
- package/dist/commands/docker/restart.d.ts +14 -0
- package/dist/commands/docker/restart.js +129 -0
- package/dist/commands/docker/shell.d.ts +14 -0
- package/dist/commands/docker/shell.js +103 -0
- package/dist/commands/docker/start.d.ts +12 -0
- package/dist/commands/docker/start.js +92 -0
- package/dist/commands/docker/status.d.ts +7 -0
- package/dist/commands/docker/status.js +40 -0
- package/dist/commands/docker/stop.d.ts +14 -0
- package/dist/commands/docker/stop.js +134 -0
- package/dist/commands/docker/sync.d.ts +15 -0
- package/dist/commands/docker/sync.js +112 -0
- package/dist/commands/epic/activate.d.ts +13 -0
- package/dist/commands/epic/activate.js +118 -0
- package/dist/commands/epic/archive.d.ts +14 -0
- package/dist/commands/epic/archive.js +132 -0
- package/dist/commands/epic/create.d.ts +15 -0
- package/dist/commands/epic/create.js +137 -0
- package/dist/commands/epic/index.d.ts +13 -0
- package/dist/commands/epic/index.js +88 -0
- package/dist/commands/epic/link/block.d.ts +14 -0
- package/dist/commands/epic/link/block.js +79 -0
- package/dist/commands/epic/link/duplicates.d.ts +14 -0
- package/dist/commands/epic/link/duplicates.js +66 -0
- package/dist/commands/epic/link/index.d.ts +19 -0
- package/dist/commands/epic/link/index.js +242 -0
- package/dist/commands/epic/link/relates.d.ts +14 -0
- package/dist/commands/epic/link/relates.js +66 -0
- package/dist/commands/epic/link/remove.d.ts +16 -0
- package/dist/commands/epic/link/remove.js +89 -0
- package/dist/commands/epic/list.d.ts +11 -0
- package/dist/commands/epic/list.js +87 -0
- package/dist/commands/epic/move.d.ts +15 -0
- package/dist/commands/epic/move.js +184 -0
- package/dist/commands/epic/progress.d.ts +16 -0
- package/dist/commands/epic/progress.js +166 -0
- package/dist/commands/epic/project.d.ts +15 -0
- package/dist/commands/epic/project.js +219 -0
- package/dist/commands/epic/reorder.d.ts +21 -0
- package/dist/commands/epic/reorder.js +160 -0
- package/dist/commands/epic/spec.d.ts +15 -0
- package/dist/commands/epic/spec.js +191 -0
- package/dist/commands/epic/ticket.d.ts +18 -0
- package/dist/commands/epic/ticket.js +291 -0
- package/dist/commands/epic/view.d.ts +13 -0
- package/dist/commands/epic/view.js +117 -0
- package/dist/commands/execution/index.d.ts +13 -0
- package/dist/commands/execution/index.js +70 -0
- package/dist/commands/execution/list.d.ts +15 -0
- package/dist/commands/execution/list.js +144 -0
- package/dist/commands/execution/logs.d.ts +18 -0
- package/dist/commands/execution/logs.js +161 -0
- package/dist/commands/execution/stop.d.ts +22 -0
- package/dist/commands/execution/stop.js +248 -0
- package/dist/commands/gh/index.d.ts +9 -0
- package/dist/commands/gh/index.js +53 -0
- package/dist/commands/gh/login.d.ts +6 -0
- package/dist/commands/gh/login.js +57 -0
- package/dist/commands/gh/status.d.ts +6 -0
- package/dist/commands/gh/status.js +48 -0
- package/dist/commands/gh/token.d.ts +6 -0
- package/dist/commands/gh/token.js +59 -0
- package/dist/commands/init.d.ts +26 -0
- package/dist/commands/init.js +200 -0
- package/dist/commands/phase/create.d.ts +22 -0
- package/dist/commands/phase/create.js +123 -0
- package/dist/commands/phase/delete.d.ts +17 -0
- package/dist/commands/phase/delete.js +73 -0
- package/dist/commands/phase/list.d.ts +12 -0
- package/dist/commands/phase/list.js +76 -0
- package/dist/commands/phase/move.d.ts +17 -0
- package/dist/commands/phase/move.js +115 -0
- package/dist/commands/phase/template/apply.d.ts +17 -0
- package/dist/commands/phase/template/apply.js +106 -0
- package/dist/commands/phase/template/create.d.ts +16 -0
- package/dist/commands/phase/template/create.js +58 -0
- package/dist/commands/phase/template/delete.d.ts +17 -0
- package/dist/commands/phase/template/delete.js +98 -0
- package/dist/commands/phase/template/index.d.ts +15 -0
- package/dist/commands/phase/template/index.js +128 -0
- package/dist/commands/phase/template/list.d.ts +16 -0
- package/dist/commands/phase/template/list.js +95 -0
- package/dist/commands/phase/template/update.d.ts +17 -0
- package/dist/commands/phase/template/update.js +89 -0
- package/dist/commands/phase/update.d.ts +23 -0
- package/dist/commands/phase/update.js +174 -0
- package/dist/commands/pmo/init.d.ts +25 -0
- package/dist/commands/pmo/init.js +341 -0
- package/dist/commands/pr/create.d.ts +17 -0
- package/dist/commands/pr/create.js +242 -0
- package/dist/commands/pr/index.d.ts +9 -0
- package/dist/commands/pr/index.js +68 -0
- package/dist/commands/pr/link.d.ts +14 -0
- package/dist/commands/pr/link.js +212 -0
- package/dist/commands/pr/status.d.ts +12 -0
- package/dist/commands/pr/status.js +161 -0
- package/dist/commands/project/archive.d.ts +17 -0
- package/dist/commands/project/archive.js +83 -0
- package/dist/commands/project/create.d.ts +22 -0
- package/dist/commands/project/create.js +143 -0
- package/dist/commands/project/delete.d.ts +17 -0
- package/dist/commands/project/delete.js +128 -0
- package/dist/commands/project/index.d.ts +13 -0
- package/dist/commands/project/index.js +64 -0
- package/dist/commands/project/list.d.ts +14 -0
- package/dist/commands/project/list.js +96 -0
- package/dist/commands/project/spec.d.ts +18 -0
- package/dist/commands/project/spec.js +216 -0
- package/dist/commands/project/unarchive.d.ts +15 -0
- package/dist/commands/project/unarchive.js +35 -0
- package/dist/commands/project/view.d.ts +16 -0
- package/dist/commands/project/view.js +94 -0
- package/dist/commands/repo/add.d.ts +21 -0
- package/dist/commands/repo/add.js +118 -0
- package/dist/commands/repo/index.d.ts +13 -0
- package/dist/commands/repo/index.js +114 -0
- package/dist/commands/repo/list.d.ts +13 -0
- package/dist/commands/repo/list.js +96 -0
- package/dist/commands/repo/remove.d.ts +23 -0
- package/dist/commands/repo/remove.js +217 -0
- package/dist/commands/repo/view.d.ts +15 -0
- package/dist/commands/repo/view.js +99 -0
- package/dist/commands/session/attach.d.ts +40 -0
- package/dist/commands/session/attach.js +307 -0
- package/dist/commands/session/index.d.ts +13 -0
- package/dist/commands/session/index.js +64 -0
- package/dist/commands/session/list.d.ts +21 -0
- package/dist/commands/session/list.js +181 -0
- package/dist/commands/spec/create.d.ts +19 -0
- package/dist/commands/spec/create.js +130 -0
- package/dist/commands/spec/index.d.ts +13 -0
- package/dist/commands/spec/index.js +68 -0
- package/dist/commands/spec/link/depends.d.ts +14 -0
- package/dist/commands/spec/link/depends.js +64 -0
- package/dist/commands/spec/link/duplicates.d.ts +14 -0
- package/dist/commands/spec/link/duplicates.js +63 -0
- package/dist/commands/spec/link/index.d.ts +19 -0
- package/dist/commands/spec/link/index.js +200 -0
- package/dist/commands/spec/link/relates.d.ts +14 -0
- package/dist/commands/spec/link/relates.js +63 -0
- package/dist/commands/spec/link/remove.d.ts +16 -0
- package/dist/commands/spec/link/remove.js +94 -0
- package/dist/commands/spec/list.d.ts +12 -0
- package/dist/commands/spec/list.js +75 -0
- package/dist/commands/spec/plan.d.ts +15 -0
- package/dist/commands/spec/plan.js +108 -0
- package/dist/commands/spec/ticket.d.ts +18 -0
- package/dist/commands/spec/ticket.js +160 -0
- package/dist/commands/spec/view.d.ts +15 -0
- package/dist/commands/spec/view.js +163 -0
- package/dist/commands/status/create.d.ts +21 -0
- package/dist/commands/status/create.js +140 -0
- package/dist/commands/status/delete.d.ts +13 -0
- package/dist/commands/status/delete.js +77 -0
- package/dist/commands/status/index.d.ts +14 -0
- package/dist/commands/status/index.js +91 -0
- package/dist/commands/status/list.d.ts +12 -0
- package/dist/commands/status/list.js +93 -0
- package/dist/commands/status/move.d.ts +14 -0
- package/dist/commands/status/move.js +120 -0
- package/dist/commands/status/update.d.ts +20 -0
- package/dist/commands/status/update.js +180 -0
- package/dist/commands/template/delete.d.ts +15 -0
- package/dist/commands/template/delete.js +142 -0
- package/dist/commands/template/index.d.ts +10 -0
- package/dist/commands/template/index.js +64 -0
- package/dist/commands/template/list.d.ts +18 -0
- package/dist/commands/template/list.js +157 -0
- package/dist/commands/template/phase/apply.d.ts +14 -0
- package/dist/commands/template/phase/apply.js +41 -0
- package/dist/commands/template/phase/create.d.ts +12 -0
- package/dist/commands/template/phase/create.js +29 -0
- package/dist/commands/template/phase/delete.d.ts +13 -0
- package/dist/commands/template/phase/delete.js +34 -0
- package/dist/commands/template/phase/index.d.ts +10 -0
- package/dist/commands/template/phase/index.js +62 -0
- package/dist/commands/template/phase/list.d.ts +11 -0
- package/dist/commands/template/phase/list.js +34 -0
- package/dist/commands/template/phase/update.d.ts +13 -0
- package/dist/commands/template/phase/update.js +35 -0
- package/dist/commands/template/ticket/apply.d.ts +17 -0
- package/dist/commands/template/ticket/apply.js +58 -0
- package/dist/commands/template/ticket/delete.d.ts +13 -0
- package/dist/commands/template/ticket/delete.js +34 -0
- package/dist/commands/template/ticket/index.d.ts +10 -0
- package/dist/commands/template/ticket/index.js +62 -0
- package/dist/commands/template/ticket/list.d.ts +11 -0
- package/dist/commands/template/ticket/list.js +34 -0
- package/dist/commands/template/ticket/save.d.ts +13 -0
- package/dist/commands/template/ticket/save.js +35 -0
- package/dist/commands/ticket/bulk.d.ts +13 -0
- package/dist/commands/ticket/bulk.js +145 -0
- package/dist/commands/ticket/complete.d.ts +16 -0
- package/dist/commands/ticket/complete.js +170 -0
- package/dist/commands/ticket/create.d.ts +22 -0
- package/dist/commands/ticket/create.js +390 -0
- package/dist/commands/ticket/delete.d.ts +16 -0
- package/dist/commands/ticket/delete.js +178 -0
- package/dist/commands/ticket/edit.d.ts +27 -0
- package/dist/commands/ticket/edit.js +322 -0
- package/dist/commands/ticket/epic.d.ts +20 -0
- package/dist/commands/ticket/epic.js +333 -0
- package/dist/commands/ticket/index.d.ts +13 -0
- package/dist/commands/ticket/index.js +103 -0
- package/dist/commands/ticket/link/block.d.ts +14 -0
- package/dist/commands/ticket/link/block.js +94 -0
- package/dist/commands/ticket/link/duplicates.d.ts +14 -0
- package/dist/commands/ticket/link/duplicates.js +93 -0
- package/dist/commands/ticket/link/index.d.ts +19 -0
- package/dist/commands/ticket/link/index.js +239 -0
- package/dist/commands/ticket/link/relates.d.ts +14 -0
- package/dist/commands/ticket/link/relates.js +93 -0
- package/dist/commands/ticket/link/remove.d.ts +16 -0
- package/dist/commands/ticket/link/remove.js +128 -0
- package/dist/commands/ticket/list.d.ts +24 -0
- package/dist/commands/ticket/list.js +431 -0
- package/dist/commands/ticket/move.d.ts +18 -0
- package/dist/commands/ticket/move.js +212 -0
- package/dist/commands/ticket/project.d.ts +18 -0
- package/dist/commands/ticket/project.js +254 -0
- package/dist/commands/ticket/reassign.d.ts +19 -0
- package/dist/commands/ticket/reassign.js +279 -0
- package/dist/commands/ticket/spec.d.ts +18 -0
- package/dist/commands/ticket/spec.js +259 -0
- package/dist/commands/ticket/status.d.ts +13 -0
- package/dist/commands/ticket/status.js +87 -0
- package/dist/commands/ticket/template/apply.d.ts +25 -0
- package/dist/commands/ticket/template/apply.js +249 -0
- package/dist/commands/ticket/template/create.d.ts +19 -0
- package/dist/commands/ticket/template/create.js +210 -0
- package/dist/commands/ticket/template/delete.d.ts +17 -0
- package/dist/commands/ticket/template/delete.js +92 -0
- package/dist/commands/ticket/template/index.d.ts +15 -0
- package/dist/commands/ticket/template/index.js +118 -0
- package/dist/commands/ticket/template/list.d.ts +16 -0
- package/dist/commands/ticket/template/list.js +110 -0
- package/dist/commands/ticket/template/save.d.ts +14 -0
- package/dist/commands/ticket/template/save.js +110 -0
- package/dist/commands/ticket/update.d.ts +18 -0
- package/dist/commands/ticket/update.js +325 -0
- package/dist/commands/ticket/view.d.ts +13 -0
- package/dist/commands/ticket/view.js +80 -0
- package/dist/commands/whoami.d.ts +9 -0
- package/dist/commands/whoami.js +103 -0
- package/dist/commands/work/complete.d.ts +13 -0
- package/dist/commands/work/complete.js +121 -0
- package/dist/commands/work/index.d.ts +13 -0
- package/dist/commands/work/index.js +70 -0
- package/dist/commands/work/ready.d.ts +24 -0
- package/dist/commands/work/ready.js +290 -0
- package/dist/commands/work/revise.d.ts +19 -0
- package/dist/commands/work/revise.js +377 -0
- package/dist/commands/work/spawn-all.d.ts +17 -0
- package/dist/commands/work/spawn-all.js +58 -0
- package/dist/commands/work/spawn.d.ts +29 -0
- package/dist/commands/work/spawn.js +728 -0
- package/dist/commands/work/start.d.ts +39 -0
- package/dist/commands/work/start.js +1393 -0
- package/dist/commands/work/watch.d.ts +31 -0
- package/dist/commands/work/watch.js +359 -0
- package/dist/commands/workflow/create.d.ts +18 -0
- package/dist/commands/workflow/create.js +119 -0
- package/dist/commands/workflow/delete.d.ts +17 -0
- package/dist/commands/workflow/delete.js +119 -0
- package/dist/commands/workflow/index.d.ts +15 -0
- package/dist/commands/workflow/index.js +75 -0
- package/dist/commands/workflow/list.d.ts +15 -0
- package/dist/commands/workflow/list.js +75 -0
- package/dist/commands/workflow/switch.d.ts +13 -0
- package/dist/commands/workflow/switch.js +117 -0
- package/dist/commands/workflow/view.d.ts +16 -0
- package/dist/commands/workflow/view.js +114 -0
- package/dist/commands/workspace/add.d.ts +12 -0
- package/dist/commands/workspace/add.js +74 -0
- package/dist/commands/workspace/list.d.ts +9 -0
- package/dist/commands/workspace/list.js +153 -0
- package/dist/commands/workspace/remove.d.ts +13 -0
- package/dist/commands/workspace/remove.js +98 -0
- package/dist/commands/workspace/use.d.ts +12 -0
- package/dist/commands/workspace/use.js +111 -0
- package/dist/hooks/init.d.ts +11 -0
- package/dist/hooks/init.js +57 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/agents/commands.d.ts +189 -0
- package/dist/lib/agents/commands.js +893 -0
- package/dist/lib/agents/index.d.ts +54 -0
- package/dist/lib/agents/index.js +382 -0
- package/dist/lib/branch/index.d.ts +120 -0
- package/dist/lib/branch/index.js +334 -0
- package/dist/lib/colors.d.ts +94 -0
- package/dist/lib/colors.js +68 -0
- package/dist/lib/commands/docker-command.d.ts +21 -0
- package/dist/lib/commands/docker-command.js +27 -0
- package/dist/lib/database/index.d.ts +176 -0
- package/dist/lib/database/index.js +581 -0
- package/dist/lib/docker/resolve.d.ts +38 -0
- package/dist/lib/docker/resolve.js +175 -0
- package/dist/lib/execution/config.d.ts +150 -0
- package/dist/lib/execution/config.js +541 -0
- package/dist/lib/execution/devcontainer.d.ts +85 -0
- package/dist/lib/execution/devcontainer.js +594 -0
- package/dist/lib/execution/index.d.ts +10 -0
- package/dist/lib/execution/index.js +10 -0
- package/dist/lib/execution/runners.d.ts +53 -0
- package/dist/lib/execution/runners.js +1182 -0
- package/dist/lib/execution/spawner.d.ts +85 -0
- package/dist/lib/execution/spawner.js +548 -0
- package/dist/lib/execution/storage.d.ts +159 -0
- package/dist/lib/execution/storage.js +425 -0
- package/dist/lib/execution/types.d.ts +145 -0
- package/dist/lib/execution/types.js +157 -0
- package/dist/lib/init/index.d.ts +75 -0
- package/dist/lib/init/index.js +355 -0
- package/dist/lib/machine-config.d.ts +170 -0
- package/dist/lib/machine-config.js +386 -0
- package/dist/lib/pmo/base-command.d.ts +195 -0
- package/dist/lib/pmo/base-command.js +319 -0
- package/dist/lib/pmo/create-spec-folders.d.ts +43 -0
- package/dist/lib/pmo/create-spec-folders.js +64 -0
- package/dist/lib/pmo/epic-files.d.ts +56 -0
- package/dist/lib/pmo/epic-files.js +195 -0
- package/dist/lib/pmo/find-pmo.d.ts +14 -0
- package/dist/lib/pmo/find-pmo.js +172 -0
- package/dist/lib/pmo/index.d.ts +109 -0
- package/dist/lib/pmo/index.js +501 -0
- package/dist/lib/pmo/markdown.d.ts +31 -0
- package/dist/lib/pmo/markdown.js +245 -0
- package/dist/lib/pmo/pmo-context.d.ts +27 -0
- package/dist/lib/pmo/pmo-context.js +44 -0
- package/dist/lib/pmo/schema.d.ts +82 -0
- package/dist/lib/pmo/schema.js +531 -0
- package/dist/lib/pmo/spec-parser.d.ts +25 -0
- package/dist/lib/pmo/spec-parser.js +205 -0
- package/dist/lib/pmo/spec-types.d.ts +43 -0
- package/dist/lib/pmo/spec-types.js +7 -0
- package/dist/lib/pmo/storage/actions.d.ts +34 -0
- package/dist/lib/pmo/storage/actions.js +177 -0
- package/dist/lib/pmo/storage/base.d.ts +47 -0
- package/dist/lib/pmo/storage/base.js +858 -0
- package/dist/lib/pmo/storage/dependencies.d.ts +61 -0
- package/dist/lib/pmo/storage/dependencies.js +267 -0
- package/dist/lib/pmo/storage/epics.d.ts +46 -0
- package/dist/lib/pmo/storage/epics.js +243 -0
- package/dist/lib/pmo/storage/helpers.d.ts +33 -0
- package/dist/lib/pmo/storage/helpers.js +148 -0
- package/dist/lib/pmo/storage/index.d.ts +186 -0
- package/dist/lib/pmo/storage/index.js +689 -0
- package/dist/lib/pmo/storage/phases.d.ts +65 -0
- package/dist/lib/pmo/storage/phases.js +392 -0
- package/dist/lib/pmo/storage/projects.d.ts +79 -0
- package/dist/lib/pmo/storage/projects.js +303 -0
- package/dist/lib/pmo/storage/specs.d.ts +77 -0
- package/dist/lib/pmo/storage/specs.js +389 -0
- package/dist/lib/pmo/storage/statuses.d.ts +63 -0
- package/dist/lib/pmo/storage/statuses.js +404 -0
- package/dist/lib/pmo/storage/subtasks.d.ts +37 -0
- package/dist/lib/pmo/storage/subtasks.js +184 -0
- package/dist/lib/pmo/storage/templates.d.ts +40 -0
- package/dist/lib/pmo/storage/templates.js +210 -0
- package/dist/lib/pmo/storage/tickets.d.ts +57 -0
- package/dist/lib/pmo/storage/tickets.js +453 -0
- package/dist/lib/pmo/storage/types.d.ts +200 -0
- package/dist/lib/pmo/storage/types.js +5 -0
- package/dist/lib/pmo/storage/views.d.ts +44 -0
- package/dist/lib/pmo/storage/views.js +355 -0
- package/dist/lib/pmo/storage-sqlite.d.ts +7 -0
- package/dist/lib/pmo/storage-sqlite.js +7 -0
- package/dist/lib/pmo/sync-manager.d.ts +92 -0
- package/dist/lib/pmo/sync-manager.js +229 -0
- package/dist/lib/pmo/types.d.ts +710 -0
- package/dist/lib/pmo/types.js +108 -0
- package/dist/lib/pmo/utils.d.ts +122 -0
- package/dist/lib/pmo/utils.js +174 -0
- package/dist/lib/pmo/watcher.d.ts +43 -0
- package/dist/lib/pmo/watcher.js +208 -0
- package/dist/lib/pr/index.d.ts +150 -0
- package/dist/lib/pr/index.js +483 -0
- package/dist/lib/prompt-json.d.ts +231 -0
- package/dist/lib/prompt-json.js +213 -0
- package/dist/lib/repos/index.d.ts +81 -0
- package/dist/lib/repos/index.js +679 -0
- package/dist/lib/styles.d.ts +98 -0
- package/dist/lib/styles.js +195 -0
- package/dist/lib/themes.d.ts +128 -0
- package/dist/lib/themes.js +301 -0
- package/dist/lib/ui/BoardUI.d.ts +21 -0
- package/dist/lib/ui/BoardUI.js +85 -0
- package/dist/lib/ui/ClaimTicketUI.d.ts +17 -0
- package/dist/lib/ui/ClaimTicketUI.js +64 -0
- package/dist/lib/ui/CreateTicketUI.d.ts +13 -0
- package/dist/lib/ui/CreateTicketUI.js +101 -0
- package/dist/lib/workspace.d.ts +66 -0
- package/dist/lib/workspace.js +204 -0
- package/oclif.manifest.json +10593 -0
- package/package.json +103 -56
- package/LICENSE +0 -21
- package/dist/bin/prlt.d.ts +0 -11
- package/dist/bin/prlt.d.ts.map +0 -1
- package/dist/bin/prlt.js +0 -144
- package/dist/bin/prlt.js.map +0 -1
- package/dist/lib/config/index.d.ts +0 -14
- package/dist/lib/config/index.d.ts.map +0 -1
- package/dist/lib/config/index.js +0 -142
- package/dist/lib/config/index.js.map +0 -1
- package/dist/lib/config/upgrade.d.ts +0 -2
- package/dist/lib/config/upgrade.d.ts.map +0 -1
- package/dist/lib/config/upgrade.js +0 -248
- package/dist/lib/config/upgrade.js.map +0 -1
- package/dist/lib/themes/index.d.ts +0 -8
- package/dist/lib/themes/index.d.ts.map +0 -1
- package/dist/lib/themes/index.js +0 -80
- package/dist/lib/themes/index.js.map +0 -1
- package/dist/lib/utils/helpers.d.ts +0 -4
- package/dist/lib/utils/helpers.d.ts.map +0 -1
- package/dist/lib/utils/helpers.js +0 -39
- package/dist/lib/utils/helpers.js.map +0 -1
- package/dist/lib/utils/logger.d.ts +0 -4
- package/dist/lib/utils/logger.d.ts.map +0 -1
- package/dist/lib/utils/logger.js +0 -28
- package/dist/lib/utils/logger.js.map +0 -1
- package/dist/lib/workspace/index.d.ts +0 -13
- package/dist/lib/workspace/index.d.ts.map +0 -1
- package/dist/lib/workspace/index.js +0 -116
- package/dist/lib/workspace/index.js.map +0 -1
- package/dist/lib/worktree/index.d.ts +0 -7
- package/dist/lib/worktree/index.d.ts.map +0 -1
- package/dist/lib/worktree/index.js +0 -362
- package/dist/lib/worktree/index.js.map +0 -1
- package/dist/lib/worktree/migrate.d.ts +0 -2
- package/dist/lib/worktree/migrate.d.ts.map +0 -1
- package/dist/lib/worktree/migrate.js +0 -214
- package/dist/lib/worktree/migrate.js.map +0 -1
- package/dist/lib/worktree/repair.d.ts +0 -3
- package/dist/lib/worktree/repair.d.ts.map +0 -1
- package/dist/lib/worktree/repair.js +0 -320
- package/dist/lib/worktree/repair.js.map +0 -1
- package/dist/types/index.d.ts +0 -57
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Spawner
|
|
3
|
+
*
|
|
4
|
+
* Shared logic for spawning agent executions.
|
|
5
|
+
* Used by `work start`, `work spawn`, and `work watch` commands.
|
|
6
|
+
*/
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import { SQLiteStorage } from '../pmo/storage-sqlite.js';
|
|
9
|
+
import { WorkspaceInfo } from '../agents/commands.js';
|
|
10
|
+
import { ExecutionStorage } from './storage.js';
|
|
11
|
+
import { isDockerRunning } from './runners.js';
|
|
12
|
+
import { DisplayMode, SessionManager, ExecutorType, ExecutionEnvironment, ExecutionConfig } from './types.js';
|
|
13
|
+
import { Ticket } from '../pmo/types.js';
|
|
14
|
+
export type AgentStrategy = 'round-robin' | 'least-busy' | 'random';
|
|
15
|
+
export interface SpawnOptions {
|
|
16
|
+
/** Environment to run in */
|
|
17
|
+
environment?: ExecutionEnvironment;
|
|
18
|
+
/** Display mode for output */
|
|
19
|
+
displayMode?: DisplayMode;
|
|
20
|
+
/** Session manager for container environments (tmux runs inside container) */
|
|
21
|
+
sessionManager?: SessionManager;
|
|
22
|
+
/** Executor to use */
|
|
23
|
+
executor?: ExecutorType;
|
|
24
|
+
/** Skip permission prompts (danger mode) */
|
|
25
|
+
skipPermissions?: boolean;
|
|
26
|
+
/** Explicitly allow running on host (bypasses sandbox) */
|
|
27
|
+
runOnHost?: boolean;
|
|
28
|
+
/** Create PR when work is ready */
|
|
29
|
+
createPR?: boolean;
|
|
30
|
+
/** Execution config (terminal app, shell, etc.) */
|
|
31
|
+
executionConfig?: ExecutionConfig;
|
|
32
|
+
/** Logging callback */
|
|
33
|
+
log?: (msg: string) => void;
|
|
34
|
+
}
|
|
35
|
+
export interface SpawnResult {
|
|
36
|
+
success: boolean;
|
|
37
|
+
executionId?: string;
|
|
38
|
+
ticketId?: string;
|
|
39
|
+
agentName?: string;
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface BatchSpawnResult {
|
|
43
|
+
spawned: SpawnResult[];
|
|
44
|
+
skipped: Array<{
|
|
45
|
+
ticketId: string;
|
|
46
|
+
reason: string;
|
|
47
|
+
}>;
|
|
48
|
+
failed: SpawnResult[];
|
|
49
|
+
}
|
|
50
|
+
interface AgentWithExecutionCount {
|
|
51
|
+
name: string;
|
|
52
|
+
runningCount: number;
|
|
53
|
+
totalCount: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get all agents with their execution counts.
|
|
57
|
+
*/
|
|
58
|
+
export declare function getAgentsWithCounts(workspaceInfo: WorkspaceInfo, executionStorage: ExecutionStorage): AgentWithExecutionCount[];
|
|
59
|
+
/**
|
|
60
|
+
* Get agents that are not currently running any executions.
|
|
61
|
+
*/
|
|
62
|
+
export declare function getAvailableAgents(workspaceInfo: WorkspaceInfo, executionStorage: ExecutionStorage): string[];
|
|
63
|
+
/**
|
|
64
|
+
* Select an agent using the specified strategy.
|
|
65
|
+
*/
|
|
66
|
+
export declare function selectAgent(strategy: AgentStrategy, availableAgents: string[], executionStorage: ExecutionStorage, roundRobinState?: {
|
|
67
|
+
lastIndex: number;
|
|
68
|
+
}): string | null;
|
|
69
|
+
/**
|
|
70
|
+
* Spawn an agent to work on a ticket.
|
|
71
|
+
* This is the core spawning logic extracted from `work start`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function spawnAgentForTicket(ticket: Ticket, agentName: string, storage: SQLiteStorage, executionStorage: ExecutionStorage, workspaceInfo: WorkspaceInfo, db: Database.Database, pmoPath: string, options?: SpawnOptions): Promise<SpawnResult>;
|
|
74
|
+
/**
|
|
75
|
+
* Spawn agents for all tickets in a column.
|
|
76
|
+
*/
|
|
77
|
+
export declare function spawnForColumn(projectId: string, columnName: string, storage: SQLiteStorage, executionStorage: ExecutionStorage, workspaceInfo: WorkspaceInfo, db: Database.Database, pmoPath: string, options?: {
|
|
78
|
+
strategy?: AgentStrategy;
|
|
79
|
+
specificAgent?: string;
|
|
80
|
+
limit?: number;
|
|
81
|
+
dryRun?: boolean;
|
|
82
|
+
ticketIds?: string[];
|
|
83
|
+
log?: (msg: string) => void;
|
|
84
|
+
} & SpawnOptions): Promise<BatchSpawnResult>;
|
|
85
|
+
export { isDockerRunning };
|
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Spawner
|
|
3
|
+
*
|
|
4
|
+
* Shared logic for spawning agent executions.
|
|
5
|
+
* Used by `work start`, `work spawn`, and `work watch` commands.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import { execSync } from 'node:child_process';
|
|
10
|
+
import { autoExportToBoard } from '../pmo/index.js';
|
|
11
|
+
import { getWorkColumnSetting, findColumnByName } from '../pmo/utils.js';
|
|
12
|
+
import { findHQRoot } from '../repos/index.js';
|
|
13
|
+
import { hasDevcontainerConfig } from './devcontainer.js';
|
|
14
|
+
import { loadExecutionConfig, getOrPromptCoderName } from './config.js';
|
|
15
|
+
import { runExecution, isDockerRunning } from './runners.js';
|
|
16
|
+
import { generateBranchName, DEFAULT_EXECUTION_CONFIG, } from './types.js';
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Git Utilities
|
|
19
|
+
// =============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Try to execute a git command, return true if successful
|
|
22
|
+
*/
|
|
23
|
+
function tryGitCommand(cmd, cwd) {
|
|
24
|
+
try {
|
|
25
|
+
execSync(cmd, { cwd, stdio: 'pipe' });
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check if a directory is a git repository
|
|
34
|
+
*/
|
|
35
|
+
function isGitRepo(dir) {
|
|
36
|
+
return tryGitCommand('git rev-parse --git-dir', dir);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Find the first existing branch from a list of candidates
|
|
40
|
+
*/
|
|
41
|
+
function findBaseBranch(repoPath, candidates = ['origin/main', 'origin/master']) {
|
|
42
|
+
for (const branch of candidates) {
|
|
43
|
+
if (tryGitCommand(`git rev-parse --verify ${branch}`, repoPath)) {
|
|
44
|
+
return branch;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return 'HEAD';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Try to execute a docker exec git command, return true if successful
|
|
51
|
+
*/
|
|
52
|
+
function tryDockerGitCommand(containerId, containerRepoPath, gitArgs) {
|
|
53
|
+
try {
|
|
54
|
+
execSync(`docker exec ${containerId} git -C "${containerRepoPath}" ${gitArgs}`, { stdio: 'pipe' });
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if a path is a git repo inside a container
|
|
63
|
+
*/
|
|
64
|
+
function isGitRepoInContainer(containerId, containerRepoPath) {
|
|
65
|
+
return tryDockerGitCommand(containerId, containerRepoPath, 'rev-parse --git-dir');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Find the base branch inside a container
|
|
69
|
+
*/
|
|
70
|
+
function findBaseBranchInContainer(containerId, containerRepoPath, candidates = ['origin/main', 'origin/master']) {
|
|
71
|
+
for (const branch of candidates) {
|
|
72
|
+
if (tryDockerGitCommand(containerId, containerRepoPath, `rev-parse --verify ${branch}`)) {
|
|
73
|
+
return branch;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return 'HEAD';
|
|
77
|
+
}
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// Agent Selection
|
|
80
|
+
// =============================================================================
|
|
81
|
+
/**
|
|
82
|
+
* Get all agents with their execution counts.
|
|
83
|
+
*/
|
|
84
|
+
export function getAgentsWithCounts(workspaceInfo, executionStorage) {
|
|
85
|
+
return workspaceInfo.agents.map(agent => {
|
|
86
|
+
const running = executionStorage.getAgentRunningExecutions(agent.name);
|
|
87
|
+
const total = executionStorage.getAgentExecutionCount(agent.name);
|
|
88
|
+
return {
|
|
89
|
+
name: agent.name,
|
|
90
|
+
runningCount: running.length,
|
|
91
|
+
totalCount: total,
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get agents that are not currently running any executions.
|
|
97
|
+
*/
|
|
98
|
+
export function getAvailableAgents(workspaceInfo, executionStorage) {
|
|
99
|
+
return workspaceInfo.agents
|
|
100
|
+
.filter(agent => executionStorage.isAgentAvailable(agent.name))
|
|
101
|
+
.map(agent => agent.name);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Select an agent using the specified strategy.
|
|
105
|
+
*/
|
|
106
|
+
export function selectAgent(strategy, availableAgents, executionStorage, roundRobinState) {
|
|
107
|
+
if (availableAgents.length === 0) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
switch (strategy) {
|
|
111
|
+
case 'round-robin': {
|
|
112
|
+
// Use round-robin state if provided, otherwise start from 0
|
|
113
|
+
const lastIndex = roundRobinState?.lastIndex ?? -1;
|
|
114
|
+
const nextIndex = (lastIndex + 1) % availableAgents.length;
|
|
115
|
+
if (roundRobinState) {
|
|
116
|
+
roundRobinState.lastIndex = nextIndex;
|
|
117
|
+
}
|
|
118
|
+
return availableAgents[nextIndex];
|
|
119
|
+
}
|
|
120
|
+
case 'least-busy': {
|
|
121
|
+
// Select agent with fewest total executions (historical)
|
|
122
|
+
let minCount = Infinity;
|
|
123
|
+
let selected = availableAgents[0];
|
|
124
|
+
for (const agentName of availableAgents) {
|
|
125
|
+
const count = executionStorage.getAgentExecutionCount(agentName);
|
|
126
|
+
if (count < minCount) {
|
|
127
|
+
minCount = count;
|
|
128
|
+
selected = agentName;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return selected;
|
|
132
|
+
}
|
|
133
|
+
case 'random': {
|
|
134
|
+
const randomIndex = Math.floor(Math.random() * availableAgents.length);
|
|
135
|
+
return availableAgents[randomIndex];
|
|
136
|
+
}
|
|
137
|
+
default:
|
|
138
|
+
return availableAgents[0];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// =============================================================================
|
|
142
|
+
// Spawning
|
|
143
|
+
// =============================================================================
|
|
144
|
+
/**
|
|
145
|
+
* Spawn an agent to work on a ticket.
|
|
146
|
+
* This is the core spawning logic extracted from `work start`.
|
|
147
|
+
*/
|
|
148
|
+
export async function spawnAgentForTicket(ticket, agentName, storage, executionStorage, workspaceInfo, db, pmoPath, options = {}) {
|
|
149
|
+
const log = options.log || (() => { });
|
|
150
|
+
const executor = options.executor || DEFAULT_EXECUTION_CONFIG.defaultExecutor;
|
|
151
|
+
// Determine agent directory and worktree path
|
|
152
|
+
const agentDir = path.join(workspaceInfo.agentsPath, agentName);
|
|
153
|
+
if (!fs.existsSync(agentDir)) {
|
|
154
|
+
return {
|
|
155
|
+
success: false,
|
|
156
|
+
ticketId: ticket.id,
|
|
157
|
+
agentName,
|
|
158
|
+
error: `Agent directory not found at ${agentDir}`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
// Find worktree path for agent
|
|
162
|
+
let worktreePath = agentDir;
|
|
163
|
+
const agentContents = fs.readdirSync(agentDir);
|
|
164
|
+
const repoWorktrees = agentContents.filter(item => {
|
|
165
|
+
const itemPath = path.join(agentDir, item);
|
|
166
|
+
const gitPath = path.join(itemPath, '.git');
|
|
167
|
+
return fs.statSync(itemPath).isDirectory() && fs.existsSync(gitPath);
|
|
168
|
+
});
|
|
169
|
+
if (repoWorktrees.length === 1) {
|
|
170
|
+
worktreePath = path.join(agentDir, repoWorktrees[0]);
|
|
171
|
+
}
|
|
172
|
+
else if (repoWorktrees.length > 1) {
|
|
173
|
+
worktreePath = agentDir;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// No git worktrees found - use current directory
|
|
177
|
+
worktreePath = process.cwd();
|
|
178
|
+
}
|
|
179
|
+
// Get coder name for branch naming (prompts on first use)
|
|
180
|
+
const coderName = await getOrPromptCoderName(db);
|
|
181
|
+
// Generate branch name
|
|
182
|
+
const branch = generateBranchName(ticket.id, ticket.title, coderName, agentName, ticket.category);
|
|
183
|
+
// Get epic info if linked
|
|
184
|
+
let epicTitle;
|
|
185
|
+
if (ticket.epicId) {
|
|
186
|
+
const epic = await storage.getEpic(ticket.epicId);
|
|
187
|
+
epicTitle = epic?.title;
|
|
188
|
+
}
|
|
189
|
+
// Get spec info if linked
|
|
190
|
+
let specId;
|
|
191
|
+
let specTitle;
|
|
192
|
+
let specProblem;
|
|
193
|
+
let specSolution;
|
|
194
|
+
if (ticket.specId) {
|
|
195
|
+
const spec = await storage.getSpec(ticket.specId);
|
|
196
|
+
if (spec) {
|
|
197
|
+
specId = spec.id;
|
|
198
|
+
specTitle = spec.title;
|
|
199
|
+
specProblem = spec.problem;
|
|
200
|
+
specSolution = spec.solution;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Build execution context
|
|
204
|
+
// Find proper HQ root (don't assume PMO is at {hq}/pmo - it could be at {hq}/repos/myrepo/pmo)
|
|
205
|
+
const hqPath = findHQRoot() || path.dirname(pmoPath);
|
|
206
|
+
const context = {
|
|
207
|
+
ticketId: ticket.id,
|
|
208
|
+
ticketTitle: ticket.title,
|
|
209
|
+
ticketDescription: ticket.description,
|
|
210
|
+
ticketSubtasks: ticket.subtasks?.map(s => ({ title: s.title, done: s.done })),
|
|
211
|
+
ticketPriority: ticket.priority,
|
|
212
|
+
ticketCategory: ticket.category,
|
|
213
|
+
epicTitle,
|
|
214
|
+
specId,
|
|
215
|
+
specTitle,
|
|
216
|
+
specProblem,
|
|
217
|
+
specSolution,
|
|
218
|
+
agentName,
|
|
219
|
+
agentDir,
|
|
220
|
+
worktreePath,
|
|
221
|
+
branch,
|
|
222
|
+
hqPath,
|
|
223
|
+
pmoPath,
|
|
224
|
+
createPR: options.createPR ?? false,
|
|
225
|
+
};
|
|
226
|
+
// Determine execution environment and display mode
|
|
227
|
+
const hasDevcontainer = hasDevcontainerConfig(agentDir);
|
|
228
|
+
const dockerRunning = isDockerRunning();
|
|
229
|
+
// Security check: If devcontainer exists but Docker isn't running,
|
|
230
|
+
// require explicit --run-on-host flag to proceed (TKT-046)
|
|
231
|
+
let environment;
|
|
232
|
+
if (options.environment) {
|
|
233
|
+
environment = options.environment;
|
|
234
|
+
}
|
|
235
|
+
else if (hasDevcontainer && dockerRunning) {
|
|
236
|
+
environment = 'devcontainer';
|
|
237
|
+
}
|
|
238
|
+
else if (hasDevcontainer && !dockerRunning) {
|
|
239
|
+
// Devcontainer exists but Docker isn't running
|
|
240
|
+
if (options.runOnHost) {
|
|
241
|
+
// User explicitly opted to run on host
|
|
242
|
+
environment = 'host';
|
|
243
|
+
log('⚠️ Running on host (--run-on-host flag set). Agent has full host access.');
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
// Security: Don't silently fall back to host
|
|
247
|
+
return {
|
|
248
|
+
success: false,
|
|
249
|
+
ticketId: ticket.id,
|
|
250
|
+
agentName,
|
|
251
|
+
error: 'Docker is not running but devcontainer is configured.\n\n' +
|
|
252
|
+
'For security, agents should run in Docker containers.\n' +
|
|
253
|
+
'Options:\n' +
|
|
254
|
+
' 1. Start Docker Desktop and try again\n' +
|
|
255
|
+
' 2. Use --run-on-host flag to run directly on your machine (bypasses sandbox)',
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
// No devcontainer configured, host is the only option
|
|
261
|
+
environment = 'host';
|
|
262
|
+
}
|
|
263
|
+
const displayMode = options.displayMode || 'terminal';
|
|
264
|
+
const sandboxed = !(options.skipPermissions ?? false);
|
|
265
|
+
// Create branch in worktree(s)
|
|
266
|
+
// For devcontainer environments, run git commands inside the container
|
|
267
|
+
// because the worktree .git file has container paths, not host paths
|
|
268
|
+
const gitRepos = repoWorktrees.length > 0
|
|
269
|
+
? repoWorktrees.map(r => path.join(agentDir, r))
|
|
270
|
+
: [worktreePath];
|
|
271
|
+
// Always fetch latest from origin before branch operations
|
|
272
|
+
// This ensures all spawn actions work with the latest code
|
|
273
|
+
for (const repoPath of gitRepos) {
|
|
274
|
+
if (isGitRepo(repoPath)) {
|
|
275
|
+
tryGitCommand('git fetch origin', repoPath);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (environment === 'devcontainer') {
|
|
279
|
+
// Get container ID for this agent
|
|
280
|
+
let containerId = null;
|
|
281
|
+
try {
|
|
282
|
+
containerId = execSync(`docker ps -q --filter "label=devcontainer.local_folder=${agentDir}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim() || null;
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
// Container not running
|
|
286
|
+
}
|
|
287
|
+
if (containerId) {
|
|
288
|
+
// Run git commands inside the container
|
|
289
|
+
for (const repoPath of gitRepos) {
|
|
290
|
+
const repoName = path.basename(repoPath);
|
|
291
|
+
// Map host path to container path: /workspace/{repoName}
|
|
292
|
+
const containerRepoPath = `/workspace/${repoName}`;
|
|
293
|
+
// Skip if not a git repo
|
|
294
|
+
if (!isGitRepoInContainer(containerId, containerRepoPath)) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
// Fetch latest from origin inside container (may fail if offline)
|
|
299
|
+
tryDockerGitCommand(containerId, containerRepoPath, 'fetch origin');
|
|
300
|
+
// Find base branch (origin/main or origin/master)
|
|
301
|
+
const baseBranch = findBaseBranchInContainer(containerId, containerRepoPath);
|
|
302
|
+
// Check if branch exists and checkout, or create new branch
|
|
303
|
+
const branchExists = tryDockerGitCommand(containerId, containerRepoPath, `rev-parse --verify ${branch}`);
|
|
304
|
+
if (branchExists) {
|
|
305
|
+
execSync(`docker exec ${containerId} git -C "${containerRepoPath}" checkout ${branch}`, { stdio: 'pipe' });
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
execSync(`docker exec ${containerId} git -C "${containerRepoPath}" checkout -b ${branch} ${baseBranch}`, { stdio: 'pipe' });
|
|
309
|
+
}
|
|
310
|
+
log(`Created branch ${branch} in ${repoName} from ${baseBranch} (inside container)`);
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
log(`Could not create branch in ${repoName}: ${error instanceof Error ? error.message : error}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
log('Container not running, will create branch when container starts');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
// Host environment - run git commands directly
|
|
323
|
+
for (const repoPath of gitRepos) {
|
|
324
|
+
// Skip if not a git repo
|
|
325
|
+
if (!isGitRepo(repoPath)) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
try {
|
|
329
|
+
// Find base branch (origin/main or origin/master)
|
|
330
|
+
const baseBranch = findBaseBranch(repoPath);
|
|
331
|
+
// Check if branch exists and checkout, or create new branch
|
|
332
|
+
const branchExists = tryGitCommand(`git rev-parse --verify ${branch}`, repoPath);
|
|
333
|
+
if (branchExists) {
|
|
334
|
+
execSync(`git checkout ${branch}`, { cwd: repoPath, stdio: 'pipe' });
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
execSync(`git checkout -b ${branch} ${baseBranch}`, { cwd: repoPath, stdio: 'pipe' });
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
log(`Could not create branch in ${path.basename(repoPath)}: ${error instanceof Error ? error.message : error}`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// Create execution record
|
|
346
|
+
const execution = executionStorage.createExecution({
|
|
347
|
+
ticketId: ticket.id,
|
|
348
|
+
agentName,
|
|
349
|
+
executor,
|
|
350
|
+
environment,
|
|
351
|
+
displayMode,
|
|
352
|
+
sandboxed,
|
|
353
|
+
branch,
|
|
354
|
+
});
|
|
355
|
+
// Load execution config (use passed config or load from db)
|
|
356
|
+
const executionConfig = options.executionConfig || loadExecutionConfig(db);
|
|
357
|
+
executionConfig.sandboxed = sandboxed;
|
|
358
|
+
// Use print mode for background, interactive for terminal/tmux
|
|
359
|
+
executionConfig.outputMode = displayMode === 'background' ? 'print' : 'interactive';
|
|
360
|
+
// Run execution
|
|
361
|
+
const sessionManager = options.sessionManager || 'direct';
|
|
362
|
+
const result = await runExecution(environment, context, executor, executionConfig, {
|
|
363
|
+
displayMode,
|
|
364
|
+
sessionManager: environment === 'devcontainer' ? sessionManager : undefined,
|
|
365
|
+
});
|
|
366
|
+
if (result.success) {
|
|
367
|
+
executionStorage.updateStatus(execution.id, 'running');
|
|
368
|
+
executionStorage.updateProcessInfo(execution.id, {
|
|
369
|
+
pid: result.pid,
|
|
370
|
+
containerId: result.containerId,
|
|
371
|
+
sessionId: result.sessionId,
|
|
372
|
+
logPath: result.logPath,
|
|
373
|
+
});
|
|
374
|
+
// Only update ticket status and move to In Progress after successful spawn
|
|
375
|
+
await storage.updateTicket(ticket.id, {
|
|
376
|
+
status: 'in_progress',
|
|
377
|
+
assignee: agentName,
|
|
378
|
+
});
|
|
379
|
+
const targetColumnName = getWorkColumnSetting(db, 'in_progress');
|
|
380
|
+
const board = await storage.getBoard(ticket.projectId);
|
|
381
|
+
const columnNames = board.columns.map(col => col.name);
|
|
382
|
+
const inProgressColumn = findColumnByName(columnNames, targetColumnName);
|
|
383
|
+
if (inProgressColumn && ticket.statusName !== inProgressColumn) {
|
|
384
|
+
await storage.moveTicket(ticket.projectId, ticket.id, inProgressColumn);
|
|
385
|
+
}
|
|
386
|
+
await autoExportToBoard(pmoPath, storage, log);
|
|
387
|
+
return {
|
|
388
|
+
success: true,
|
|
389
|
+
executionId: execution.id,
|
|
390
|
+
ticketId: ticket.id,
|
|
391
|
+
agentName,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
executionStorage.updateStatus(execution.id, 'failed');
|
|
396
|
+
return {
|
|
397
|
+
success: false,
|
|
398
|
+
executionId: execution.id,
|
|
399
|
+
ticketId: ticket.id,
|
|
400
|
+
agentName,
|
|
401
|
+
error: result.error,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Spawn agents for all tickets in a column.
|
|
407
|
+
*/
|
|
408
|
+
export async function spawnForColumn(projectId, columnName, storage, executionStorage, workspaceInfo, db, pmoPath, options = {}) {
|
|
409
|
+
const log = options.log || (() => { });
|
|
410
|
+
const strategy = options.strategy || 'round-robin';
|
|
411
|
+
const limit = options.limit || Infinity;
|
|
412
|
+
const result = {
|
|
413
|
+
spawned: [],
|
|
414
|
+
skipped: [],
|
|
415
|
+
failed: [],
|
|
416
|
+
};
|
|
417
|
+
// Get tickets in the specified column
|
|
418
|
+
let allTickets = await storage.listTickets(projectId, { column: columnName });
|
|
419
|
+
// If specific ticket IDs provided, filter to only those tickets
|
|
420
|
+
if (options.ticketIds && options.ticketIds.length > 0) {
|
|
421
|
+
allTickets = allTickets.filter(t => options.ticketIds.includes(t.id));
|
|
422
|
+
// Check if any requested tickets weren't found
|
|
423
|
+
const foundIds = new Set(allTickets.map(t => t.id));
|
|
424
|
+
const notFoundIds = options.ticketIds.filter(id => !foundIds.has(id));
|
|
425
|
+
for (const id of notFoundIds) {
|
|
426
|
+
result.skipped.push({
|
|
427
|
+
ticketId: id,
|
|
428
|
+
reason: `Ticket not found in column "${columnName}"`,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
if (allTickets.length === 0) {
|
|
433
|
+
log(`No tickets found in column "${columnName}"`);
|
|
434
|
+
return result;
|
|
435
|
+
}
|
|
436
|
+
// Filter tickets that don't have running executions
|
|
437
|
+
const ticketsToSpawn = [];
|
|
438
|
+
for (const ticket of allTickets) {
|
|
439
|
+
const runningExec = executionStorage.getRunningExecution(ticket.id);
|
|
440
|
+
if (runningExec) {
|
|
441
|
+
result.skipped.push({
|
|
442
|
+
ticketId: ticket.id,
|
|
443
|
+
reason: `Already has running execution: ${runningExec.id}`,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
ticketsToSpawn.push(ticket);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
// Apply limit
|
|
451
|
+
const ticketsToProcess = ticketsToSpawn.slice(0, limit);
|
|
452
|
+
if (ticketsToProcess.length === 0) {
|
|
453
|
+
log('No tickets available to spawn (all have running executions)');
|
|
454
|
+
return result;
|
|
455
|
+
}
|
|
456
|
+
// Get available agents (or use specific agent)
|
|
457
|
+
let availableAgents;
|
|
458
|
+
if (options.specificAgent) {
|
|
459
|
+
// Check if specific agent is available
|
|
460
|
+
if (!executionStorage.isAgentAvailable(options.specificAgent)) {
|
|
461
|
+
log(`Agent "${options.specificAgent}" is busy`);
|
|
462
|
+
for (const ticket of ticketsToProcess) {
|
|
463
|
+
result.skipped.push({
|
|
464
|
+
ticketId: ticket.id,
|
|
465
|
+
reason: `Specified agent "${options.specificAgent}" is busy`,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
return result;
|
|
469
|
+
}
|
|
470
|
+
availableAgents = [options.specificAgent];
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
availableAgents = getAvailableAgents(workspaceInfo, executionStorage);
|
|
474
|
+
}
|
|
475
|
+
if (availableAgents.length === 0) {
|
|
476
|
+
log('No agents available');
|
|
477
|
+
for (const ticket of ticketsToProcess) {
|
|
478
|
+
result.skipped.push({
|
|
479
|
+
ticketId: ticket.id,
|
|
480
|
+
reason: 'No agents available',
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
return result;
|
|
484
|
+
}
|
|
485
|
+
// Round-robin state
|
|
486
|
+
const roundRobinState = { lastIndex: -1 };
|
|
487
|
+
// Spawn for each ticket
|
|
488
|
+
for (const ticket of ticketsToProcess) {
|
|
489
|
+
// Select agent
|
|
490
|
+
const agentName = options.specificAgent
|
|
491
|
+
? options.specificAgent
|
|
492
|
+
: selectAgent(strategy, availableAgents, executionStorage, roundRobinState);
|
|
493
|
+
if (!agentName) {
|
|
494
|
+
result.skipped.push({
|
|
495
|
+
ticketId: ticket.id,
|
|
496
|
+
reason: 'No agents available',
|
|
497
|
+
});
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
if (options.dryRun) {
|
|
501
|
+
log(`[DRY RUN] Would spawn ${agentName} for ${ticket.id}: ${ticket.title}`);
|
|
502
|
+
result.spawned.push({
|
|
503
|
+
success: true,
|
|
504
|
+
ticketId: ticket.id,
|
|
505
|
+
agentName,
|
|
506
|
+
});
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
log(`Spawning ${agentName} for ${ticket.id}: ${ticket.title}`);
|
|
510
|
+
const spawnResult = await spawnAgentForTicket(ticket, agentName, storage, executionStorage, workspaceInfo, db, pmoPath, options);
|
|
511
|
+
if (spawnResult.success) {
|
|
512
|
+
result.spawned.push(spawnResult);
|
|
513
|
+
// Remove agent from available list if using round-robin/random
|
|
514
|
+
// (they can only work on one ticket at a time)
|
|
515
|
+
if (!options.specificAgent) {
|
|
516
|
+
const agentIndex = availableAgents.indexOf(agentName);
|
|
517
|
+
if (agentIndex !== -1) {
|
|
518
|
+
availableAgents.splice(agentIndex, 1);
|
|
519
|
+
}
|
|
520
|
+
// Update round-robin index since we removed an agent
|
|
521
|
+
if (roundRobinState.lastIndex >= availableAgents.length) {
|
|
522
|
+
roundRobinState.lastIndex = -1;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
result.failed.push(spawnResult);
|
|
528
|
+
}
|
|
529
|
+
// Check if we ran out of agents
|
|
530
|
+
if (availableAgents.length === 0 && !options.specificAgent) {
|
|
531
|
+
log('Ran out of available agents');
|
|
532
|
+
// Skip remaining tickets
|
|
533
|
+
const remainingIndex = ticketsToProcess.indexOf(ticket) + 1;
|
|
534
|
+
for (let i = remainingIndex; i < ticketsToProcess.length; i++) {
|
|
535
|
+
result.skipped.push({
|
|
536
|
+
ticketId: ticketsToProcess[i].id,
|
|
537
|
+
reason: 'No agents available',
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return result;
|
|
544
|
+
}
|
|
545
|
+
// =============================================================================
|
|
546
|
+
// Docker Check
|
|
547
|
+
// =============================================================================
|
|
548
|
+
export { isDockerRunning };
|