@workermill/agent 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -0
- package/dist/api.d.ts +13 -0
- package/dist/api.js +29 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +59 -0
- package/dist/commands/logs.d.ts +9 -0
- package/dist/commands/logs.js +52 -0
- package/dist/commands/pull.d.ts +4 -0
- package/dist/commands/pull.js +35 -0
- package/dist/commands/setup.d.ts +11 -0
- package/dist/commands/setup.js +396 -0
- package/dist/commands/start.d.ts +11 -0
- package/dist/commands/start.js +117 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.js +86 -0
- package/dist/commands/stop.d.ts +6 -0
- package/dist/commands/stop.js +61 -0
- package/dist/config.d.ts +77 -0
- package/dist/config.js +284 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +104 -0
- package/dist/planner.d.ts +19 -0
- package/dist/planner.js +268 -0
- package/dist/poller.d.ts +15 -0
- package/dist/poller.js +188 -0
- package/dist/spawner.d.ts +42 -0
- package/dist/spawner.js +290 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @workermill/agent
|
|
2
|
+
|
|
3
|
+
Run WorkerMill AI workers locally using your Claude Max subscription. The agent polls the WorkerMill cloud dashboard for tasks, runs planning via Claude CLI, and spawns Docker worker containers on your machine.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- **Docker Desktop** — [Install Docker](https://docs.docker.com/get-docker/)
|
|
8
|
+
- **Claude Code CLI** — The setup wizard auto-installs this, or install manually:
|
|
9
|
+
- macOS/Linux/WSL: `curl -fsSL https://claude.ai/install.sh | bash`
|
|
10
|
+
- Windows PowerShell: `irm https://claude.ai/install.ps1 | iex`
|
|
11
|
+
- **Claude Max subscription** — Run `claude` and sign in with your Claude account
|
|
12
|
+
- **Node.js >= 20** — [Install Node.js](https://nodejs.org/)
|
|
13
|
+
- **WorkerMill account** — Sign up at [workermill.com](https://workermill.com)
|
|
14
|
+
|
|
15
|
+
## Install & Setup
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g @workermill/agent
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The setup wizard launches automatically after install. It will:
|
|
22
|
+
1. Check all prerequisites (auto-installs Claude CLI if missing)
|
|
23
|
+
2. Prompt for your API key (from Settings > Integrations on the dashboard)
|
|
24
|
+
3. Validate connectivity to the WorkerMill API
|
|
25
|
+
4. Prompt for your SCM token (GitHub/GitLab/Bitbucket)
|
|
26
|
+
5. Pull the worker Docker image
|
|
27
|
+
6. Save configuration to `~/.workermill/config.json`
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Start the agent (foreground)
|
|
33
|
+
workermill-agent start
|
|
34
|
+
|
|
35
|
+
# Start in background (daemon mode)
|
|
36
|
+
workermill-agent start --detach
|
|
37
|
+
|
|
38
|
+
# Check status
|
|
39
|
+
workermill-agent status
|
|
40
|
+
|
|
41
|
+
# Stop a background agent
|
|
42
|
+
workermill-agent stop
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## How It Works
|
|
46
|
+
|
|
47
|
+
1. **Agent polls** the cloud API for tasks assigned to your organization
|
|
48
|
+
2. **Planning runs locally** via Claude CLI (using your Claude Max subscription — no per-token API charges)
|
|
49
|
+
3. **Worker containers** spawn locally via Docker, executing code changes
|
|
50
|
+
4. **Logs and status** stream back to the cloud dashboard in real-time
|
|
51
|
+
5. **PRs are created** on your SCM provider (GitHub/GitLab/Bitbucket)
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
Config is stored at `~/.workermill/config.json` (created by `workermill-agent setup`):
|
|
56
|
+
|
|
57
|
+
| Field | Default | Description |
|
|
58
|
+
|-------|---------|-------------|
|
|
59
|
+
| `apiUrl` | `https://workermill.com` | WorkerMill API URL |
|
|
60
|
+
| `apiKey` | — | Organization API key |
|
|
61
|
+
| `agentId` | `agent-<hostname>` | Unique agent identifier |
|
|
62
|
+
| `maxWorkers` | `2` | Max concurrent worker containers |
|
|
63
|
+
| `workerImage` | `public.ecr.aws/a7k5r0v0/workermill-worker:latest` | Docker image for workers |
|
|
64
|
+
|
|
65
|
+
## Troubleshooting
|
|
66
|
+
|
|
67
|
+
| Issue | Solution |
|
|
68
|
+
|-------|----------|
|
|
69
|
+
| "No config found" | Run `workermill-agent setup` |
|
|
70
|
+
| Auth failure | Check API key in Settings > Integrations |
|
|
71
|
+
| Docker not found | Install Docker Desktop and ensure it's running |
|
|
72
|
+
| Claude CLI not found | See install instructions above |
|
|
73
|
+
| Image pull fails | Check internet and try `docker pull public.ecr.aws/a7k5r0v0/workermill-worker:latest` |
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Axios instance for talking to the WorkerMill cloud API.
|
|
3
|
+
* Configured lazily after config is loaded.
|
|
4
|
+
*/
|
|
5
|
+
import { type AxiosInstance } from "axios";
|
|
6
|
+
/**
|
|
7
|
+
* Initialize the shared API client.
|
|
8
|
+
*/
|
|
9
|
+
export declare function initApi(baseUrl: string, apiKey: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Get the shared API client. Must call initApi() first.
|
|
12
|
+
*/
|
|
13
|
+
export declare const api: AxiosInstance;
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Axios instance for talking to the WorkerMill cloud API.
|
|
3
|
+
* Configured lazily after config is loaded.
|
|
4
|
+
*/
|
|
5
|
+
import axios from "axios";
|
|
6
|
+
let _api = null;
|
|
7
|
+
/**
|
|
8
|
+
* Initialize the shared API client.
|
|
9
|
+
*/
|
|
10
|
+
export function initApi(baseUrl, apiKey) {
|
|
11
|
+
_api = axios.create({
|
|
12
|
+
baseURL: baseUrl,
|
|
13
|
+
headers: {
|
|
14
|
+
"Content-Type": "application/json",
|
|
15
|
+
"x-api-key": apiKey,
|
|
16
|
+
},
|
|
17
|
+
timeout: 30_000,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get the shared API client. Must call initApi() first.
|
|
22
|
+
*/
|
|
23
|
+
export const api = new Proxy({}, {
|
|
24
|
+
get(_target, prop) {
|
|
25
|
+
if (!_api)
|
|
26
|
+
throw new Error("API client not initialized. Call initApi() first.");
|
|
27
|
+
return _api[prop];
|
|
28
|
+
},
|
|
29
|
+
});
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* WorkerMill Remote Agent CLI
|
|
4
|
+
*
|
|
5
|
+
* Smart default: running `workermill-agent` with no args auto-launches
|
|
6
|
+
* setup if no config exists, or starts the agent if already configured.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync } from "fs";
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
import { setupCommand } from "./commands/setup.js";
|
|
11
|
+
import { startCommand } from "./commands/start.js";
|
|
12
|
+
import { stopCommand } from "./commands/stop.js";
|
|
13
|
+
import { statusCommand } from "./commands/status.js";
|
|
14
|
+
import { logsCommand } from "./commands/logs.js";
|
|
15
|
+
import { pullCommand } from "./commands/pull.js";
|
|
16
|
+
import { getConfigFile } from "./config.js";
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.name("workermill-agent")
|
|
20
|
+
.description("WorkerMill Remote Agent - Run AI workers locally with your Claude Max subscription")
|
|
21
|
+
.version("0.1.0");
|
|
22
|
+
program
|
|
23
|
+
.command("setup")
|
|
24
|
+
.description("Interactive setup wizard - configure API key, validate prerequisites, pull worker image")
|
|
25
|
+
.action(setupCommand);
|
|
26
|
+
program
|
|
27
|
+
.command("start")
|
|
28
|
+
.description("Start the agent, polling the cloud API for tasks")
|
|
29
|
+
.option("--detach", "Run in background (daemon mode)")
|
|
30
|
+
.action(startCommand);
|
|
31
|
+
program
|
|
32
|
+
.command("stop")
|
|
33
|
+
.description("Stop the running agent")
|
|
34
|
+
.action(stopCommand);
|
|
35
|
+
program
|
|
36
|
+
.command("status")
|
|
37
|
+
.description("Show agent status, active containers, and API connectivity")
|
|
38
|
+
.action(statusCommand);
|
|
39
|
+
program
|
|
40
|
+
.command("logs")
|
|
41
|
+
.description("Live tail of agent logs (like tail -f)")
|
|
42
|
+
.option("-n, --lines <count>", "Number of lines to show initially", "50")
|
|
43
|
+
.action(logsCommand);
|
|
44
|
+
program
|
|
45
|
+
.command("pull")
|
|
46
|
+
.description("Pull the latest worker Docker image")
|
|
47
|
+
.action(pullCommand);
|
|
48
|
+
// If no command given, auto-detect: run setup if no config, otherwise start
|
|
49
|
+
if (process.argv.length <= 2) {
|
|
50
|
+
if (existsSync(getConfigFile())) {
|
|
51
|
+
startCommand({ detach: false });
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
setupCommand();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
program.parse();
|
|
59
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logs Command — Live tail of agent logs.
|
|
3
|
+
*
|
|
4
|
+
* Works like `tail -f ~/.workermill/agent.log`.
|
|
5
|
+
* Shows the last N lines then follows new output.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import { existsSync, readFileSync, watchFile, statSync, openSync, readSync, closeSync } from "fs";
|
|
9
|
+
import { getLogFile } from "../config.js";
|
|
10
|
+
export async function logsCommand(options) {
|
|
11
|
+
const logFile = getLogFile();
|
|
12
|
+
if (!existsSync(logFile)) {
|
|
13
|
+
console.log(chalk.yellow("No log file found."));
|
|
14
|
+
console.log(chalk.dim(`Expected at: ${logFile}`));
|
|
15
|
+
console.log(chalk.dim("Start the agent with --detach to generate logs."));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const tailLines = parseInt(options.lines || "50", 10);
|
|
19
|
+
// Show last N lines
|
|
20
|
+
const content = readFileSync(logFile, "utf-8");
|
|
21
|
+
const lines = content.split("\n");
|
|
22
|
+
const startIdx = Math.max(0, lines.length - tailLines);
|
|
23
|
+
const tail = lines.slice(startIdx).join("\n");
|
|
24
|
+
if (tail.trim()) {
|
|
25
|
+
process.stdout.write(tail);
|
|
26
|
+
if (!tail.endsWith("\n"))
|
|
27
|
+
process.stdout.write("\n");
|
|
28
|
+
}
|
|
29
|
+
console.log(chalk.dim(`── Following ${logFile} (Ctrl+C to stop) ──`));
|
|
30
|
+
// Follow new output
|
|
31
|
+
let lastSize = statSync(logFile).size;
|
|
32
|
+
watchFile(logFile, { interval: 500 }, () => {
|
|
33
|
+
try {
|
|
34
|
+
const currentSize = statSync(logFile).size;
|
|
35
|
+
if (currentSize <= lastSize) {
|
|
36
|
+
lastSize = currentSize;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const fd = openSync(logFile, "r");
|
|
40
|
+
const buffer = Buffer.alloc(currentSize - lastSize);
|
|
41
|
+
readSync(fd, buffer, 0, buffer.length, lastSize);
|
|
42
|
+
closeSync(fd);
|
|
43
|
+
process.stdout.write(buffer.toString());
|
|
44
|
+
lastSize = currentSize;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// File may have been rotated
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
// Keep process alive
|
|
51
|
+
await new Promise(() => { });
|
|
52
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull Command — Pull the latest worker Docker image.
|
|
3
|
+
*/
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { spawnSync } from "child_process";
|
|
6
|
+
import { existsSync } from "fs";
|
|
7
|
+
import { loadConfigFromFile, getConfigFile } from "../config.js";
|
|
8
|
+
export async function pullCommand() {
|
|
9
|
+
let workerImage = "public.ecr.aws/a7k5r0v0/workermill-worker:latest";
|
|
10
|
+
// Use configured image if config exists
|
|
11
|
+
if (existsSync(getConfigFile())) {
|
|
12
|
+
const config = loadConfigFromFile();
|
|
13
|
+
workerImage = config.workerImage || workerImage;
|
|
14
|
+
}
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(chalk.dim(` Pulling worker image: ${workerImage}`));
|
|
17
|
+
console.log(chalk.dim(" This may take a few minutes..."));
|
|
18
|
+
console.log();
|
|
19
|
+
const result = spawnSync("docker", ["pull", workerImage], {
|
|
20
|
+
stdio: "inherit",
|
|
21
|
+
timeout: 600_000,
|
|
22
|
+
});
|
|
23
|
+
console.log();
|
|
24
|
+
if (result.status === 0) {
|
|
25
|
+
console.log(chalk.green(` ✓ Worker image updated`));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
console.log(chalk.red(" ✗ Failed to pull worker image."));
|
|
29
|
+
if (result.error) {
|
|
30
|
+
console.log(chalk.yellow(` Error: ${result.error.message}`));
|
|
31
|
+
}
|
|
32
|
+
console.log(chalk.yellow(" Is Docker Desktop running?"));
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup Wizard — Interactive configuration for the WorkerMill Remote Agent.
|
|
3
|
+
*
|
|
4
|
+
* Prerequisites checked/installed:
|
|
5
|
+
* - Docker Desktop (must be installed manually)
|
|
6
|
+
* - Git for Windows (must be installed manually — required by Claude Code on Windows)
|
|
7
|
+
* - Claude CLI → winget on Windows, curl | bash on Linux/macOS/WSL
|
|
8
|
+
* - Claude auth → launches `claude` which prompts for sign-in on first run
|
|
9
|
+
* - Worker image → `docker pull public.ecr.aws/a7k5r0v0/workermill-worker:latest`
|
|
10
|
+
*/
|
|
11
|
+
export declare function setupCommand(): Promise<void>;
|