@desplega.ai/agent-swarm 1.10.3 → 1.20.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/.claude/settings.local.json +14 -1
- package/.env.docker.example +6 -0
- package/.env.example +14 -0
- package/.github/workflows/ci.yml +76 -0
- package/.github/workflows/{docker-publish.yml → docker-and-deploy.yml} +26 -1
- package/.wts-config.json +4 -0
- package/.wts-setup.ts +102 -0
- package/CLAUDE.md +81 -88
- package/DEPLOYMENT.md +228 -14
- package/Dockerfile +6 -3
- package/Dockerfile.worker +21 -4
- package/MCP.md +158 -1
- package/README.md +83 -0
- package/assets/agent-swarm.mp4 +0 -0
- package/biome.json +4 -1
- package/deploy/prod-db.ts +1 -1
- package/docker-compose.example.yml +25 -2
- package/docker-entrypoint.sh +71 -0
- package/ecosystem.config.cjs +66 -0
- package/package.json +12 -3
- package/plugin/commands/close-issue.md +86 -0
- package/plugin/commands/create-pr.md +93 -0
- package/plugin/commands/implement-issue.md +131 -0
- package/plugin/commands/investigate-sentry-issue.md +138 -0
- package/plugin/commands/respond-github.md +94 -0
- package/plugin/commands/review-pr.md +227 -0
- package/plugin/commands/start-leader.md +32 -12
- package/plugin/commands/swarm-chat.md +4 -0
- package/plugin/commands/work-on-task.md +12 -3
- package/pyproject.toml +9 -0
- package/scripts/generate-mcp-docs.ts +4 -4
- package/slack-manifest.json +2 -0
- package/src/be/db.ts +2335 -176
- package/src/claude.ts +8 -8
- package/src/commands/runner.ts +1128 -93
- package/src/github/app.ts +231 -0
- package/src/github/handlers.ts +918 -0
- package/src/github/index.ts +31 -0
- package/src/github/mentions.test.ts +104 -0
- package/src/github/mentions.ts +30 -0
- package/src/github/reactions.ts +153 -0
- package/src/github/types.ts +156 -0
- package/src/hooks/hook.ts +314 -5
- package/src/http.ts +1134 -86
- package/src/prompts/base-prompt.ts +168 -17
- package/src/scheduler/index.ts +1 -0
- package/src/scheduler/scheduler.test.ts +149 -0
- package/src/scheduler/scheduler.ts +164 -0
- package/src/server.ts +62 -2
- package/src/slack/files.ts +302 -0
- package/src/slack/handlers.test.ts +165 -0
- package/src/slack/handlers.ts +158 -5
- package/src/slack/index.ts +15 -0
- package/src/slack/responses.ts +10 -2
- package/src/tests/concurrency.test.ts +213 -0
- package/src/tests/db-capacity.test.ts +212 -0
- package/src/tests/epics.test.ts +370 -0
- package/src/tests/generate-default-claude-md.test.ts +90 -0
- package/src/tests/get-inbox-message.test.ts +145 -0
- package/src/tests/rest-api.test.ts +633 -0
- package/src/tests/runner-polling-api.test.ts +84 -12
- package/src/tests/scheduled-tasks-api.test.ts +352 -0
- package/src/tests/scheduled-tasks.test.ts +501 -0
- package/src/tests/session-costs.test.ts +725 -0
- package/src/tests/store-progress-cost.test.ts +209 -0
- package/src/tests/task-cancellation.test.ts +511 -0
- package/src/tests/task-pause-resume.test.ts +737 -0
- package/src/tests/trigger-claiming.test.ts +631 -0
- package/src/tests/update-profile-api.test.ts +561 -0
- package/src/tools/cancel-task.ts +111 -0
- package/src/tools/create-channel.ts +1 -0
- package/src/tools/epics/assign-task-to-epic.ts +128 -0
- package/src/tools/epics/create-epic.ts +111 -0
- package/src/tools/epics/delete-epic.ts +119 -0
- package/src/tools/epics/get-epic-details.ts +90 -0
- package/src/tools/epics/index.ts +7 -0
- package/src/tools/epics/list-epics.ts +83 -0
- package/src/tools/epics/unassign-task-from-epic.ts +108 -0
- package/src/tools/epics/update-epic.ts +171 -0
- package/src/tools/get-inbox-message.ts +89 -0
- package/src/tools/get-swarm.ts +1 -0
- package/src/tools/get-task-details.ts +1 -0
- package/src/tools/get-tasks.ts +10 -1
- package/src/tools/inbox-delegate.ts +113 -0
- package/src/tools/join-swarm.ts +24 -11
- package/src/tools/list-channels.ts +1 -0
- package/src/tools/list-services.ts +1 -0
- package/src/tools/my-agent-info.ts +3 -0
- package/src/tools/poll-task.ts +42 -3
- package/src/tools/post-message.ts +1 -0
- package/src/tools/read-messages.ts +4 -0
- package/src/tools/register-service.ts +1 -0
- package/src/tools/schedules/create-schedule.ts +226 -0
- package/src/tools/schedules/delete-schedule.ts +125 -0
- package/src/tools/schedules/index.ts +5 -0
- package/src/tools/schedules/list-schedules.ts +104 -0
- package/src/tools/schedules/run-schedule-now.ts +123 -0
- package/src/tools/schedules/update-schedule.ts +243 -0
- package/src/tools/send-task.ts +39 -8
- package/src/tools/slack-download-file.ts +174 -0
- package/src/tools/slack-list-channels.ts +168 -0
- package/src/tools/slack-post.ts +103 -0
- package/src/tools/slack-read.ts +385 -0
- package/src/tools/slack-reply.ts +142 -0
- package/src/tools/slack-upload-file.ts +376 -0
- package/src/tools/store-progress.ts +44 -6
- package/src/tools/task-action.ts +92 -2
- package/src/tools/unregister-service.ts +1 -0
- package/src/tools/update-profile.ts +45 -8
- package/src/tools/update-service-status.ts +1 -0
- package/src/types.ts +169 -1
- package/thoughts/shared/plans/2025-12-23-worker-lead-spawn-triggers.md +568 -0
- package/thoughts/shared/plans/{2025-12-18-inverse-teleport.md → 2026-01-09-inverse-teleport.md} +562 -188
- package/thoughts/shared/plans/2026-01-12-agent-rename-pm2-control.md +1133 -0
- package/thoughts/shared/plans/2026-01-12-github-app-integration.md +380 -0
- package/thoughts/shared/plans/2026-01-12-lead-inbox-model.md +876 -0
- package/thoughts/shared/plans/2026-01-12-ralph-wiggum-integration.md +463 -0
- package/thoughts/shared/plans/2026-01-13-agent-concurrency.md +691 -0
- package/thoughts/shared/plans/2026-01-13-github-assignment-handling.md +690 -0
- package/thoughts/shared/plans/2026-01-13-prevent-duplicate-trigger-processing.md +1071 -0
- package/thoughts/shared/plans/2026-01-14-fix-slack-thread-context.md +507 -0
- package/thoughts/shared/plans/2026-01-15-scheduled-tasks-implementation.md +565 -0
- package/thoughts/shared/plans/2026-01-15-usage-cost-tracking-ui.md +1479 -0
- package/thoughts/shared/plans/2026-01-16-epics-feature-implementation.md +1230 -0
- package/thoughts/shared/research/2025-01-09-inverse-teleport-plan-review.md +420 -0
- package/thoughts/shared/research/2026-01-13-lead-duplicate-trigger-processing.md +223 -0
- package/thoughts/shared/research/2026-01-14-lead-slack-thread-context.md +277 -0
- package/thoughts/shared/research/2026-01-15-ai-tracker-agent-swarm-integration.md +376 -0
- package/thoughts/shared/research/2026-01-15-auto-starting-processes-in-worker-containers.md +787 -0
- package/thoughts/shared/research/2026-01-15-scheduled-tasks.md +390 -0
- package/thoughts/shared/research/2026-01-16-epics-feature-research.md +437 -0
- package/thoughts/taras/plans/2026-01-22-agent-swarm-schemas.md +98 -0
- package/thoughts/taras/plans/2026-01-28-per-worker-claude-md.md +617 -0
- package/thoughts/taras/plans/2026-01-28-sentry-cli-integration.md +214 -0
- package/thoughts/taras/research/2026-01-22-vercel-cli-integration.md +287 -0
- package/thoughts/taras/research/2026-01-27-excessive-polling-issue.md +311 -0
- package/thoughts/taras/research/2026-01-28-per-worker-claude-md.md +383 -0
- package/thoughts/taras/research/2026-01-28-sentry-cli-integration.md +240 -0
- package/tsconfig.json +1 -1
- package/ui/CLAUDE.md +49 -0
- package/ui/bun.lock +81 -2
- package/ui/package-lock.json +5290 -0
- package/ui/package.json +1 -0
- package/ui/pnpm-lock.yaml +307 -0
- package/ui/src/App.tsx +25 -5
- package/ui/src/components/ActivityFeed.tsx +121 -96
- package/ui/src/components/AgentDetailPanel.tsx +243 -44
- package/ui/src/components/AgentsPanel.tsx +328 -62
- package/ui/src/components/ChatPanel.tsx +236 -136
- package/ui/src/components/ConfigModal.tsx +31 -10
- package/ui/src/components/Dashboard.tsx +324 -26
- package/ui/src/components/EditAgentProfileModal.tsx +433 -0
- package/ui/src/components/EpicDetailPage.tsx +741 -0
- package/ui/src/components/EpicsPanel.tsx +566 -0
- package/ui/src/components/Header.tsx +4 -12
- package/ui/src/components/JsonViewer.tsx +171 -0
- package/ui/src/components/ScheduledTaskDetailPanel.tsx +517 -0
- package/ui/src/components/ScheduledTasksPanel.tsx +639 -0
- package/ui/src/components/ServicesPanel.tsx +20 -10
- package/ui/src/components/SessionLogPanel.tsx +928 -142
- package/ui/src/components/StatsBar.tsx +58 -25
- package/ui/src/components/StatusBadge.tsx +48 -4
- package/ui/src/components/TaskDetailPanel.tsx +150 -74
- package/ui/src/components/TasksPanel.tsx +76 -37
- package/ui/src/components/UsageCharts.tsx +216 -0
- package/ui/src/components/UsageTab.tsx +394 -0
- package/ui/src/hooks/queries.ts +179 -5
- package/ui/src/hooks/useAutoScroll.ts +37 -9
- package/ui/src/index.css +60 -38
- package/ui/src/lib/api.ts +109 -12
- package/ui/src/lib/contentPreview.ts +208 -0
- package/ui/src/lib/theme.ts +24 -24
- package/ui/src/lib/utils.ts +41 -1
- package/ui/src/main.tsx +5 -9
- package/ui/src/types/api.ts +145 -1
- package/ui/tailwind.config.js +3 -1
- package/ui/vite.config.ts +20 -7
- package/plugin/.claude-plugin/plugin.json +0 -13
- package/plugin/commands/create-plan.md +0 -415
- package/plugin/commands/implement-plan.md +0 -89
- package/plugin/commands/research.md +0 -200
|
@@ -24,7 +24,20 @@
|
|
|
24
24
|
"WebFetch(domain:geminicli.com)",
|
|
25
25
|
"Bash(bun run docs:mcp:*)",
|
|
26
26
|
"Bash(bun test:*)",
|
|
27
|
-
"Bash(curl:*)"
|
|
27
|
+
"Bash(curl:*)",
|
|
28
|
+
"WebFetch(domain:github.com)",
|
|
29
|
+
"Bash(gh pr checks:*)",
|
|
30
|
+
"Bash(gh run view:*)",
|
|
31
|
+
"Bash(timeout 5 bun run:*)",
|
|
32
|
+
"Bash(bun run typecheck:*)",
|
|
33
|
+
"Bash(npx tsc:*)",
|
|
34
|
+
"WebFetch(domain:docs.github.com)",
|
|
35
|
+
"Bash(bun run lint:fix:*)",
|
|
36
|
+
"Skill(desplega:research)",
|
|
37
|
+
"Bash(bun run check:*)",
|
|
38
|
+
"Bash(bun build:*)",
|
|
39
|
+
"WebFetch(domain:www.npmjs.com)",
|
|
40
|
+
"Bash(sentry-cli:*)"
|
|
28
41
|
]
|
|
29
42
|
},
|
|
30
43
|
"enableAllProjectMcpServers": true,
|
package/.env.docker.example
CHANGED
|
@@ -31,3 +31,9 @@ SYSTEM_PROMPT_FILE=
|
|
|
31
31
|
|
|
32
32
|
# For the agent exposed services (optional)
|
|
33
33
|
SWARM_URL=swarm.example.com
|
|
34
|
+
|
|
35
|
+
# Sentry Integration (optional - for issue investigation)
|
|
36
|
+
# Create an Organization Auth Token at https://sentry.io/settings/{org}/auth-tokens/
|
|
37
|
+
# Required scopes: event:read, project:read, org:read
|
|
38
|
+
SENTRY_AUTH_TOKEN=
|
|
39
|
+
SENTRY_ORG=
|
package/.env.example
CHANGED
|
@@ -19,8 +19,22 @@ SLACK_APP_TOKEN=xapp-... # App-Level Token (for Socket Mode)
|
|
|
19
19
|
SLACK_SIGNING_SECRET=... # Signing Secret (optional for Socket Mode)
|
|
20
20
|
SLACK_DISABLE=true # Set to "true" to disable Slack integration
|
|
21
21
|
|
|
22
|
+
# Slack User Filtering (optional - leave empty to allow all users)
|
|
23
|
+
# SLACK_ALLOWED_EMAIL_DOMAINS=desplega.ai,partner.com # Comma-separated email domains
|
|
24
|
+
# SLACK_ALLOWED_USER_IDS=U12345678,U87654321 # Comma-separated Slack user IDs to always allow
|
|
25
|
+
|
|
22
26
|
# App URL for Slack message links (e.g., https://your-dashboard.com)
|
|
23
27
|
APP_URL=
|
|
24
28
|
|
|
25
29
|
# Environment mode - set to "development" to add (dev) prefix to agent names in Slack
|
|
26
30
|
ENV=
|
|
31
|
+
|
|
32
|
+
# GitHub App Integration (optional)
|
|
33
|
+
# GITHUB_DISABLE=true # Set to skip GitHub integration
|
|
34
|
+
GITHUB_WEBHOOK_SECRET= # Webhook secret from GitHub App settings
|
|
35
|
+
GITHUB_BOT_NAME=agent-swarm-bot # Bot name for @mentions (default: agent-swarm-bot)
|
|
36
|
+
GITHUB_APP_ID= # GitHub App ID (from app settings)
|
|
37
|
+
GITHUB_APP_PRIVATE_KEY= # Private key: raw PEM with \n escapes, OR base64-encoded
|
|
38
|
+
|
|
39
|
+
# Scheduler configuration
|
|
40
|
+
SCHEDULER_INTERVAL_MS=10000 # Polling interval for scheduled tasks (default: 10 seconds)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
lint-and-typecheck:
|
|
14
|
+
name: Lint and Type Check
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Setup Bun
|
|
22
|
+
uses: oven-sh/setup-bun@v2
|
|
23
|
+
with:
|
|
24
|
+
bun-version: latest
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: bun install --frozen-lockfile
|
|
28
|
+
|
|
29
|
+
- name: Run Biome linter
|
|
30
|
+
run: bun run lint
|
|
31
|
+
|
|
32
|
+
- name: Run TypeScript type check
|
|
33
|
+
run: bun run tsc:check
|
|
34
|
+
|
|
35
|
+
test:
|
|
36
|
+
name: Run Tests
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
|
|
39
|
+
steps:
|
|
40
|
+
- name: Checkout repository
|
|
41
|
+
uses: actions/checkout@v4
|
|
42
|
+
|
|
43
|
+
- name: Setup Bun
|
|
44
|
+
uses: oven-sh/setup-bun@v2
|
|
45
|
+
with:
|
|
46
|
+
bun-version: latest
|
|
47
|
+
|
|
48
|
+
- name: Install dependencies
|
|
49
|
+
run: bun install --frozen-lockfile
|
|
50
|
+
|
|
51
|
+
- name: Run tests
|
|
52
|
+
run: bun test
|
|
53
|
+
|
|
54
|
+
docker-build:
|
|
55
|
+
name: Docker Build Test
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
if: github.event_name == 'pull_request'
|
|
58
|
+
|
|
59
|
+
strategy:
|
|
60
|
+
matrix:
|
|
61
|
+
dockerfile: [Dockerfile, Dockerfile.worker]
|
|
62
|
+
|
|
63
|
+
steps:
|
|
64
|
+
- name: Checkout repository
|
|
65
|
+
uses: actions/checkout@v4
|
|
66
|
+
|
|
67
|
+
- name: Set up Docker Buildx
|
|
68
|
+
uses: docker/setup-buildx-action@v3
|
|
69
|
+
|
|
70
|
+
- name: Build Docker image
|
|
71
|
+
uses: docker/build-push-action@v5
|
|
72
|
+
with:
|
|
73
|
+
context: .
|
|
74
|
+
file: ./${{ matrix.dockerfile }}
|
|
75
|
+
push: false
|
|
76
|
+
tags: test-image:latest
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name: Docker Build
|
|
1
|
+
name: Docker Build + Publish + Deploy
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
@@ -50,6 +50,7 @@ jobs:
|
|
|
50
50
|
push: true
|
|
51
51
|
tags: ${{ steps.meta.outputs.tags }}
|
|
52
52
|
labels: ${{ steps.meta.outputs.labels }}
|
|
53
|
+
no-cache: true
|
|
53
54
|
|
|
54
55
|
build-and-push-worker:
|
|
55
56
|
runs-on: ubuntu-latest
|
|
@@ -90,3 +91,27 @@ jobs:
|
|
|
90
91
|
push: true
|
|
91
92
|
tags: ${{ steps.meta.outputs.tags }}
|
|
92
93
|
labels: ${{ steps.meta.outputs.labels }}
|
|
94
|
+
no-cache: true
|
|
95
|
+
|
|
96
|
+
deploy:
|
|
97
|
+
name: Deploy
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
|
|
100
|
+
needs:
|
|
101
|
+
- build-and-push-server
|
|
102
|
+
- build-and-push-worker
|
|
103
|
+
|
|
104
|
+
steps:
|
|
105
|
+
- name: Checkout
|
|
106
|
+
id: checkout
|
|
107
|
+
uses: actions/checkout@v4
|
|
108
|
+
|
|
109
|
+
- name: Deploy Agent Swarm
|
|
110
|
+
uses: tarasyarema/dokploy-deploy-action@main
|
|
111
|
+
with:
|
|
112
|
+
deployment_type: compose
|
|
113
|
+
compose_id: h4or-knfw2HWkTzjLmrn8
|
|
114
|
+
compose_name: agent-swarm-nrz8v0
|
|
115
|
+
dokploy_url: https://app.dokploy.com
|
|
116
|
+
auth_token: ${{ secrets.DOKPLOY_TOKEN }}
|
|
117
|
+
wait_for_completion: true
|
package/.wts-config.json
ADDED
package/.wts-setup.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// wts setup script - runs after worktree creation
|
|
3
|
+
//
|
|
4
|
+
// Environment variables:
|
|
5
|
+
// WTS_WORKTREE_PATH - path to the new worktree (also the working directory)
|
|
6
|
+
// WTS_GIT_ROOT - path to the main repository root
|
|
7
|
+
|
|
8
|
+
import { exists, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
9
|
+
import { join, basename } from "node:path";
|
|
10
|
+
|
|
11
|
+
const worktreePath = process.env.WTS_WORKTREE_PATH!;
|
|
12
|
+
const gitRoot = process.env.WTS_GIT_ROOT!;
|
|
13
|
+
const worktreeName = basename(worktreePath);
|
|
14
|
+
|
|
15
|
+
console.log(`Setting up worktree "${worktreeName}" at ${worktreePath}...`);
|
|
16
|
+
|
|
17
|
+
// Generate a unique port based on worktree index
|
|
18
|
+
// Main repo uses 3013, worktrees use 3014+
|
|
19
|
+
async function getUniquePort(): Promise<number> {
|
|
20
|
+
const basePort = 3013;
|
|
21
|
+
try {
|
|
22
|
+
// Count existing worktrees to determine port offset
|
|
23
|
+
const worktreesDir = join(gitRoot, ".worktrees");
|
|
24
|
+
if (await exists(worktreesDir)) {
|
|
25
|
+
const worktrees = await readdir(worktreesDir);
|
|
26
|
+
return basePort + worktrees.length;
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
// Fallback: use a hash of the worktree name
|
|
30
|
+
let hash = 0;
|
|
31
|
+
for (const char of worktreeName) {
|
|
32
|
+
hash = ((hash << 5) - hash + char.charCodeAt(0)) | 0;
|
|
33
|
+
}
|
|
34
|
+
return basePort + 1 + (Math.abs(hash) % 100);
|
|
35
|
+
}
|
|
36
|
+
return basePort + 1;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const port = await getUniquePort();
|
|
40
|
+
console.log(`Using port ${port} for this worktree`);
|
|
41
|
+
|
|
42
|
+
// --- Copy and configure .env ---
|
|
43
|
+
const mainEnv = join(gitRoot, ".env");
|
|
44
|
+
const envExample = join(worktreePath, ".env.example");
|
|
45
|
+
const targetEnv = join(worktreePath, ".env");
|
|
46
|
+
|
|
47
|
+
if (await exists(mainEnv)) {
|
|
48
|
+
console.log("Copying .env from main repo...");
|
|
49
|
+
let envContent = await readFile(mainEnv, "utf-8");
|
|
50
|
+
// Update PORT to the unique port
|
|
51
|
+
envContent = envContent.replace(/^PORT=\d+/m, `PORT=${port}`);
|
|
52
|
+
await writeFile(targetEnv, envContent);
|
|
53
|
+
} else if (await exists(envExample)) {
|
|
54
|
+
console.log("Creating .env from .env.example...");
|
|
55
|
+
let envContent = await readFile(envExample, "utf-8");
|
|
56
|
+
envContent = envContent.replace(/^PORT=\d+/m, `PORT=${port}`);
|
|
57
|
+
await writeFile(targetEnv, envContent);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// --- Copy and configure .mcp.json ---
|
|
61
|
+
const mainMcp = join(gitRoot, ".mcp.json");
|
|
62
|
+
const targetMcp = join(worktreePath, ".mcp.json");
|
|
63
|
+
|
|
64
|
+
if (await exists(mainMcp)) {
|
|
65
|
+
console.log("Copying .mcp.json with updated port...");
|
|
66
|
+
let mcpContent = await readFile(mainMcp, "utf-8");
|
|
67
|
+
// Update the port in the MCP URL
|
|
68
|
+
mcpContent = mcpContent.replace(/localhost:\d+/g, `localhost:${port}`);
|
|
69
|
+
await writeFile(targetMcp, mcpContent);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// --- Copy .claude directory ---
|
|
73
|
+
const mainClaude = join(gitRoot, ".claude");
|
|
74
|
+
const targetClaude = join(worktreePath, ".claude");
|
|
75
|
+
|
|
76
|
+
if (await exists(mainClaude)) {
|
|
77
|
+
console.log("Copying .claude directory...");
|
|
78
|
+
await mkdir(targetClaude, { recursive: true });
|
|
79
|
+
const files = await readdir(mainClaude);
|
|
80
|
+
for (const file of files) {
|
|
81
|
+
const content = await readFile(join(mainClaude, file));
|
|
82
|
+
await writeFile(join(targetClaude, file), content);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// --- Copy docker env files if they exist ---
|
|
87
|
+
const dockerEnvFiles = [".env.docker", ".env.docker-lead"];
|
|
88
|
+
for (const envFile of dockerEnvFiles) {
|
|
89
|
+
const mainDockerEnv = join(gitRoot, envFile);
|
|
90
|
+
const targetDockerEnv = join(worktreePath, envFile);
|
|
91
|
+
if (await exists(mainDockerEnv)) {
|
|
92
|
+
console.log(`Copying ${envFile}...`);
|
|
93
|
+
await Bun.$`cp ${mainDockerEnv} ${targetDockerEnv}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// --- Install dependencies ---
|
|
98
|
+
console.log("Installing dependencies...");
|
|
99
|
+
await Bun.$`bun install`;
|
|
100
|
+
|
|
101
|
+
console.log(`\nSetup complete! Worktree running on port ${port}`);
|
|
102
|
+
console.log(`Start the server with: bun run dev:http`);
|
package/CLAUDE.md
CHANGED
|
@@ -1,111 +1,104 @@
|
|
|
1
|
-
|
|
2
|
-
description: Use Bun instead of Node.js, npm, pnpm, or vite.
|
|
3
|
-
globs: "*.ts, *.tsx, *.html, *.css, *.js, *.jsx, package.json"
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
1
|
+
# Agent Swarm MCP
|
|
6
2
|
|
|
7
|
-
|
|
3
|
+
Multi-agent orchestration layer for Claude Code, Codex, Gemini CLI. Enables task distribution, agent communication, and service discovery.
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
- Use `bun test` instead of `jest` or `vitest`
|
|
11
|
-
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
|
|
12
|
-
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
|
|
13
|
-
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
|
|
14
|
-
- Bun automatically loads .env, so don't use dotenv.
|
|
5
|
+
**Getting Started**: See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup. Run `bun run start:http` to start the server.
|
|
15
6
|
|
|
16
|
-
|
|
7
|
+
**Database**: Uses `bun:sqlite` (SQLite with WAL mode). DB file at `./agent-swarm-db.sqlite` (auto-created). Schema defined in `src/be/db.ts`.
|
|
17
8
|
|
|
18
|
-
|
|
19
|
-
- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
|
|
20
|
-
- `Bun.redis` for Redis. Don't use `ioredis`.
|
|
21
|
-
- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
|
|
22
|
-
- `WebSocket` is built-in. Don't use `ws`.
|
|
23
|
-
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
|
|
24
|
-
- Bun.$`ls` instead of execa.
|
|
9
|
+
## Quick Reference
|
|
25
10
|
|
|
26
|
-
|
|
11
|
+
```bash
|
|
12
|
+
bun install # Install dependencies
|
|
13
|
+
bun run start:http # Run MCP HTTP server (port 3013)
|
|
14
|
+
bun run dev:http # Dev with hot reload
|
|
15
|
+
bun run lint:fix # Lint & format with Biome
|
|
16
|
+
bun run tsc:check # Type check
|
|
27
17
|
|
|
28
|
-
|
|
18
|
+
# PM2 (run API + UI + lead + worker together)
|
|
19
|
+
bun run pm2-start # Start all (API :3013, UI :5274, lead :3201, worker :3202)
|
|
20
|
+
bun run pm2-stop # Stop all services
|
|
21
|
+
bun run pm2-restart # Restart all services
|
|
22
|
+
bun run pm2-logs # View logs
|
|
23
|
+
bun run pm2-status # Check status
|
|
24
|
+
# Note: lead/worker run in Docker. On code changes:
|
|
25
|
+
# bun run docker:build:worker && bun run pm2-restart
|
|
26
|
+
```
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
import { test, expect } from "bun:test";
|
|
28
|
+
## Tech Stack
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
- **Runtime**: Bun (not Node.js) - see Bun rules below
|
|
31
|
+
- **Language**: TypeScript (strict mode)
|
|
32
|
+
- **Linter/Formatter**: Biome (2-space indent, double quotes, 100 line width)
|
|
33
|
+
- **MCP SDK**: @modelcontextprotocol/sdk
|
|
34
|
+
- **CLI**: Ink (React for terminal)
|
|
35
|
+
- **Slack**: @slack/bolt
|
|
37
36
|
|
|
38
|
-
##
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"/api/users/:id": {
|
|
51
|
-
GET: (req) => {
|
|
52
|
-
return new Response(JSON.stringify({ id: req.params.id }));
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
// optional websocket support
|
|
57
|
-
websocket: {
|
|
58
|
-
open: (ws) => {
|
|
59
|
-
ws.send("Hello, world!");
|
|
60
|
-
},
|
|
61
|
-
message: (ws, message) => {
|
|
62
|
-
ws.send(message);
|
|
63
|
-
},
|
|
64
|
-
close: (ws) => {
|
|
65
|
-
// handle close
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
development: {
|
|
69
|
-
hmr: true,
|
|
70
|
-
console: true,
|
|
71
|
-
}
|
|
72
|
-
})
|
|
37
|
+
## Project Structure
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
src/
|
|
41
|
+
http.ts # Main HTTP server + MCP endpoints
|
|
42
|
+
stdio.ts # Stdio MCP transport
|
|
43
|
+
cli.tsx # CLI entry point (Ink)
|
|
44
|
+
tools/ # MCP tool definitions
|
|
45
|
+
be/ # Backend utilities (DB, storage)
|
|
46
|
+
github/ # GitHub webhook handlers
|
|
47
|
+
slack/ # Slack integration
|
|
48
|
+
ui/ # Dashboard (separate React app)
|
|
73
49
|
```
|
|
74
50
|
|
|
75
|
-
|
|
51
|
+
## Code Style
|
|
76
52
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
<script type="module" src="./frontend.tsx"></script>
|
|
82
|
-
</body>
|
|
83
|
-
</html>
|
|
84
|
-
```
|
|
53
|
+
- Run `bun run lint:fix` before committing (lint + format)
|
|
54
|
+
- Run `bun run format` for formatting only
|
|
55
|
+
- Use Bun APIs, not Node.js equivalents
|
|
56
|
+
- Prefer `Bun.$` over execa for shell commands
|
|
85
57
|
|
|
86
|
-
|
|
58
|
+
## Related
|
|
87
59
|
|
|
88
|
-
|
|
89
|
-
|
|
60
|
+
- [UI Dashboard](./ui/CLAUDE.md) - React monitoring dashboard
|
|
61
|
+
- [MCP.md](./MCP.md) - MCP tools reference
|
|
62
|
+
- [DEPLOYMENT.md](./DEPLOYMENT.md) - Production deployment
|
|
63
|
+
- [CONTRIBUTING.md](./CONTRIBUTING.md) - Development setup
|
|
90
64
|
|
|
91
|
-
|
|
92
|
-
import './index.css';
|
|
65
|
+
---
|
|
93
66
|
|
|
94
|
-
|
|
67
|
+
## Local Development
|
|
95
68
|
|
|
96
|
-
|
|
69
|
+
**Environment Files:**
|
|
70
|
+
- `.env` - Local dev config (API server, Slack, GitHub)
|
|
71
|
+
- `.env.docker` - Docker worker config
|
|
97
72
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
73
|
+
**Testing API locally:**
|
|
74
|
+
```bash
|
|
75
|
+
# API_KEY from .env (default: 123123)
|
|
76
|
+
curl -H "Authorization: Bearer 123123" http://localhost:3013/api/agents
|
|
101
77
|
|
|
102
|
-
|
|
78
|
+
# With agent ID header for MCP tools
|
|
79
|
+
curl -H "Authorization: Bearer 123123" -H "X-Agent-ID: <uuid>" http://localhost:3013/mcp
|
|
103
80
|
```
|
|
104
81
|
|
|
105
|
-
|
|
82
|
+
**Key env vars:**
|
|
83
|
+
- `API_KEY` - Auth token for API requests
|
|
84
|
+
- `MCP_BASE_URL` - API server URL (default: http://localhost:3013)
|
|
85
|
+
- `SLACK_DISABLE=true` / `GITHUB_DISABLE=true` - Disable integrations locally
|
|
106
86
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Bun Rules
|
|
90
|
+
|
|
91
|
+
Use Bun instead of Node.js, npm, pnpm, or vite.
|
|
92
|
+
|
|
93
|
+
- `bun <file>` instead of `node` or `ts-node`
|
|
94
|
+
- `bun test` instead of jest/vitest
|
|
95
|
+
- `bun install` instead of npm/yarn/pnpm install
|
|
96
|
+
- `bun run <script>` instead of npm/yarn run
|
|
97
|
+
- Bun auto-loads .env - don't use dotenv
|
|
98
|
+
|
|
99
|
+
### Bun APIs
|
|
110
100
|
|
|
111
|
-
|
|
101
|
+
- `Bun.serve()` for HTTP/WebSocket. Don't use express/ws.
|
|
102
|
+
- `bun:sqlite` for SQLite. Don't use better-sqlite3.
|
|
103
|
+
- `Bun.file()` over node:fs for file I/O.
|
|
104
|
+
- `Bun.$` for shell commands. Don't use execa.
|