@desplega.ai/agent-swarm 1.20.0 → 1.51.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +271 -169
- package/openapi.json +5015 -0
- package/package.json +40 -7
- package/plugin/commands/close-issue.md +7 -3
- package/plugin/commands/create-pr.md +18 -12
- package/plugin/commands/implement-issue.md +7 -3
- package/plugin/commands/respond-github.md +8 -4
- package/plugin/commands/review-pr.md +44 -10
- package/plugin/commands/start-leader.md +1 -3
- package/plugin/commands/start-worker.md +1 -3
- package/plugin/commands/work-on-task.md +22 -3
- package/plugin/pi-skills/close-issue/SKILL.md +90 -0
- package/plugin/pi-skills/create-pr/SKILL.md +99 -0
- package/plugin/pi-skills/implement-issue/SKILL.md +135 -0
- package/plugin/pi-skills/investigate-sentry-issue/SKILL.md +138 -0
- package/plugin/pi-skills/respond-github/SKILL.md +98 -0
- package/plugin/pi-skills/review-offered-task/SKILL.md +45 -0
- package/plugin/pi-skills/review-pr/SKILL.md +261 -0
- package/plugin/pi-skills/start-leader/SKILL.md +121 -0
- package/plugin/pi-skills/start-worker/SKILL.md +60 -0
- package/plugin/pi-skills/swarm-chat/SKILL.md +82 -0
- package/plugin/pi-skills/todos/SKILL.md +66 -0
- package/plugin/pi-skills/work-on-task/SKILL.md +65 -0
- package/plugin/skills/artifacts/examples/approval-flow.ts +34 -0
- package/plugin/skills/artifacts/examples/hono-dashboard.ts +31 -0
- package/plugin/skills/artifacts/examples/multi-artifact.ts +20 -0
- package/plugin/skills/artifacts/examples/static-report.sh +17 -0
- package/plugin/skills/artifacts/skill.md +71 -0
- package/src/agentmail/app.ts +65 -0
- package/src/agentmail/handlers.ts +262 -0
- package/src/agentmail/index.ts +9 -0
- package/src/agentmail/templates.ts +111 -0
- package/src/agentmail/types.ts +51 -0
- package/src/artifact-sdk/browser-sdk.ts +30 -0
- package/src/artifact-sdk/index.ts +2 -0
- package/src/artifact-sdk/localtunnel.d.ts +20 -0
- package/src/artifact-sdk/port.ts +12 -0
- package/src/artifact-sdk/server.ts +156 -0
- package/src/artifact-sdk/tunnel.ts +19 -0
- package/src/be/chunking.ts +193 -0
- package/src/be/db-queries/oauth.ts +90 -0
- package/src/be/db-queries/tracker.ts +182 -0
- package/src/be/db.ts +3327 -784
- package/src/be/embedding.ts +80 -0
- package/src/be/migrations/001_initial.sql +409 -0
- package/src/be/migrations/002_one_time_schedules.sql +59 -0
- package/src/be/migrations/003_workflows.sql +51 -0
- package/src/be/migrations/004_workflow_source.sql +81 -0
- package/src/be/migrations/005_epic_next_steps.sql +2 -0
- package/src/be/migrations/006_vcs_provider.sql +94 -0
- package/src/be/migrations/007_task_dir.sql +2 -0
- package/src/be/migrations/008_workflow_redesign.sql +85 -0
- package/src/be/migrations/009_tracker_integration.sql +144 -0
- package/src/be/migrations/010_step_diagnostics.sql +1 -0
- package/src/be/migrations/011_step_next_port.sql +1 -0
- package/src/be/migrations/012_trigger_schema.sql +1 -0
- package/src/be/migrations/013_task_output_schema.sql +2 -0
- package/src/be/migrations/014_prompt_templates.sql +33 -0
- package/src/be/migrations/015_workflow_workspace.sql +3 -0
- package/src/be/migrations/016_active_session_runner_session.sql +4 -0
- package/src/be/migrations/017_channel_activity_cursors.sql +6 -0
- package/src/be/migrations/018_fix_seed_double_version.sql +30 -0
- package/src/be/migrations/runner.ts +188 -0
- package/src/be/seed.ts +62 -0
- package/src/cli.tsx +231 -299
- package/src/commands/artifact.ts +241 -0
- package/src/commands/onboard/compose-generator.ts +169 -0
- package/src/commands/onboard/env-generator.ts +79 -0
- package/src/commands/onboard/manifest.ts +37 -0
- package/src/commands/onboard/presets.ts +85 -0
- package/src/commands/onboard/service-names.ts +47 -0
- package/src/commands/onboard/steps/core-credentials.tsx +111 -0
- package/src/commands/onboard/steps/custom-templates.tsx +168 -0
- package/src/commands/onboard/steps/generate.tsx +154 -0
- package/src/commands/onboard/steps/harness-credentials.tsx +195 -0
- package/src/commands/onboard/steps/harness.tsx +21 -0
- package/src/commands/onboard/steps/health-check.tsx +171 -0
- package/src/commands/onboard/steps/integration-github.tsx +105 -0
- package/src/commands/onboard/steps/integration-gitlab.tsx +79 -0
- package/src/commands/onboard/steps/integration-menu.tsx +58 -0
- package/src/commands/onboard/steps/integration-sentry.tsx +79 -0
- package/src/commands/onboard/steps/integration-slack.tsx +165 -0
- package/src/commands/onboard/steps/post-connect.tsx +145 -0
- package/src/commands/onboard/steps/post-dashboard.tsx +34 -0
- package/src/commands/onboard/steps/post-task.tsx +103 -0
- package/src/commands/onboard/steps/prereq-check.tsx +178 -0
- package/src/commands/onboard/steps/review.tsx +82 -0
- package/src/commands/onboard/steps/start.tsx +97 -0
- package/src/commands/onboard/templates.ts +34 -0
- package/src/commands/onboard/types.ts +259 -0
- package/src/commands/onboard.tsx +425 -0
- package/src/commands/runner.ts +1540 -630
- package/src/commands/setup.tsx +23 -38
- package/src/commands/shared/client-config.ts +41 -0
- package/src/commands/templates.ts +172 -0
- package/src/github/app.ts +8 -0
- package/src/github/handlers.ts +384 -151
- package/src/github/index.ts +1 -0
- package/src/github/mentions-aliases.test.ts +73 -0
- package/src/github/mentions.test.ts +3 -3
- package/src/github/mentions.ts +32 -6
- package/src/github/templates.ts +398 -0
- package/src/github/types.ts +1 -0
- package/src/gitlab/auth.ts +63 -0
- package/src/gitlab/handlers.ts +368 -0
- package/src/gitlab/index.ts +19 -0
- package/src/gitlab/reactions.ts +104 -0
- package/src/gitlab/templates.ts +140 -0
- package/src/gitlab/types.ts +130 -0
- package/src/heartbeat/heartbeat.ts +434 -0
- package/src/heartbeat/index.ts +1 -0
- package/src/heartbeat/templates.ts +30 -0
- package/src/hooks/hook.ts +555 -4
- package/src/hooks/tool-loop-detection.test.ts +158 -0
- package/src/hooks/tool-loop-detection.ts +167 -0
- package/src/http/active-sessions.ts +199 -0
- package/src/http/agents.ts +328 -0
- package/src/http/config.ts +191 -0
- package/src/http/core.ts +309 -0
- package/src/http/db-query.ts +91 -0
- package/src/http/ecosystem.ts +63 -0
- package/src/http/epics.ts +460 -0
- package/src/http/index.ts +216 -0
- package/src/http/mcp.ts +77 -0
- package/src/http/memory.ts +168 -0
- package/src/http/openapi.ts +109 -0
- package/src/http/poll.ts +299 -0
- package/src/http/prompt-templates.ts +412 -0
- package/src/http/repos.ts +195 -0
- package/src/http/route-def.ts +123 -0
- package/src/http/schedules.ts +426 -0
- package/src/http/session-data.ts +241 -0
- package/src/http/stats.ts +174 -0
- package/src/http/tasks.ts +468 -0
- package/src/http/trackers/index.ts +10 -0
- package/src/http/trackers/linear.ts +187 -0
- package/src/http/types.ts +12 -0
- package/src/http/utils.ts +87 -0
- package/src/http/webhooks.ts +432 -0
- package/src/http/workflows.ts +530 -0
- package/src/http.ts +1 -1890
- package/src/linear/README.md +65 -0
- package/src/linear/app.ts +48 -0
- package/src/linear/client.ts +18 -0
- package/src/linear/index.ts +1 -0
- package/src/linear/oauth.ts +35 -0
- package/src/linear/outbound.ts +212 -0
- package/src/linear/sync.ts +567 -0
- package/src/linear/templates.ts +47 -0
- package/src/linear/types.ts +7 -0
- package/src/linear/webhook.ts +104 -0
- package/src/oauth/README.md +66 -0
- package/src/oauth/index.ts +6 -0
- package/src/oauth/wrapper.ts +204 -0
- package/src/prompts/base-prompt.ts +150 -265
- package/src/prompts/defaults.ts +196 -0
- package/src/prompts/registry.ts +57 -0
- package/src/prompts/resolver.ts +296 -0
- package/src/prompts/session-templates.ts +604 -0
- package/src/providers/claude-adapter.ts +442 -0
- package/src/providers/index.ts +24 -0
- package/src/providers/pi-mono-adapter.ts +442 -0
- package/src/providers/pi-mono-extension.ts +624 -0
- package/src/providers/pi-mono-mcp-client.ts +124 -0
- package/src/providers/types.ts +75 -0
- package/src/scheduler/scheduler.test.ts +2 -0
- package/src/scheduler/scheduler.ts +231 -40
- package/src/server.ts +97 -6
- package/src/slack/HEURISTICS.md +105 -0
- package/src/slack/actions.ts +133 -0
- package/src/slack/app.ts +7 -0
- package/src/slack/assistant.ts +118 -0
- package/src/slack/blocks.ts +233 -0
- package/src/slack/channel-activity.ts +177 -0
- package/src/slack/commands.ts +31 -17
- package/src/slack/files.ts +1 -1
- package/src/slack/handlers.test.ts +114 -1
- package/src/slack/handlers.ts +230 -55
- package/src/slack/responses.ts +120 -67
- package/src/slack/router.ts +17 -99
- package/src/slack/templates.ts +55 -0
- package/src/slack/thread-buffer.ts +213 -0
- package/src/slack/watcher.ts +119 -4
- package/src/tests/agent-activity.test.ts +247 -0
- package/src/tests/agentmail-filters.test.ts +97 -0
- package/src/tests/artifact-sdk.test.ts +800 -0
- package/src/tests/base-prompt.test.ts +264 -0
- package/src/tests/build-pi-skills.test.ts +127 -0
- package/src/tests/channel-activity.test.ts +363 -0
- package/src/tests/claude-adapter.test.ts +126 -0
- package/src/tests/context-versioning.test.ts +425 -0
- package/src/tests/db-queries-oauth.test.ts +197 -0
- package/src/tests/db-queries-tracker.test.ts +230 -0
- package/src/tests/epics.test.ts +3 -3
- package/src/tests/error-tracker.test.ts +368 -0
- package/src/tests/fetch-resolved-env.test.ts +167 -0
- package/src/tests/generate-default-claude-md.test.ts +9 -1
- package/src/tests/generate-identity-templates.test.ts +124 -0
- package/src/tests/gitlab-auth.test.ts +109 -0
- package/src/tests/gitlab-handlers.test.ts +691 -0
- package/src/tests/gitlab-vcs-db.test.ts +177 -0
- package/src/tests/heartbeat.test.ts +364 -0
- package/src/tests/http-api-integration.test.ts +1698 -0
- package/src/tests/linear-outbound-sync.test.ts +200 -0
- package/src/tests/linear-webhook.test.ts +406 -0
- package/src/tests/match-route.test.ts +187 -0
- package/src/tests/memory.test.ts +737 -0
- package/src/tests/migration-runner-regressions.test.ts +86 -0
- package/src/tests/model-control.test.ts +338 -0
- package/src/tests/oauth-wrapper.test.ts +147 -0
- package/src/tests/onboard-compose.test.ts +138 -0
- package/src/tests/onboard-env.test.ts +174 -0
- package/src/tests/onboard-manifest.test.ts +137 -0
- package/src/tests/pi-mono-adapter.test.ts +234 -0
- package/src/tests/pool-session-logs.test.ts +199 -0
- package/src/tests/progress-dedup.test.ts +98 -0
- package/src/tests/prompt-template-github.test.ts +682 -0
- package/src/tests/prompt-template-remaining.test.ts +504 -0
- package/src/tests/prompt-template-resolver.test.ts +621 -0
- package/src/tests/prompt-template-session.test.ts +363 -0
- package/src/tests/prompt-templates-db.test.ts +616 -0
- package/src/tests/provider-adapter.test.ts +122 -0
- package/src/tests/provider-command-format.test.ts +98 -0
- package/src/tests/reload-config.test.ts +170 -0
- package/src/tests/runner-polling-api.test.ts +25 -20
- package/src/tests/scheduled-tasks.test.ts +104 -0
- package/src/tests/scheduler-backoff.test.ts +166 -0
- package/src/tests/self-improvement.test.ts +541 -0
- package/src/tests/session-attach.test.ts +536 -0
- package/src/tests/session-costs.test.ts +267 -1
- package/src/tests/slack-actions.test.ts +133 -0
- package/src/tests/slack-assistant.test.ts +136 -0
- package/src/tests/slack-blocks.test.ts +246 -0
- package/src/tests/slack-metadata-inheritance.test.ts +243 -0
- package/src/tests/slack-queue-offline.test.ts +174 -0
- package/src/tests/slack-router.test.ts +181 -0
- package/src/tests/slack-thread-buffer.test.ts +305 -0
- package/src/tests/slack-thread-followups.test.ts +298 -0
- package/src/tests/slack-watcher.test.ts +101 -0
- package/src/tests/structured-output.test.ts +307 -0
- package/src/tests/swarm-repos.test.ts +198 -0
- package/src/tests/task-cancellation.test.ts +6 -4
- package/src/tests/task-working-dir.test.ts +176 -0
- package/src/tests/template-fetch.test.ts +490 -0
- package/src/tests/tool-annotations.test.ts +371 -0
- package/src/tests/tracker-tools.test.ts +184 -0
- package/src/tests/update-profile-agentid.test.ts +248 -0
- package/src/tests/update-profile-api.test.ts +143 -3
- package/src/tests/update-profile-auth.test.ts +195 -0
- package/src/tests/validation-adapters.test.ts +86 -0
- package/src/tests/vcs-provider.test.ts +27 -0
- package/src/tests/workflow-agent-task.test.ts +196 -0
- package/src/tests/workflow-async-v2.test.ts +508 -0
- package/src/tests/workflow-convergence.test.ts +541 -0
- package/src/tests/workflow-definition-validation.test.ts +366 -0
- package/src/tests/workflow-engine-v2.test.ts +691 -0
- package/src/tests/workflow-executors.test.ts +736 -0
- package/src/tests/workflow-http-v2.test.ts +599 -0
- package/src/tests/workflow-integration-io.test.ts +902 -0
- package/src/tests/workflow-io-schemas.test.ts +624 -0
- package/src/tests/workflow-registry.test.ts +592 -0
- package/src/tests/workflow-retry-v2.test.ts +401 -0
- package/src/tests/workflow-retry-validation.test.ts +282 -0
- package/src/tests/workflow-schedule-trigger.test.ts +104 -0
- package/src/tests/workflow-template.test.ts +288 -0
- package/src/tests/workflow-trigger-schema.test.ts +359 -0
- package/src/tests/workflow-triggers-v2.test.ts +264 -0
- package/src/tests/workflow-versions.test.ts +208 -0
- package/src/tests/workflow-workspace.test.ts +272 -0
- package/src/tests/x402-client.test.ts +117 -0
- package/src/tests/x402-config.test.ts +182 -0
- package/src/tests/x402-spending-tracker.test.ts +185 -0
- package/src/tools/cancel-task.ts +2 -0
- package/src/tools/context-diff.ts +171 -0
- package/src/tools/context-history.ts +138 -0
- package/src/tools/create-channel.ts +1 -0
- package/src/tools/db-query.ts +78 -0
- package/src/tools/delete-channel.ts +132 -0
- package/src/tools/epics/assign-task-to-epic.ts +1 -0
- package/src/tools/epics/create-epic.ts +3 -2
- package/src/tools/epics/delete-epic.ts +2 -0
- package/src/tools/epics/get-epic-details.ts +2 -0
- package/src/tools/epics/list-epics.ts +2 -0
- package/src/tools/epics/unassign-task-from-epic.ts +1 -0
- package/src/tools/epics/update-epic.ts +7 -4
- package/src/tools/get-swarm.ts +2 -0
- package/src/tools/get-task-details.ts +2 -0
- package/src/tools/get-tasks.ts +27 -1
- package/src/tools/inject-learning.ts +106 -0
- package/src/tools/join-swarm.ts +17 -7
- package/src/tools/list-channels.ts +2 -0
- package/src/tools/list-services.ts +2 -0
- package/src/tools/memory-get.ts +56 -0
- package/src/tools/memory-search.ts +131 -0
- package/src/tools/my-agent-info.ts +2 -0
- package/src/tools/poll-task.ts +2 -20
- package/src/tools/post-message.ts +1 -0
- package/src/tools/prompt-templates/delete.ts +86 -0
- package/src/tools/prompt-templates/get.ts +89 -0
- package/src/tools/prompt-templates/index.ts +5 -0
- package/src/tools/prompt-templates/list.ts +95 -0
- package/src/tools/prompt-templates/preview.ts +84 -0
- package/src/tools/prompt-templates/set.ts +117 -0
- package/src/tools/read-messages.ts +2 -0
- package/src/tools/register-agentmail-inbox.ts +166 -0
- package/src/tools/register-service.ts +2 -0
- package/src/tools/schedules/create-schedule.ts +134 -24
- package/src/tools/schedules/delete-schedule.ts +2 -0
- package/src/tools/schedules/list-schedules.ts +20 -4
- package/src/tools/schedules/run-schedule-now.ts +1 -0
- package/src/tools/schedules/update-schedule.ts +49 -17
- package/src/tools/send-task.ts +132 -10
- package/src/tools/slack-download-file.ts +4 -2
- package/src/tools/slack-list-channels.ts +2 -0
- package/src/tools/slack-post.ts +2 -0
- package/src/tools/slack-read.ts +2 -0
- package/src/tools/slack-reply.ts +2 -0
- package/src/tools/slack-upload-file.ts +2 -0
- package/src/tools/store-progress.ts +205 -4
- package/src/tools/swarm-config/delete-config.ts +87 -0
- package/src/tools/swarm-config/get-config.ts +108 -0
- package/src/tools/swarm-config/index.ts +4 -0
- package/src/tools/swarm-config/list-config.ts +99 -0
- package/src/tools/swarm-config/set-config.ts +118 -0
- package/src/tools/task-action.ts +50 -5
- package/src/tools/task-dedup.ts +97 -0
- package/src/tools/templates.ts +53 -0
- package/src/tools/tool-config.ts +124 -0
- package/src/tools/tracker/index.ts +6 -0
- package/src/tools/tracker/tracker-link-epic.ts +64 -0
- package/src/tools/tracker/tracker-link-task.ts +64 -0
- package/src/tools/tracker/tracker-map-agent.ts +57 -0
- package/src/tools/tracker/tracker-status.ts +56 -0
- package/src/tools/tracker/tracker-sync-status.ts +42 -0
- package/src/tools/tracker/tracker-unlink.ts +41 -0
- package/src/tools/unregister-service.ts +2 -0
- package/src/tools/update-profile.ts +172 -17
- package/src/tools/update-service-status.ts +2 -0
- package/src/tools/utils.ts +10 -1
- package/src/tools/workflows/create-workflow.ts +129 -0
- package/src/tools/workflows/delete-workflow.ts +42 -0
- package/src/tools/workflows/get-workflow-run.ts +59 -0
- package/src/tools/workflows/get-workflow.ts +53 -0
- package/src/tools/workflows/index.ts +9 -0
- package/src/tools/workflows/list-workflow-runs.ts +48 -0
- package/src/tools/workflows/list-workflows.ts +42 -0
- package/src/tools/workflows/retry-workflow-run.ts +40 -0
- package/src/tools/workflows/trigger-workflow.ts +96 -0
- package/src/tools/workflows/update-workflow.ts +133 -0
- package/src/tracker/types.ts +51 -0
- package/src/types.ts +530 -14
- package/src/utils/credentials.test.ts +156 -0
- package/src/utils/credentials.ts +50 -0
- package/src/utils/error-tracker.ts +190 -0
- package/src/vcs/index.ts +15 -0
- package/src/vcs/types.ts +5 -0
- package/src/workflows/checkpoint.ts +121 -0
- package/src/workflows/cooldown.ts +28 -0
- package/src/workflows/definition.ts +235 -0
- package/src/workflows/engine.ts +580 -0
- package/src/workflows/event-bus.ts +29 -0
- package/src/workflows/executors/agent-task.ts +103 -0
- package/src/workflows/executors/base.ts +86 -0
- package/src/workflows/executors/code-match.ts +88 -0
- package/src/workflows/executors/index.ts +16 -0
- package/src/workflows/executors/notify.ts +93 -0
- package/src/workflows/executors/property-match.ts +104 -0
- package/src/workflows/executors/raw-llm.ts +83 -0
- package/src/workflows/executors/registry.ts +76 -0
- package/src/workflows/executors/script.ts +103 -0
- package/src/workflows/executors/validate.ts +215 -0
- package/src/workflows/executors/vcs.ts +58 -0
- package/src/workflows/index.ts +61 -0
- package/src/workflows/input.ts +46 -0
- package/src/workflows/json-schema-validator.ts +118 -0
- package/src/workflows/recovery.ts +139 -0
- package/src/workflows/resume.ts +229 -0
- package/src/workflows/retry-poller.ts +216 -0
- package/src/workflows/template.ts +74 -0
- package/src/workflows/templates.ts +86 -0
- package/src/workflows/triggers.ts +124 -0
- package/src/workflows/validation.ts +104 -0
- package/src/workflows/version.ts +44 -0
- package/src/x402/cli.ts +140 -0
- package/src/x402/client.ts +192 -0
- package/src/x402/config.ts +131 -0
- package/src/x402/index.ts +37 -0
- package/src/x402/openfort-signer.ts +83 -0
- package/src/x402/spending-tracker.ts +109 -0
- package/templates/official/coder/CLAUDE.md +49 -0
- package/templates/official/coder/IDENTITY.md +28 -0
- package/templates/official/coder/SOUL.md +43 -0
- package/templates/official/coder/TOOLS.md +40 -0
- package/templates/official/coder/config.json +23 -0
- package/templates/official/coder/start-up.sh +23 -0
- package/templates/official/content-reviewer/CLAUDE.md +68 -0
- package/templates/official/content-reviewer/IDENTITY.md +28 -0
- package/templates/official/content-reviewer/SOUL.md +44 -0
- package/templates/official/content-reviewer/TOOLS.md +37 -0
- package/templates/official/content-reviewer/config.json +23 -0
- package/templates/official/content-reviewer/start-up.sh +23 -0
- package/templates/official/content-strategist/CLAUDE.md +63 -0
- package/templates/official/content-strategist/IDENTITY.md +33 -0
- package/templates/official/content-strategist/SOUL.md +48 -0
- package/templates/official/content-strategist/TOOLS.md +47 -0
- package/templates/official/content-strategist/config.json +23 -0
- package/templates/official/content-strategist/start-up.sh +23 -0
- package/templates/official/content-writer/CLAUDE.md +72 -0
- package/templates/official/content-writer/IDENTITY.md +30 -0
- package/templates/official/content-writer/SOUL.md +46 -0
- package/templates/official/content-writer/TOOLS.md +44 -0
- package/templates/official/content-writer/config.json +23 -0
- package/templates/official/content-writer/start-up.sh +23 -0
- package/templates/official/forward-deployed-engineer/CLAUDE.md +54 -0
- package/templates/official/forward-deployed-engineer/IDENTITY.md +37 -0
- package/templates/official/forward-deployed-engineer/SOUL.md +55 -0
- package/templates/official/forward-deployed-engineer/config.json +21 -0
- package/templates/official/lead/CLAUDE.md +33 -0
- package/templates/official/lead/IDENTITY.md +36 -0
- package/templates/official/lead/SOUL.md +51 -0
- package/templates/official/lead/config.json +22 -0
- package/templates/official/researcher/CLAUDE.md +46 -0
- package/templates/official/researcher/IDENTITY.md +28 -0
- package/templates/official/researcher/SOUL.md +43 -0
- package/templates/official/researcher/config.json +21 -0
- package/templates/official/reviewer/CLAUDE.md +63 -0
- package/templates/official/reviewer/IDENTITY.md +28 -0
- package/templates/official/reviewer/SOUL.md +45 -0
- package/templates/official/reviewer/config.json +21 -0
- package/templates/official/tester/CLAUDE.md +53 -0
- package/templates/official/tester/IDENTITY.md +28 -0
- package/templates/official/tester/SOUL.md +55 -0
- package/templates/official/tester/config.json +21 -0
- package/templates/schema.ts +35 -0
- package/.claude/settings.local.json +0 -115
- package/.dockerignore +0 -61
- package/.editorconfig +0 -15
- package/.env.docker.example +0 -39
- package/.env.example +0 -40
- package/.github/workflows/ci.yml +0 -76
- package/.github/workflows/docker-and-deploy.yml +0 -117
- package/.wts-config.json +0 -4
- package/.wts-setup.ts +0 -102
- package/CLAUDE.md +0 -104
- package/CONTRIBUTING.md +0 -270
- package/DEPLOYMENT.md +0 -605
- package/Dockerfile +0 -57
- package/Dockerfile.worker +0 -157
- package/FAQ.md +0 -19
- package/MCP.md +0 -406
- package/UI.md +0 -40
- package/assets/agent-swarm-logo-orange.png +0 -0
- package/assets/agent-swarm-logo.png +0 -0
- package/assets/agent-swarm.mp4 +0 -0
- package/assets/agent-swarm.png +0 -0
- package/biome.json +0 -39
- package/deploy/DEPLOY.md +0 -60
- package/deploy/agent-swarm.service +0 -17
- package/deploy/docker-push.ts +0 -30
- package/deploy/install.ts +0 -85
- package/deploy/prod-db.ts +0 -42
- package/deploy/uninstall.ts +0 -12
- package/deploy/update.ts +0 -21
- package/docker-compose.example.yml +0 -159
- package/docker-entrypoint.sh +0 -352
- package/ecosystem.config.cjs +0 -66
- package/plugin/README.md +0 -1
- package/plugin/hooks/hooks.json +0 -71
- package/pyproject.toml +0 -9
- package/scripts/generate-mcp-docs.ts +0 -415
- package/slack-manifest.json +0 -71
- package/src/tests/get-inbox-message.test.ts +0 -145
- package/src/tools/get-inbox-message.ts +0 -89
- package/src/tools/inbox-delegate.ts +0 -113
- package/thoughts/shared/plans/2025-12-18-slack-integration.md +0 -1195
- package/thoughts/shared/plans/2025-12-19-agent-log-streaming.md +0 -732
- package/thoughts/shared/plans/2025-12-19-role-based-swarm-plugin.md +0 -361
- package/thoughts/shared/plans/2025-12-20-mobile-responsive-ui.md +0 -501
- package/thoughts/shared/plans/2025-12-20-startup-team-swarm.md +0 -560
- package/thoughts/shared/plans/2025-12-23-runner-level-polling.md +0 -934
- package/thoughts/shared/plans/2025-12-23-runner-session-logs.md +0 -1000
- package/thoughts/shared/plans/2025-12-23-worker-lead-spawn-triggers.md +0 -568
- package/thoughts/shared/plans/2026-01-09-inverse-teleport.md +0 -1516
- package/thoughts/shared/plans/2026-01-12-agent-rename-pm2-control.md +0 -1133
- package/thoughts/shared/plans/2026-01-12-github-app-integration.md +0 -380
- package/thoughts/shared/plans/2026-01-12-lead-inbox-model.md +0 -876
- package/thoughts/shared/plans/2026-01-12-ralph-wiggum-integration.md +0 -463
- package/thoughts/shared/plans/2026-01-13-agent-concurrency.md +0 -691
- package/thoughts/shared/plans/2026-01-13-github-assignment-handling.md +0 -690
- package/thoughts/shared/plans/2026-01-13-prevent-duplicate-trigger-processing.md +0 -1071
- package/thoughts/shared/plans/2026-01-14-fix-slack-thread-context.md +0 -507
- package/thoughts/shared/plans/2026-01-15-scheduled-tasks-implementation.md +0 -565
- package/thoughts/shared/plans/2026-01-15-usage-cost-tracking-ui.md +0 -1479
- package/thoughts/shared/plans/2026-01-16-epics-feature-implementation.md +0 -1230
- package/thoughts/shared/research/.gitkeep +0 -0
- package/thoughts/shared/research/2025-01-09-inverse-teleport-plan-review.md +0 -420
- package/thoughts/shared/research/2025-12-18-slack-integration.md +0 -442
- package/thoughts/shared/research/2025-12-19-agent-log-streaming.md +0 -339
- package/thoughts/shared/research/2025-12-19-agent-secrets-cli-research.md +0 -390
- package/thoughts/shared/research/2025-12-21-gemini-cli-integration.md +0 -376
- package/thoughts/shared/research/2025-12-22-runner-loop-architecture.md +0 -582
- package/thoughts/shared/research/2025-12-22-setup-experience-improvements.md +0 -264
- package/thoughts/shared/research/2026-01-13-lead-duplicate-trigger-processing.md +0 -223
- package/thoughts/shared/research/2026-01-14-lead-slack-thread-context.md +0 -277
- package/thoughts/shared/research/2026-01-15-ai-tracker-agent-swarm-integration.md +0 -376
- package/thoughts/shared/research/2026-01-15-auto-starting-processes-in-worker-containers.md +0 -787
- package/thoughts/shared/research/2026-01-15-scheduled-tasks.md +0 -390
- package/thoughts/shared/research/2026-01-16-epics-feature-research.md +0 -437
- package/thoughts/taras/plans/2026-01-22-agent-swarm-schemas.md +0 -98
- package/thoughts/taras/plans/2026-01-28-per-worker-claude-md.md +0 -617
- package/thoughts/taras/plans/2026-01-28-sentry-cli-integration.md +0 -214
- package/thoughts/taras/research/2026-01-22-vercel-cli-integration.md +0 -287
- package/thoughts/taras/research/2026-01-27-excessive-polling-issue.md +0 -311
- package/thoughts/taras/research/2026-01-28-per-worker-claude-md.md +0 -383
- package/thoughts/taras/research/2026-01-28-sentry-cli-integration.md +0 -240
- package/tsconfig.json +0 -37
- package/ui/CLAUDE.md +0 -49
- package/ui/bun.lock +0 -771
- package/ui/index.html +0 -22
- package/ui/package-lock.json +0 -5290
- package/ui/package.json +0 -33
- package/ui/pnpm-lock.yaml +0 -3341
- package/ui/postcss.config.js +0 -6
- package/ui/public/logo.png +0 -0
- package/ui/src/App.tsx +0 -63
- package/ui/src/components/ActivityFeed.tsx +0 -440
- package/ui/src/components/AgentDetailPanel.tsx +0 -733
- package/ui/src/components/AgentsPanel.tsx +0 -815
- package/ui/src/components/ChatPanel.tsx +0 -1920
- package/ui/src/components/ConfigModal.tsx +0 -253
- package/ui/src/components/Dashboard.tsx +0 -832
- package/ui/src/components/EditAgentProfileModal.tsx +0 -433
- package/ui/src/components/EpicDetailPage.tsx +0 -741
- package/ui/src/components/EpicsPanel.tsx +0 -566
- package/ui/src/components/Header.tsx +0 -160
- package/ui/src/components/JsonViewer.tsx +0 -171
- package/ui/src/components/ScheduledTaskDetailPanel.tsx +0 -517
- package/ui/src/components/ScheduledTasksPanel.tsx +0 -639
- package/ui/src/components/ServicesPanel.tsx +0 -622
- package/ui/src/components/SessionLogPanel.tsx +0 -1219
- package/ui/src/components/StatsBar.tsx +0 -321
- package/ui/src/components/StatusBadge.tsx +0 -168
- package/ui/src/components/TaskDetailPanel.tsx +0 -903
- package/ui/src/components/TasksPanel.tsx +0 -614
- package/ui/src/components/UsageCharts.tsx +0 -216
- package/ui/src/components/UsageTab.tsx +0 -394
- package/ui/src/hooks/queries.ts +0 -353
- package/ui/src/hooks/useAutoScroll.ts +0 -83
- package/ui/src/index.css +0 -257
- package/ui/src/lib/api.ts +0 -268
- package/ui/src/lib/config.ts +0 -35
- package/ui/src/lib/contentPreview.ts +0 -208
- package/ui/src/lib/theme.ts +0 -214
- package/ui/src/lib/utils.ts +0 -88
- package/ui/src/main.tsx +0 -28
- package/ui/src/types/api.ts +0 -323
- package/ui/src/vite-env.d.ts +0 -1
- package/ui/tailwind.config.js +0 -37
- package/ui/tsconfig.json +0 -31
- package/ui/vite.config.ts +0 -35
- /package/{thoughts/shared/plans → templates/community}/.gitkeep +0 -0
|
@@ -1,691 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
date: 2026-01-13
|
|
3
|
-
author: master lord
|
|
4
|
-
git_commit: 5ce502b
|
|
5
|
-
branch: main
|
|
6
|
-
repository: agent-swarm
|
|
7
|
-
topic: "Agent Concurrency - Parallel Claude Subprocess Execution"
|
|
8
|
-
tags: [plan, concurrency, runner, parallel-execution, capacity-management]
|
|
9
|
-
status: complete
|
|
10
|
-
last_updated: 2026-01-13T16:20:00Z
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Implementation Progress Summary
|
|
14
|
-
|
|
15
|
-
**COMPLETE - All implementation and manual verification finished.**
|
|
16
|
-
|
|
17
|
-
### Completed:
|
|
18
|
-
- [x] Phase 1: Database and Type Changes
|
|
19
|
-
- [x] Phase 2: Task Assignment Capacity Checks
|
|
20
|
-
- [x] Phase 3: Runner Parallel Execution
|
|
21
|
-
- [x] Phase 4: API and Registration Updates
|
|
22
|
-
- [x] Phase 5: Integration Testing (automated tests)
|
|
23
|
-
|
|
24
|
-
### Bug Fixes Applied:
|
|
25
|
-
1. **Poll endpoint marking tasks in_progress** (`src/http.ts:369-380`) - Fixed duplicate task polling by marking tasks as `in_progress` when returned via poll API
|
|
26
|
-
2. **Process completion detection** (`src/commands/runner.ts:684-699`) - Fixed using `task.process.exitCode !== null` instead of broken `Promise.race` pattern
|
|
27
|
-
3. **Poll endpoint capacity check** (`src/http.ts:371-384`) - Added server-side capacity check before returning pending tasks to prevent exceeding maxTasks
|
|
28
|
-
4. **Agent registration maxTasks sync** (`src/http.ts:315-318`, `src/be/db.ts:529-537`) - Added `updateAgentMaxTasks()` function and updated registration endpoint to sync `MAX_CONCURRENT_TASKS` env var to database when agent re-registers
|
|
29
|
-
|
|
30
|
-
### Remaining Manual Verification:
|
|
31
|
-
- [x] Phase 2: Capacity enforcement test - VERIFIED (2026-01-13)
|
|
32
|
-
- [x] Phase 3: Concurrent execution test - VERIFIED (server-side enforces maxTasks, tasks queue correctly)
|
|
33
|
-
- [x] Phase 4: API capacity response - VERIFIED (maxTasks shows in agent responses)
|
|
34
|
-
- [x] Phase 5: Full end-to-end test - VERIFIED (tasks queue when at capacity, process when slots free)
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
# Agent Concurrency Implementation Plan
|
|
39
|
-
|
|
40
|
-
## Overview
|
|
41
|
-
|
|
42
|
-
Add support for parallel Claude subprocess execution to the agent-swarm system, allowing leads and workers to handle multiple tasks concurrently. Each agent will have a configurable maximum concurrency limit (default: 1 for backwards compatibility).
|
|
43
|
-
|
|
44
|
-
## Current State Analysis
|
|
45
|
-
|
|
46
|
-
The current architecture is strictly sequential:
|
|
47
|
-
|
|
48
|
-
1. **Runner loop** (`src/commands/runner.ts:573-661`) polls for one trigger at a time and **blocks until Claude completes** before polling for the next trigger
|
|
49
|
-
2. **Agent status** is binary: `idle`, `busy`, `offline` (`src/types.ts:97`)
|
|
50
|
-
3. **Task assignment** is blocked when agent is not `idle` (`src/tools/send-task.ts:119-125`)
|
|
51
|
-
4. **Status management**: `store-progress.ts:91,99` sets agent to `idle` on task completion
|
|
52
|
-
|
|
53
|
-
### Key Files:
|
|
54
|
-
- `src/commands/runner.ts` - Main runner loop (lines 573-661)
|
|
55
|
-
- `src/types.ts` - Agent and task schemas
|
|
56
|
-
- `src/be/db.ts` - Database operations
|
|
57
|
-
- `src/http.ts` - HTTP API including `/api/poll` (lines 316-425)
|
|
58
|
-
- `src/tools/send-task.ts` - Task assignment logic
|
|
59
|
-
- `src/tools/store-progress.ts` - Task completion handling
|
|
60
|
-
- `src/tools/poll-task.ts` - MCP polling tool
|
|
61
|
-
|
|
62
|
-
## Desired End State
|
|
63
|
-
|
|
64
|
-
After implementation:
|
|
65
|
-
- Agents can run N Claude subprocesses concurrently (configurable via `MAX_CONCURRENT_TASKS` env var)
|
|
66
|
-
- Runner spawns Claude without blocking, tracking active processes in a Map
|
|
67
|
-
- Capacity is checked before task assignment (not binary idle/busy)
|
|
68
|
-
- Tasks queue in `pending` status when agent is at capacity, picked up when slots open
|
|
69
|
-
- Status derived from active task count (`idle` = 0 tasks, `busy` = 1+ tasks)
|
|
70
|
-
- Default limit is 1 (backwards compatible)
|
|
71
|
-
|
|
72
|
-
### Verification:
|
|
73
|
-
1. Set `MAX_CONCURRENT_TASKS=3` and send 3 tasks to a worker
|
|
74
|
-
2. All 3 Claude processes should run simultaneously
|
|
75
|
-
3. A 4th task should queue in `pending` until one completes
|
|
76
|
-
4. Agent status shows `busy` while any task is running
|
|
77
|
-
|
|
78
|
-
## What We're NOT Doing
|
|
79
|
-
|
|
80
|
-
- NOT changing the MCP `poll-task` tool (it's for AI-loop mode, mostly unused)
|
|
81
|
-
- NOT adding a formal job queue system (simple Promise tracking is sufficient)
|
|
82
|
-
- NOT using PM2 for subprocess management (overkill for this)
|
|
83
|
-
- NOT changing the lead inbox model (leads still process inbox triggers)
|
|
84
|
-
- NOT implementing task priority-based scheduling (FIFO from pending queue)
|
|
85
|
-
|
|
86
|
-
## Implementation Approach
|
|
87
|
-
|
|
88
|
-
**Capacity Model**: Track `maxTasks` per agent in the database, derive active count from `agent_tasks` table where `status = 'in_progress'`. This ensures accuracy without stale state.
|
|
89
|
-
|
|
90
|
-
**Process Model**: Track running Claude processes in a `Map<taskId, Promise<number>>` within the runner. Poll for new triggers when under capacity, spawn without blocking.
|
|
91
|
-
|
|
92
|
-
**Status Derivation**: Keep `idle/busy/offline` status but derive from active task count. Agent is `idle` when no in-progress tasks, `busy` otherwise.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Phase 1: Database and Type Changes
|
|
97
|
-
|
|
98
|
-
### Overview
|
|
99
|
-
Add capacity tracking fields to the agent schema and database, implement helper functions.
|
|
100
|
-
|
|
101
|
-
### Changes Required:
|
|
102
|
-
|
|
103
|
-
#### 1. Update Agent Schema
|
|
104
|
-
**File**: `src/types.ts`
|
|
105
|
-
|
|
106
|
-
Add `maxTasks` field to `AgentSchema`:
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
export const AgentSchema = z.object({
|
|
110
|
-
id: z.uuid(),
|
|
111
|
-
name: z.string().min(1),
|
|
112
|
-
isLead: z.boolean().default(false),
|
|
113
|
-
status: AgentStatusSchema,
|
|
114
|
-
|
|
115
|
-
// Profile fields
|
|
116
|
-
description: z.string().optional(),
|
|
117
|
-
role: z.string().max(100).optional(),
|
|
118
|
-
capabilities: z.array(z.string()).default([]),
|
|
119
|
-
|
|
120
|
-
// NEW: Concurrency limit
|
|
121
|
-
maxTasks: z.number().int().min(1).max(20).default(1),
|
|
122
|
-
|
|
123
|
-
createdAt: z.iso.datetime().default(() => new Date().toISOString()),
|
|
124
|
-
lastUpdatedAt: z.iso.datetime().default(() => new Date().toISOString()),
|
|
125
|
-
});
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
#### 2. Database Schema Migration
|
|
129
|
-
**File**: `src/be/db.ts`
|
|
130
|
-
|
|
131
|
-
Add column to agents table in `initDb()` (around line 42):
|
|
132
|
-
|
|
133
|
-
```sql
|
|
134
|
-
ALTER TABLE agents ADD COLUMN maxTasks INTEGER DEFAULT 1;
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
Handle migration for existing databases by checking if column exists.
|
|
138
|
-
|
|
139
|
-
#### 3. Add Capacity Functions
|
|
140
|
-
**File**: `src/be/db.ts`
|
|
141
|
-
|
|
142
|
-
Add new functions after `updateAgentStatus()` (around line 520):
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
export function getActiveTaskCount(agentId: string): number {
|
|
146
|
-
const result = getDb()
|
|
147
|
-
.prepare<{ count: number }, [string]>(
|
|
148
|
-
"SELECT COUNT(*) as count FROM agent_tasks WHERE agentId = ? AND status = 'in_progress'"
|
|
149
|
-
)
|
|
150
|
-
.get(agentId);
|
|
151
|
-
return result?.count ?? 0;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export function hasCapacity(agentId: string): boolean {
|
|
155
|
-
const agent = getAgentById(agentId);
|
|
156
|
-
if (!agent) return false;
|
|
157
|
-
const activeCount = getActiveTaskCount(agentId);
|
|
158
|
-
return activeCount < (agent.maxTasks ?? 1);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function getRemainingCapacity(agentId: string): number {
|
|
162
|
-
const agent = getAgentById(agentId);
|
|
163
|
-
if (!agent) return 0;
|
|
164
|
-
const activeCount = getActiveTaskCount(agentId);
|
|
165
|
-
return Math.max(0, (agent.maxTasks ?? 1) - activeCount);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export function updateAgentStatusFromCapacity(agentId: string): void {
|
|
169
|
-
const agent = getAgentById(agentId);
|
|
170
|
-
if (!agent || agent.status === 'offline') return;
|
|
171
|
-
|
|
172
|
-
const activeCount = getActiveTaskCount(agentId);
|
|
173
|
-
const newStatus = activeCount > 0 ? 'busy' : 'idle';
|
|
174
|
-
|
|
175
|
-
if (agent.status !== newStatus) {
|
|
176
|
-
updateAgentStatus(agentId, newStatus);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
#### 4. Update Agent Registration
|
|
182
|
-
**File**: `src/be/db.ts`
|
|
183
|
-
|
|
184
|
-
Modify `createAgent()` to accept `maxTasks` parameter.
|
|
185
|
-
|
|
186
|
-
### Success Criteria:
|
|
187
|
-
|
|
188
|
-
#### Automated Verification:
|
|
189
|
-
- [x] Type checks pass: `bun run typecheck` (if script exists) or no TS errors
|
|
190
|
-
- [x] Database migration runs: start server and verify `maxTasks` column exists
|
|
191
|
-
- [x] Unit test for capacity functions: `bun test src/tests/db-capacity.test.ts`
|
|
192
|
-
|
|
193
|
-
#### Manual Verification:
|
|
194
|
-
- [x] Query `SELECT * FROM agents` shows `maxTasks` column
|
|
195
|
-
- [x] New agents get `maxTasks = 1` by default
|
|
196
|
-
|
|
197
|
-
**Implementation Note**: After completing this phase and all automated verification passes, pause here for manual confirmation before proceeding to the next phase.
|
|
198
|
-
|
|
199
|
-
---
|
|
200
|
-
|
|
201
|
-
## Phase 2: Task Assignment Capacity Checks
|
|
202
|
-
|
|
203
|
-
### Overview
|
|
204
|
-
Replace binary `idle` checks with capacity-based checks in task assignment logic.
|
|
205
|
-
|
|
206
|
-
### Changes Required:
|
|
207
|
-
|
|
208
|
-
#### 1. Update send-task Tool
|
|
209
|
-
**File**: `src/tools/send-task.ts`
|
|
210
|
-
|
|
211
|
-
Replace lines 119-125:
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
// OLD:
|
|
215
|
-
if (!offerMode && agent.status !== "idle") {
|
|
216
|
-
return {
|
|
217
|
-
success: false,
|
|
218
|
-
message: `Agent "${agent.name}" is not idle (status: ${agent.status}). Cannot assign task directly.`,
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// NEW:
|
|
223
|
-
if (!offerMode && !hasCapacity(agentId)) {
|
|
224
|
-
const activeCount = getActiveTaskCount(agentId);
|
|
225
|
-
return {
|
|
226
|
-
success: false,
|
|
227
|
-
message: `Agent "${agent.name}" is at capacity (${activeCount}/${agent.maxTasks} tasks). Use offerMode: true to offer the task instead, or wait for a task to complete.`,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
Import the new functions at the top.
|
|
233
|
-
|
|
234
|
-
#### 2. Update store-progress Tool
|
|
235
|
-
**File**: `src/tools/store-progress.ts`
|
|
236
|
-
|
|
237
|
-
Replace lines 86-107:
|
|
238
|
-
|
|
239
|
-
```typescript
|
|
240
|
-
// Handle status change
|
|
241
|
-
if (status === "completed") {
|
|
242
|
-
const result = completeTask(taskId, output);
|
|
243
|
-
if (result) {
|
|
244
|
-
updatedTask = result;
|
|
245
|
-
if (existingTask.agentId) {
|
|
246
|
-
// NEW: Derive status from capacity instead of always setting idle
|
|
247
|
-
updateAgentStatusFromCapacity(existingTask.agentId);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
} else if (status === "failed") {
|
|
251
|
-
const result = failTask(taskId, failureReason ?? "Unknown failure");
|
|
252
|
-
if (result) {
|
|
253
|
-
updatedTask = result;
|
|
254
|
-
if (existingTask.agentId) {
|
|
255
|
-
updateAgentStatusFromCapacity(existingTask.agentId);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
} else {
|
|
259
|
-
// Progress update - ensure status reflects current load
|
|
260
|
-
if (existingTask.agentId) {
|
|
261
|
-
updateAgentStatusFromCapacity(existingTask.agentId);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
#### 3. Update task-action Tool
|
|
267
|
-
**File**: `src/tools/task-action.ts`
|
|
268
|
-
|
|
269
|
-
Add capacity check for `claim` action:
|
|
270
|
-
|
|
271
|
-
```typescript
|
|
272
|
-
case "claim": {
|
|
273
|
-
if (!hasCapacity(agentId)) {
|
|
274
|
-
const activeCount = getActiveTaskCount(agentId);
|
|
275
|
-
const agent = getAgentById(agentId);
|
|
276
|
-
return {
|
|
277
|
-
success: false,
|
|
278
|
-
message: `You have no capacity (${activeCount}/${agent?.maxTasks ?? 1} tasks). Complete a task first.`
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
// ... existing claim logic
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### Success Criteria:
|
|
286
|
-
|
|
287
|
-
#### Automated Verification:
|
|
288
|
-
- [x] Type checks pass
|
|
289
|
-
- [x] Existing tests still pass: `bun test`
|
|
290
|
-
- [x] New test: assign task to agent at capacity, verify rejection message
|
|
291
|
-
|
|
292
|
-
#### Manual Verification:
|
|
293
|
-
- [ ] Set agent `maxTasks = 2`, assign 2 tasks, try to assign 3rd - should get capacity error
|
|
294
|
-
- [ ] Complete one task, agent should allow 3rd assignment
|
|
295
|
-
|
|
296
|
-
**Implementation Note**: After completing this phase and all automated verification passes, pause here for manual confirmation before proceeding to the next phase.
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## Phase 3: Runner Parallel Execution
|
|
301
|
-
|
|
302
|
-
### Overview
|
|
303
|
-
Transform the runner loop from blocking sequential execution to parallel subprocess management.
|
|
304
|
-
|
|
305
|
-
**IMPORTANT FIX REQUIRED**: The poll endpoint (`src/http.ts`) must mark tasks as `in_progress` when returning them to prevent duplicate polling. Add `startTask(pendingTask.id)` before returning the `task_assigned` trigger.
|
|
306
|
-
|
|
307
|
-
### Changes Required:
|
|
308
|
-
|
|
309
|
-
#### 1. Add Runner State Type
|
|
310
|
-
**File**: `src/commands/runner.ts`
|
|
311
|
-
|
|
312
|
-
Add new interfaces after line 100:
|
|
313
|
-
|
|
314
|
-
```typescript
|
|
315
|
-
interface RunningTask {
|
|
316
|
-
taskId: string;
|
|
317
|
-
process: ReturnType<typeof Bun.spawn>;
|
|
318
|
-
logFile: string;
|
|
319
|
-
startTime: Date;
|
|
320
|
-
promise: Promise<number>;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
interface RunnerState {
|
|
324
|
-
activeTasks: Map<string, RunningTask>;
|
|
325
|
-
maxConcurrent: number;
|
|
326
|
-
}
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
#### 2. Create Non-Blocking Claude Spawner
|
|
330
|
-
**File**: `src/commands/runner.ts`
|
|
331
|
-
|
|
332
|
-
Add new function after `runClaudeIteration()`:
|
|
333
|
-
|
|
334
|
-
```typescript
|
|
335
|
-
function spawnClaudeProcess(opts: RunClaudeIterationOptions): RunningTask {
|
|
336
|
-
const { role, logFile } = opts;
|
|
337
|
-
const Cmd = [
|
|
338
|
-
"claude",
|
|
339
|
-
"--model", "opus",
|
|
340
|
-
"--verbose",
|
|
341
|
-
"--output-format", "stream-json",
|
|
342
|
-
"--dangerously-skip-permissions",
|
|
343
|
-
"--allow-dangerously-skip-permissions",
|
|
344
|
-
"--permission-mode", "bypassPermissions",
|
|
345
|
-
"-p", opts.prompt,
|
|
346
|
-
];
|
|
347
|
-
|
|
348
|
-
if (opts.additionalArgs?.length) {
|
|
349
|
-
Cmd.push(...opts.additionalArgs);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
if (opts.systemPrompt) {
|
|
353
|
-
Cmd.push("--append-system-prompt", opts.systemPrompt);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
console.log(`[${role}] Spawning Claude for task ${opts.taskId || 'unknown'}`);
|
|
357
|
-
|
|
358
|
-
const logFileHandle = Bun.file(logFile).writer();
|
|
359
|
-
|
|
360
|
-
const proc = Bun.spawn(Cmd, {
|
|
361
|
-
env: process.env,
|
|
362
|
-
stdout: "pipe",
|
|
363
|
-
stderr: "pipe",
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
// Create promise that resolves when process completes
|
|
367
|
-
const promise = (async () => {
|
|
368
|
-
// Stream stdout and stderr (existing logic from runClaudeIteration)
|
|
369
|
-
const stdoutPromise = streamStdout(proc, logFileHandle, opts);
|
|
370
|
-
const stderrPromise = streamStderr(proc, logFileHandle, role);
|
|
371
|
-
|
|
372
|
-
await Promise.all([stdoutPromise, stderrPromise]);
|
|
373
|
-
await logFileHandle.end();
|
|
374
|
-
return await proc.exited ?? 1;
|
|
375
|
-
})();
|
|
376
|
-
|
|
377
|
-
return {
|
|
378
|
-
taskId: opts.taskId || crypto.randomUUID(),
|
|
379
|
-
process: proc,
|
|
380
|
-
logFile,
|
|
381
|
-
startTime: new Date(),
|
|
382
|
-
promise,
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
#### 3. Refactor Main Loop
|
|
388
|
-
**File**: `src/commands/runner.ts`
|
|
389
|
-
|
|
390
|
-
Replace the `while (true)` loop (lines 573-661) in non-AI-loop mode:
|
|
391
|
-
|
|
392
|
-
```typescript
|
|
393
|
-
// Initialize runner state
|
|
394
|
-
const state: RunnerState = {
|
|
395
|
-
activeTasks: new Map(),
|
|
396
|
-
maxConcurrent: parseInt(process.env.MAX_CONCURRENT_TASKS || "1", 10),
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
console.log(`[${role}] Max concurrent tasks: ${state.maxConcurrent}`);
|
|
400
|
-
|
|
401
|
-
while (true) {
|
|
402
|
-
await pingServer(apiConfig, role);
|
|
403
|
-
|
|
404
|
-
// Check for completed processes
|
|
405
|
-
await checkCompletedProcesses(state, role);
|
|
406
|
-
|
|
407
|
-
// Only poll if we have capacity
|
|
408
|
-
if (state.activeTasks.size < state.maxConcurrent) {
|
|
409
|
-
console.log(`[${role}] Polling for triggers (${state.activeTasks.size}/${state.maxConcurrent} active)...`);
|
|
410
|
-
|
|
411
|
-
const trigger = await pollForTrigger({
|
|
412
|
-
apiUrl,
|
|
413
|
-
apiKey,
|
|
414
|
-
agentId,
|
|
415
|
-
pollInterval: PollIntervalMs,
|
|
416
|
-
pollTimeout: state.activeTasks.size > 0 ? 5000 : PollTimeoutMs, // Short timeout if tasks running
|
|
417
|
-
since: lastFinishedTaskCheck,
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
if (trigger) {
|
|
421
|
-
if (trigger.type === "tasks_finished") {
|
|
422
|
-
lastFinishedTaskCheck = new Date().toISOString();
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
console.log(`[${role}] Trigger received: ${trigger.type}`);
|
|
426
|
-
|
|
427
|
-
const triggerPrompt = buildPromptForTrigger(trigger, prompt);
|
|
428
|
-
iteration++;
|
|
429
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
430
|
-
const logFile = `${logDir}/${timestamp}-${trigger.taskId?.slice(0, 8) || 'notask'}.jsonl`;
|
|
431
|
-
|
|
432
|
-
// Spawn without blocking
|
|
433
|
-
const runningTask = spawnClaudeProcess({
|
|
434
|
-
prompt: triggerPrompt,
|
|
435
|
-
logFile,
|
|
436
|
-
systemPrompt: resolvedSystemPrompt,
|
|
437
|
-
additionalArgs: opts.additionalArgs,
|
|
438
|
-
role,
|
|
439
|
-
apiUrl,
|
|
440
|
-
apiKey,
|
|
441
|
-
agentId,
|
|
442
|
-
sessionId,
|
|
443
|
-
iteration,
|
|
444
|
-
taskId: trigger.taskId,
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
state.activeTasks.set(runningTask.taskId, runningTask);
|
|
448
|
-
console.log(`[${role}] Started task ${runningTask.taskId} (${state.activeTasks.size}/${state.maxConcurrent} active)`);
|
|
449
|
-
}
|
|
450
|
-
} else {
|
|
451
|
-
console.log(`[${role}] At capacity (${state.activeTasks.size}/${state.maxConcurrent}), waiting for completion...`);
|
|
452
|
-
await Bun.sleep(1000);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
#### 4. Add Process Completion Handler
|
|
458
|
-
**File**: `src/commands/runner.ts`
|
|
459
|
-
|
|
460
|
-
**NOTE**: The original `Promise.race` pattern doesn't work because `Promise.resolve()` always wins the race even against already-resolved promises. Use Bun's native `process.exitCode` check instead:
|
|
461
|
-
|
|
462
|
-
```typescript
|
|
463
|
-
async function checkCompletedProcesses(state: RunnerState, role: string): Promise<void> {
|
|
464
|
-
const completedTasks: string[] = [];
|
|
465
|
-
|
|
466
|
-
for (const [taskId, task] of state.activeTasks) {
|
|
467
|
-
// Check if the Bun subprocess has exited (non-blocking)
|
|
468
|
-
if (task.process.exitCode !== null) {
|
|
469
|
-
console.log(`[${role}] Task ${taskId.slice(0, 8)} completed with exit code ${task.process.exitCode}`);
|
|
470
|
-
completedTasks.push(taskId);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// Remove completed tasks from the map
|
|
475
|
-
for (const taskId of completedTasks) {
|
|
476
|
-
state.activeTasks.delete(taskId);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
#### 5. Update Graceful Shutdown
|
|
482
|
-
**File**: `src/commands/runner.ts`
|
|
483
|
-
|
|
484
|
-
Modify `shutdown` function (around line 65):
|
|
485
|
-
|
|
486
|
-
```typescript
|
|
487
|
-
const shutdown = async (signal: string) => {
|
|
488
|
-
console.log(`\n[${role}] Received ${signal}, shutting down...`);
|
|
489
|
-
|
|
490
|
-
// Wait for active tasks with timeout
|
|
491
|
-
if (state && state.activeTasks.size > 0) {
|
|
492
|
-
console.log(`[${role}] Waiting for ${state.activeTasks.size} active tasks to complete (30s timeout)...`);
|
|
493
|
-
const deadline = Date.now() + 30000;
|
|
494
|
-
|
|
495
|
-
while (state.activeTasks.size > 0 && Date.now() < deadline) {
|
|
496
|
-
await checkCompletedProcesses(state, role);
|
|
497
|
-
if (state.activeTasks.size > 0) {
|
|
498
|
-
await Bun.sleep(500);
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
// Force kill remaining
|
|
503
|
-
for (const [taskId, task] of state.activeTasks) {
|
|
504
|
-
console.log(`[${role}] Force stopping task ${taskId}`);
|
|
505
|
-
task.process.kill("SIGTERM");
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
if (apiConfig) {
|
|
510
|
-
await closeAgent(apiConfig, role);
|
|
511
|
-
}
|
|
512
|
-
await savePm2State(role);
|
|
513
|
-
process.exit(0);
|
|
514
|
-
};
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
### Success Criteria:
|
|
518
|
-
|
|
519
|
-
#### Automated Verification:
|
|
520
|
-
- [x] Type checks pass
|
|
521
|
-
- [x] Existing tests pass: `bun test`
|
|
522
|
-
- [ ] New test: spawn agent with `MAX_CONCURRENT_TASKS=2`, assign 2 tasks, verify both run
|
|
523
|
-
|
|
524
|
-
#### Manual Verification:
|
|
525
|
-
- [ ] Start worker with `MAX_CONCURRENT_TASKS=3`
|
|
526
|
-
- [ ] Assign 3 tasks rapidly
|
|
527
|
-
- [ ] Verify 3 Claude processes are running simultaneously (`ps aux | grep claude`)
|
|
528
|
-
- [ ] Verify all 3 complete successfully
|
|
529
|
-
- [ ] Test graceful shutdown with active tasks
|
|
530
|
-
|
|
531
|
-
**Implementation Note**: After completing this phase and all automated verification passes, pause here for manual confirmation before proceeding to the next phase.
|
|
532
|
-
|
|
533
|
-
---
|
|
534
|
-
|
|
535
|
-
## Phase 4: API and Registration Updates
|
|
536
|
-
|
|
537
|
-
### Overview
|
|
538
|
-
Update HTTP endpoints and agent registration to support capacity configuration.
|
|
539
|
-
|
|
540
|
-
### Changes Required:
|
|
541
|
-
|
|
542
|
-
#### 1. Update Agent Registration
|
|
543
|
-
**File**: `src/http.ts`
|
|
544
|
-
|
|
545
|
-
In `POST /api/agents` handler (around line 280), accept `maxTasks`:
|
|
546
|
-
|
|
547
|
-
```typescript
|
|
548
|
-
const agent = createAgent({
|
|
549
|
-
id: agentId,
|
|
550
|
-
name: body.name,
|
|
551
|
-
isLead: body.isLead ?? false,
|
|
552
|
-
status: "idle",
|
|
553
|
-
description: body.description,
|
|
554
|
-
role: body.role,
|
|
555
|
-
capabilities: body.capabilities,
|
|
556
|
-
maxTasks: body.maxTasks ?? parseInt(process.env.MAX_CONCURRENT_TASKS || "1", 10),
|
|
557
|
-
});
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
#### 2. Include Capacity in Agent Responses
|
|
561
|
-
**File**: `src/http.ts`
|
|
562
|
-
|
|
563
|
-
Add capacity info to agent responses:
|
|
564
|
-
|
|
565
|
-
```typescript
|
|
566
|
-
function agentWithCapacity(agent: Agent) {
|
|
567
|
-
const activeCount = getActiveTaskCount(agent.id);
|
|
568
|
-
return {
|
|
569
|
-
...agent,
|
|
570
|
-
capacity: {
|
|
571
|
-
current: activeCount,
|
|
572
|
-
max: agent.maxTasks ?? 1,
|
|
573
|
-
available: Math.max(0, (agent.maxTasks ?? 1) - activeCount),
|
|
574
|
-
},
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
```
|
|
578
|
-
|
|
579
|
-
Apply this to `/me`, `GET /api/agents`, and poll responses.
|
|
580
|
-
|
|
581
|
-
#### 3. Update Runner Registration
|
|
582
|
-
**File**: `src/commands/runner.ts`
|
|
583
|
-
|
|
584
|
-
Update `registerAgent()` to send `maxTasks`:
|
|
585
|
-
|
|
586
|
-
```typescript
|
|
587
|
-
await registerAgent({
|
|
588
|
-
apiUrl,
|
|
589
|
-
apiKey,
|
|
590
|
-
agentId,
|
|
591
|
-
name: agentName,
|
|
592
|
-
isLead: role === "lead",
|
|
593
|
-
capabilities: config.capabilities,
|
|
594
|
-
maxTasks: parseInt(process.env.MAX_CONCURRENT_TASKS || "1", 10),
|
|
595
|
-
});
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
### Success Criteria:
|
|
599
|
-
|
|
600
|
-
#### Automated Verification:
|
|
601
|
-
- [x] API tests pass: `bun test src/tests/rest-api.test.ts`
|
|
602
|
-
- [x] Agent registration includes `maxTasks`
|
|
603
|
-
|
|
604
|
-
#### Manual Verification:
|
|
605
|
-
- [ ] `GET /me` response includes `capacity` object
|
|
606
|
-
- [ ] Start agent with `MAX_CONCURRENT_TASKS=5`, verify API shows `max: 5`
|
|
607
|
-
|
|
608
|
-
**Implementation Note**: After completing this phase and all automated verification passes, pause here for manual confirmation before proceeding to the next phase.
|
|
609
|
-
|
|
610
|
-
---
|
|
611
|
-
|
|
612
|
-
## Phase 5: Integration Testing
|
|
613
|
-
|
|
614
|
-
### Overview
|
|
615
|
-
Comprehensive end-to-end testing of the concurrency feature.
|
|
616
|
-
|
|
617
|
-
### Test Cases:
|
|
618
|
-
|
|
619
|
-
1. **Backwards Compatibility**
|
|
620
|
-
- Start agent without `MAX_CONCURRENT_TASKS` env var
|
|
621
|
-
- Verify default `maxTasks = 1`
|
|
622
|
-
- Verify sequential execution (only 1 Claude at a time)
|
|
623
|
-
|
|
624
|
-
2. **Concurrent Execution**
|
|
625
|
-
- Start worker with `MAX_CONCURRENT_TASKS=3`
|
|
626
|
-
- Assign 5 tasks rapidly
|
|
627
|
-
- Verify 3 Claude processes running
|
|
628
|
-
- Verify 2 tasks queued in `pending`
|
|
629
|
-
- As tasks complete, queued tasks start
|
|
630
|
-
|
|
631
|
-
3. **Capacity Enforcement**
|
|
632
|
-
- Agent at capacity
|
|
633
|
-
- Try to assign directly -> should get capacity error
|
|
634
|
-
- Offer mode should still work
|
|
635
|
-
|
|
636
|
-
4. **Graceful Shutdown**
|
|
637
|
-
- Start 3 concurrent tasks
|
|
638
|
-
- Send SIGTERM
|
|
639
|
-
- Verify tasks complete before exit (up to 30s)
|
|
640
|
-
|
|
641
|
-
5. **Status Accuracy**
|
|
642
|
-
- Agent with 2/3 tasks running -> `status: busy`
|
|
643
|
-
- All tasks complete -> `status: idle`
|
|
644
|
-
- New task starts -> `status: busy`
|
|
645
|
-
|
|
646
|
-
### Success Criteria:
|
|
647
|
-
|
|
648
|
-
#### Automated Verification:
|
|
649
|
-
- [x] All unit tests pass: `bun test`
|
|
650
|
-
- [x] New integration test file passes: `bun test src/tests/concurrency.test.ts`
|
|
651
|
-
|
|
652
|
-
#### Manual Verification:
|
|
653
|
-
- [ ] Run through all 5 test cases above
|
|
654
|
-
- [ ] Monitor with `ps aux | grep claude` to verify concurrent processes
|
|
655
|
-
- [ ] Check UI shows correct capacity info
|
|
656
|
-
|
|
657
|
-
---
|
|
658
|
-
|
|
659
|
-
## Testing Strategy
|
|
660
|
-
|
|
661
|
-
### Unit Tests:
|
|
662
|
-
- `getActiveTaskCount()` returns correct count
|
|
663
|
-
- `hasCapacity()` returns true/false correctly
|
|
664
|
-
- `updateAgentStatusFromCapacity()` sets correct status
|
|
665
|
-
- `send-task` rejects at capacity, allows with capacity
|
|
666
|
-
|
|
667
|
-
### Integration Tests:
|
|
668
|
-
- Full flow: register -> assign tasks -> complete -> verify status
|
|
669
|
-
- Concurrent spawn verification
|
|
670
|
-
- Graceful shutdown with active tasks
|
|
671
|
-
|
|
672
|
-
### Manual Testing Steps:
|
|
673
|
-
1. Start swarm server: `bun run src/server.ts`
|
|
674
|
-
2. Start worker with concurrency: `MAX_CONCURRENT_TASKS=3 bun run src/cli.tsx worker`
|
|
675
|
-
3. Send 5 tasks via API or lead agent
|
|
676
|
-
4. Watch console output for concurrent spawn logs
|
|
677
|
-
5. Verify with `ps aux | grep claude` shows 3 processes
|
|
678
|
-
6. Wait for completion, verify all tasks marked complete
|
|
679
|
-
|
|
680
|
-
## Configuration Summary
|
|
681
|
-
|
|
682
|
-
| Variable | Default | Description |
|
|
683
|
-
|----------|---------|-------------|
|
|
684
|
-
| `MAX_CONCURRENT_TASKS` | 1 | Maximum concurrent Claude subprocesses per agent |
|
|
685
|
-
| `SHUTDOWN_TIMEOUT` | 30000 | Milliseconds to wait for tasks on shutdown |
|
|
686
|
-
|
|
687
|
-
## References
|
|
688
|
-
|
|
689
|
-
- Existing runner architecture: `thoughts/shared/research/2025-12-22-runner-loop-architecture.md`
|
|
690
|
-
- Runner-level polling plan: `thoughts/shared/plans/2025-12-23-runner-level-polling.md`
|
|
691
|
-
- Current implementation: `src/commands/runner.ts:573-661`
|