@desplega.ai/agent-swarm 1.2.0 → 1.2.1
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/.dockerignore +3 -0
- package/README.md +28 -4
- package/assets/agent-swarm.png +0 -0
- package/deploy/docker-push.ts +30 -0
- package/package.json +8 -4
- package/src/commands/setup.tsx +5 -5
- package/src/hooks/hook.ts +6 -0
- package/src/tools/poll-task.ts +1 -0
package/.dockerignore
CHANGED
package/README.md
CHANGED
|
@@ -87,7 +87,13 @@ bunx @desplega.ai/agent-swarm help
|
|
|
87
87
|
|
|
88
88
|
Run Claude as a containerized worker agent in the swarm.
|
|
89
89
|
|
|
90
|
-
###
|
|
90
|
+
### Pull from Registry
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
docker pull ghcr.io/desplega-ai/agent-swarm-worker:latest
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Build Locally
|
|
91
97
|
|
|
92
98
|
```bash
|
|
93
99
|
# Build the worker image
|
|
@@ -100,11 +106,20 @@ bun run docker:build:worker
|
|
|
100
106
|
### Run
|
|
101
107
|
|
|
102
108
|
```bash
|
|
103
|
-
# Using
|
|
109
|
+
# Using pre-built image from GHCR
|
|
104
110
|
docker run --rm -it \
|
|
105
111
|
-e CLAUDE_CODE_OAUTH_TOKEN=your-token \
|
|
106
112
|
-e API_KEY=your-api-key \
|
|
107
113
|
-v ./logs:/logs \
|
|
114
|
+
-v ./work:/workspace \
|
|
115
|
+
ghcr.io/desplega-ai/agent-swarm-worker
|
|
116
|
+
|
|
117
|
+
# Or using locally built image
|
|
118
|
+
docker run --rm -it \
|
|
119
|
+
-e CLAUDE_CODE_OAUTH_TOKEN=your-token \
|
|
120
|
+
-e API_KEY=your-api-key \
|
|
121
|
+
-v ./logs:/logs \
|
|
122
|
+
-v ./work:/workspace \
|
|
108
123
|
agent-swarm-worker
|
|
109
124
|
|
|
110
125
|
# Using docker-compose
|
|
@@ -138,9 +153,18 @@ The Docker worker image is built using a multi-stage build:
|
|
|
138
153
|
- **Utilities**: git, git-lfs, vim, nano, jq, curl, wget, ssh
|
|
139
154
|
- **Sudo access**: Worker can install packages with `sudo apt-get install`
|
|
140
155
|
|
|
141
|
-
**
|
|
156
|
+
**Volumes:**
|
|
157
|
+
- `/workspace` - Working directory for cloning repos (mount `./work:/workspace` for persistence)
|
|
158
|
+
- `/logs` - Session logs (mount `./logs:/logs` for persistence)
|
|
159
|
+
|
|
160
|
+
### Publishing (Maintainers)
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Requires gh CLI authenticated
|
|
164
|
+
bun deploy/docker-push.ts
|
|
165
|
+
```
|
|
142
166
|
|
|
143
|
-
|
|
167
|
+
This builds, tags with version from package.json + `latest`, and pushes to GHCR.
|
|
144
168
|
|
|
145
169
|
## Environment Variables
|
|
146
170
|
|
|
Binary file
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { $ } from "bun";
|
|
4
|
+
import pkg from "../package.json";
|
|
5
|
+
|
|
6
|
+
const IMAGE = "ghcr.io/desplega-ai/agent-swarm-worker";
|
|
7
|
+
const VERSION = pkg.version;
|
|
8
|
+
|
|
9
|
+
console.log(`Publishing ${IMAGE}:${VERSION}...`);
|
|
10
|
+
|
|
11
|
+
// Login to GHCR using gh CLI
|
|
12
|
+
const token = await $`gh auth token`.text();
|
|
13
|
+
const username = await $`gh api user -q .login`.text();
|
|
14
|
+
await $`echo ${token.trim()} | docker login ghcr.io -u ${username.trim()} --password-stdin`;
|
|
15
|
+
|
|
16
|
+
// Build
|
|
17
|
+
console.log("Building image...");
|
|
18
|
+
await $`docker build -f Dockerfile.worker -t agent-swarm-worker .`;
|
|
19
|
+
|
|
20
|
+
// Tag
|
|
21
|
+
console.log(`Tagging as ${VERSION} and latest...`);
|
|
22
|
+
await $`docker tag agent-swarm-worker ${IMAGE}:${VERSION}`;
|
|
23
|
+
await $`docker tag agent-swarm-worker ${IMAGE}:latest`;
|
|
24
|
+
|
|
25
|
+
// Push
|
|
26
|
+
console.log("Pushing to GHCR...");
|
|
27
|
+
await $`docker push ${IMAGE}:${VERSION}`;
|
|
28
|
+
await $`docker push ${IMAGE}:latest`;
|
|
29
|
+
|
|
30
|
+
console.log(`Done! Published ${IMAGE}:${VERSION}`);
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@desplega.ai/agent-swarm",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Agent orchestration layer MCP for Claude Code, Codex, Gemini CLI, and more!",
|
|
5
|
-
"module": "src/
|
|
5
|
+
"module": "src/http.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"agent-swarm": "./src/cli.tsx"
|
|
@@ -30,8 +30,12 @@
|
|
|
30
30
|
"format": "biome format --write src",
|
|
31
31
|
"build:binary": "bun build ./src/cli.tsx --compile --target=bun-linux-x64 --outfile ./dist/agent-swarm",
|
|
32
32
|
"build:binary:arm64": "bun build ./src/cli.tsx --compile --target=bun-linux-arm64 --outfile ./dist/agent-swarm",
|
|
33
|
-
"docker:build:worker": "docker build -f Dockerfile.worker -t agent-swarm-worker .",
|
|
34
|
-
"docker:run:worker": "docker run --rm -it --env-file .env.docker -v ./logs:/logs agent-swarm-worker"
|
|
33
|
+
"docker:build:worker": "docker build -f Dockerfile.worker -t agent-swarm-worker:latest .",
|
|
34
|
+
"docker:run:worker": "docker run --rm -it --env-file .env.docker -v ./logs:/logs -v ./work:/workspace agent-swarm-worker:latest",
|
|
35
|
+
"deploy:install": "bun deploy/install.ts",
|
|
36
|
+
"deploy:update": "bun deploy/update.ts",
|
|
37
|
+
"deploy:uninstall": "bun deploy/uninstall.ts",
|
|
38
|
+
"deploy:docker": "bun deploy/docker-push.ts"
|
|
35
39
|
},
|
|
36
40
|
"devDependencies": {
|
|
37
41
|
"@biomejs/biome": "^2.3.9",
|
package/src/commands/setup.tsx
CHANGED
|
@@ -434,7 +434,7 @@ export function Setup({ dryRun = false, restore = false, yes = false }: SetupPro
|
|
|
434
434
|
<Box flexDirection="column" padding={1}>
|
|
435
435
|
<Box flexDirection="column" marginBottom={1}>
|
|
436
436
|
{state.logs.map((log, i) => (
|
|
437
|
-
<Text key={i} dimColor>
|
|
437
|
+
<Text key={`log-${i}-${log.slice(0, 20)}`} dimColor>
|
|
438
438
|
{log}
|
|
439
439
|
</Text>
|
|
440
440
|
))}
|
|
@@ -457,7 +457,7 @@ export function Setup({ dryRun = false, restore = false, yes = false }: SetupPro
|
|
|
457
457
|
<Box flexDirection="column" padding={1}>
|
|
458
458
|
<Box flexDirection="column" marginBottom={1}>
|
|
459
459
|
{state.logs.map((log, i) => (
|
|
460
|
-
<Text key={i} dimColor>
|
|
460
|
+
<Text key={`log-${i}-${log.slice(0, 20)}`} dimColor>
|
|
461
461
|
{log}
|
|
462
462
|
</Text>
|
|
463
463
|
))}
|
|
@@ -496,7 +496,7 @@ export function Setup({ dryRun = false, restore = false, yes = false }: SetupPro
|
|
|
496
496
|
<Box flexDirection="column" padding={1}>
|
|
497
497
|
<Box flexDirection="column" marginBottom={1}>
|
|
498
498
|
{state.logs.map((log, i) => (
|
|
499
|
-
<Text key={i} dimColor>
|
|
499
|
+
<Text key={`log-${i}-${log.slice(0, 20)}`} dimColor>
|
|
500
500
|
{log}
|
|
501
501
|
</Text>
|
|
502
502
|
))}
|
|
@@ -534,7 +534,7 @@ export function Setup({ dryRun = false, restore = false, yes = false }: SetupPro
|
|
|
534
534
|
<Box flexDirection="column" padding={1}>
|
|
535
535
|
<Box flexDirection="column" marginBottom={1}>
|
|
536
536
|
{state.logs.map((log, i) => (
|
|
537
|
-
<Text key={i} dimColor>
|
|
537
|
+
<Text key={`log-${i}-${log.slice(0, 20)}`} dimColor>
|
|
538
538
|
{log}
|
|
539
539
|
</Text>
|
|
540
540
|
))}
|
|
@@ -565,7 +565,7 @@ export function Setup({ dryRun = false, restore = false, yes = false }: SetupPro
|
|
|
565
565
|
)}
|
|
566
566
|
<Box flexDirection="column" marginBottom={1}>
|
|
567
567
|
{state.logs.map((log, i) => (
|
|
568
|
-
<Text key={i} dimColor>
|
|
568
|
+
<Text key={`log-${i}-${log.slice(0, 20)}`} dimColor>
|
|
569
569
|
{log}
|
|
570
570
|
</Text>
|
|
571
571
|
))}
|
package/src/hooks/hook.ts
CHANGED
|
@@ -129,6 +129,12 @@ export async function handleHook(): Promise<void> {
|
|
|
129
129
|
console.log(
|
|
130
130
|
`You are registered as ${agentInfo.isLead ? "lead" : "worker"} agent "${agentInfo.name}" with ID: ${agentInfo.id} (status: ${agentInfo.status}) as of ${new Date().toISOString()}.`,
|
|
131
131
|
);
|
|
132
|
+
|
|
133
|
+
if (!agentInfo.isLead && agentInfo.status === "busy") {
|
|
134
|
+
console.log(
|
|
135
|
+
`Remember to call store-progress periodically to update the lead agent on your progress as you are currently marked as busy. The comments you leave will be helpful for the lead agent to monitor your work.`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
132
138
|
} else {
|
|
133
139
|
console.log(
|
|
134
140
|
`You are not registered in the agent swarm yet. Use the join-swarm tool to register yourself, then check your status with my-agent-info.
|
package/src/tools/poll-task.ts
CHANGED
|
@@ -68,6 +68,7 @@ export const registerPollTaskTool = (server: McpServer) => {
|
|
|
68
68
|
while (new Date() < maxTime) {
|
|
69
69
|
// Fetch and update in a single transaction to avoid race conditions
|
|
70
70
|
const startedTask = getDb().transaction(() => {
|
|
71
|
+
// biome-ignore lint/style/noNonNullAssertion: agent existence verified above
|
|
71
72
|
const agentNow = getAgentById(agentId)!;
|
|
72
73
|
|
|
73
74
|
if (agentNow.status !== "busy") {
|