@zonease/aiworker-cli 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 +360 -0
- package/aiworker.js +417 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
# AIWorker
|
|
2
|
+
|
|
3
|
+
自托管 Agent Runtime — 由 **Brain provider**(知识 / 记忆 / 技能)与 **Executor provider**(OpenAI 兼容 chat completions + tool calling)组合而成。
|
|
4
|
+
|
|
5
|
+
工作站、服务器、k8s pod、docker container 都能跑成一个 worker 加入同一个 fleet。Operator 通过一个 CLI 控制所有 worker。
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **4 种入网路径**:手动 pair、docker auto-launch、自助 self-enroll(unattended)、**OTP-attended enrollment(worker deployer 零凭证)**
|
|
10
|
+
- **WS 控制面**:operator 与 worker 共享同一 gateway 入口,按 path 分流
|
|
11
|
+
- **多 LLM engine**:`http`(OpenAI / DeepSeek / SiliconFlow 等)/ `claude-code` / `codex` / `gemini-cli` / `qwen-code` / `cursor` / `mcp`
|
|
12
|
+
- **多 channel**:Telegram / WhatsApp / Lark / LINE / Web 五种 webhook adapter,全部强制验签
|
|
13
|
+
- **Cron / per-tool approvals / hot-reload / fallback chain** 全部内建
|
|
14
|
+
- **数据物理隔离**:fleet.db(gateway)与 worker.db(每 worker)AES-256-GCM 各自加密,丢失 master key = 全部失联
|
|
15
|
+
- **三档部署**:裸跑(开发)/ systemd(推荐 Linux)/ docker compose(fast-launch)
|
|
16
|
+
|
|
17
|
+
## Architecture
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
operator ─basicauth─► /ws ──────► gateway
|
|
21
|
+
worker ─无凭证─────► /enroll-ws ──────► gateway (OTP enrollment 专用)
|
|
22
|
+
│
|
|
23
|
+
▼
|
|
24
|
+
fleet.db
|
|
25
|
+
│
|
|
26
|
+
outbound WS
|
|
27
|
+
│
|
|
28
|
+
worker process(es)
|
|
29
|
+
│
|
|
30
|
+
▼
|
|
31
|
+
worker.db + LLM engine
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
详见 [`docs/architecture.md`](docs/architecture.md)。
|
|
35
|
+
|
|
36
|
+
## Stack
|
|
37
|
+
|
|
38
|
+
- Bun workspaces (monorepo: `apps/api` + `apps/cli` + `apps/gateway` + `apps/web` + 7 个 packages)
|
|
39
|
+
- Hono OpenAPIHono / Bun.serve / Drizzle ORM / SQLite / Zod / consola
|
|
40
|
+
- React 19 + TanStack Router/Query + shadcn/ui + Tailwind v4(web SPA)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
### Published(待 FEAT-027 npm publish 上线启用)
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
bun install -g @zonease/aiworker-cli
|
|
50
|
+
# 或 npm install -g @zonease/aiworker-cli
|
|
51
|
+
# 或从 GitHub Releases 下载单文件 binary(无依赖):
|
|
52
|
+
# curl -fsSL https://github.com/ZonEaseTech/aiworker/releases/latest/download/aiworker-linux-x64 -o /usr/local/bin/aiworker
|
|
53
|
+
# chmod +x /usr/local/bin/aiworker
|
|
54
|
+
|
|
55
|
+
aiworker serve
|
|
56
|
+
aiworker fleet list
|
|
57
|
+
aiworker chat <workerId> 'hello'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 本地开发(当前主路径)
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
git clone <repo-url>
|
|
64
|
+
cd aiworker && bun install
|
|
65
|
+
bun apps/cli/src/aiworker.ts <subcmd>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
下面的 Quickstart / cheat sheet 用本地开发态 `bun apps/cli/src/aiworker.ts ...` 调用;Stage B 完成后等价改写为全局 `aiworker ...`,命令树不变。
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Quickstart
|
|
73
|
+
|
|
74
|
+
### 角色
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
operator ─── 持 basicauth + aiworker CLI ─── 管 fleet
|
|
78
|
+
worker deployer ─── 跑 aiworker serve ────────── 加入 fleet 后等指令
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 选哪种 enrollment?
|
|
82
|
+
|
|
83
|
+
| 场景 | 用 | 一句话 |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| 朋友/客户/CI 临时装 worker | **OTP(推荐)** | worker deployer **零凭证**,operator 看 8 字符 OTP 后 approve |
|
|
86
|
+
| k8s/docker compose 批量 unattended | self-enroll | env 配 `AIWORKER_JOIN_TOKEN` 自动入网 |
|
|
87
|
+
| 高安全单 worker 手动 | 手动 pair | `aiworker pair --bootstrap-token wtk_...` |
|
|
88
|
+
| docker fast-launch(gateway 同机) | `aiworker fleet launch` | gateway supervisor 自己拉容器 |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 路径 1:OTP 入网(最简)
|
|
93
|
+
|
|
94
|
+
### Worker deployer(任何机器,**零 fleet 凭证**)
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
# 1. 装 bun
|
|
98
|
+
curl -fsSL https://bun.sh/install | bash
|
|
99
|
+
|
|
100
|
+
# 2. clone + install
|
|
101
|
+
git clone <repo-url>
|
|
102
|
+
cd aiworker && bun install
|
|
103
|
+
|
|
104
|
+
# 3. 最小 env
|
|
105
|
+
export AIWORKER_HOME="$HOME/.aiworker"
|
|
106
|
+
export AIWORKER_MASTER_KEY=$(openssl rand -hex 32) # worker 自己的 vault key
|
|
107
|
+
export WORKER_DB_PATH="$AIWORKER_HOME/worker.db"
|
|
108
|
+
export AIWORKER_GATEWAY_URL="wss://your-gateway.example/" # ← 仅这一个公网地址
|
|
109
|
+
export AIWORKER_DISPLAY_NAME="my-laptop" # 可选
|
|
110
|
+
|
|
111
|
+
# 4. init + serve
|
|
112
|
+
bun apps/cli/src/aiworker.ts init
|
|
113
|
+
bun apps/cli/src/aiworker.ts serve --port 3001
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
控制台输出:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
i [aiworker serve] OTP enrolling to wss://your-gateway.example/enroll-ws; awaiting operator approval
|
|
120
|
+
┌─────────────────────┐
|
|
121
|
+
│ OTP: 9CDT-94BK │
|
|
122
|
+
│ expires in 300s │
|
|
123
|
+
└─────────────────────┘
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
把 OTP 报给 operator。
|
|
127
|
+
|
|
128
|
+
### Operator
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
aiworker enroll list
|
|
132
|
+
# {"pending":[{"otp":"9CDT-94BK","displayName":"my-laptop",...}]}
|
|
133
|
+
|
|
134
|
+
aiworker enroll approve 9CDT-94BK
|
|
135
|
+
# ✔ 已批准
|
|
136
|
+
|
|
137
|
+
aiworker fleet list
|
|
138
|
+
# {"workers":[{"workerId":"w_xxx","displayName":"my-laptop","online":true,...}]}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
worker 端同步打:`√ approved as w_xxx; deviceToken=wtk_...,已加入 fleet`。
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 路径 2:self-enroll(自动化批量)
|
|
146
|
+
|
|
147
|
+
Worker 端 env 多两个,省去 operator approve:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
export AIWORKER_GATEWAY_URL="wss://operator:<basicauth-pwd>@your-gateway.example/ws"
|
|
151
|
+
export AIWORKER_JOIN_TOKEN="<gateway 端配的 join token>"
|
|
152
|
+
export AIWORKER_DISPLAY_NAME="ci-runner-12"
|
|
153
|
+
|
|
154
|
+
bun apps/cli/src/aiworker.ts init
|
|
155
|
+
bun apps/cli/src/aiworker.ts serve --port 3001
|
|
156
|
+
# 自动加入;operator 端 aiworker fleet list 直接见到
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
> ⚠️ URL 含 basicauth + JOIN_TOKEN 是 fleet 共享 secret,泄露面大。CI 可接受,朋友机器不要给。
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 路径 3:手动 pair(高安全)
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
# Worker 端:
|
|
167
|
+
bun apps/cli/src/aiworker.ts init
|
|
168
|
+
# 抓 stdout 的 wtk_xxx
|
|
169
|
+
bun apps/cli/src/aiworker.ts serve --port 3001 --gateway wss://operator:<pwd>@gateway/ws
|
|
170
|
+
|
|
171
|
+
# Operator 端:
|
|
172
|
+
aiworker pair --url wss://operator:<pwd>@gateway/ws \
|
|
173
|
+
--worker-url http://<worker-host>:3001 \
|
|
174
|
+
--bootstrap-token wtk_xxx \
|
|
175
|
+
--display-name production-1
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
> 限制:gateway 必须能 inbound 到 worker `:3001` 验 token。worker 在 NAT 后需要反向 tunnel;改用 OTP 模式避坑。
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 路径 4:docker auto-launch
|
|
183
|
+
|
|
184
|
+
需要 gateway 启用 `AIWORKER_GATEWAY_CAN_LAUNCH=true` + `docker.sock:ro` mount。
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
aiworker fleet launch --display-name demo
|
|
188
|
+
# gateway supervisor 自动 docker run + scrape bootstrap token + pair
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
详见 [`docs/deployment.md`](docs/deployment.md) 的 supervisor overlay 段落。
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Operator 日常 cheat sheet
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
# fleet 状态
|
|
199
|
+
aiworker fleet list # 谁在线
|
|
200
|
+
aiworker fleet info <workerId> # 单个 worker 运行时快照
|
|
201
|
+
aiworker fleet remove <workerId> # 摘除(deviceToken 立即失效)
|
|
202
|
+
|
|
203
|
+
# 与 worker 对话(流式 NDJSON)
|
|
204
|
+
aiworker chat <workerId> 'hello'
|
|
205
|
+
aiworker chat <workerId> '继续' --conversation-id <prev-id>
|
|
206
|
+
|
|
207
|
+
# 配置(乐观锁必须带 --if-match)
|
|
208
|
+
aiworker config get <workerId> # 读出含 version
|
|
209
|
+
aiworker config set <workerId> "$(cat new.json)" --if-match <version>
|
|
210
|
+
|
|
211
|
+
# Token 轮换(旧立即失效)
|
|
212
|
+
aiworker token rotate <workerId>
|
|
213
|
+
|
|
214
|
+
# OTP 审批
|
|
215
|
+
aiworker enroll list
|
|
216
|
+
aiworker enroll approve <OTP>
|
|
217
|
+
aiworker enroll reject <OTP>
|
|
218
|
+
|
|
219
|
+
# 日志订阅
|
|
220
|
+
aiworker logs <workerId> --follow --tail 200
|
|
221
|
+
|
|
222
|
+
# 审批 per-tool
|
|
223
|
+
aiworker approvals list
|
|
224
|
+
aiworker approvals grant <workerId> <taskId> <toolCallId> # allow
|
|
225
|
+
aiworker approvals grant <workerId> <taskId> <toolCallId> --deny
|
|
226
|
+
|
|
227
|
+
# 定时任务
|
|
228
|
+
aiworker schedule list <workerId>
|
|
229
|
+
aiworker schedule add <workerId> --expression '0 9 * * *' --prompt '早报' --channel web --chat-id daily
|
|
230
|
+
aiworker schedule remove <workerId> <jobId>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
`aiworker` operator 默认 gatewayUrl 在 `~/.aiworker/aim.json`。第一次跑:
|
|
234
|
+
|
|
235
|
+
```sh
|
|
236
|
+
mkdir -p ~/.aiworker
|
|
237
|
+
cat > ~/.aiworker/aim.json <<EOF
|
|
238
|
+
{
|
|
239
|
+
"gatewayUrl": "wss://operator:<basicauth-pwd>@your-gateway.example/ws",
|
|
240
|
+
"deviceId": "op-$(uuidgen)",
|
|
241
|
+
"deviceToken": "<INTERNAL_SHARED_SECRET>",
|
|
242
|
+
"defaultWorkerId": ""
|
|
243
|
+
}
|
|
244
|
+
EOF
|
|
245
|
+
chmod 600 ~/.aiworker/aim.json
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
如果在 gateway 同机跑(loopback),用 `ws://127.0.0.1:3000/ws`,无需 basicauth/token。
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Worker 配 LLM(claude-code 示例)
|
|
253
|
+
|
|
254
|
+
```sh
|
|
255
|
+
NEW='{"brains":[],"brainWriteTarget":"","brainRetrieval":"first-match","executor":{"engine":"claude-code","variant":"default"},"channels":[],"evolution":{"enabled":false,"observationRetentionDays":7}}'
|
|
256
|
+
aiworker config set <workerId> "$NEW" --if-match <current-version>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
可选 `engine`:`http`(OpenAI 兼容)/ `mcp` / `claude-code` / `acp`(gemini/qwen) / `codex` / `cursor`。
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 部署形态对比
|
|
264
|
+
|
|
265
|
+
| 形态 | 适用 | 入口 | docker |
|
|
266
|
+
|------|------|------|--------|
|
|
267
|
+
| **裸跑** | 开发 / CI | `aiworker gateway start` / `aiworker serve` 前台 | 无 |
|
|
268
|
+
| **systemd**(Linux 推荐) | 服务器长跑 | `aiworker install systemd [--user\|--system]` | 无 |
|
|
269
|
+
| **docker compose** | 不愿装 bun / per-worker 隔离 | `ops/compose/docker-compose.yml`(GHCR 镜像) | 有 |
|
|
270
|
+
|
|
271
|
+
详见 [`docs/deployment.md`](docs/deployment.md);公网 HTTPS(Cloudflare + Caddy)单独叠加层在 [`docs/deployment-public-https.md`](docs/deployment-public-https.md)。
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 关键 env
|
|
276
|
+
|
|
277
|
+
| 变量 | 用于 | 说明 |
|
|
278
|
+
|---|---|---|
|
|
279
|
+
| `AIWORKER_MASTER_KEY` | gateway / worker | 64 hex;丢了 fleet.db 解不开 — **必须组织级离线备份** |
|
|
280
|
+
| `INTERNAL_SHARED_SECRET` | gateway / 远程 operator | ≥16 chars;远程 aiworker CLI bearer |
|
|
281
|
+
| `AIWORKER_JOIN_TOKEN` | gateway / self-enroll worker | self-enroll 模式触发;与 INTERNAL_SHARED_SECRET 解耦 |
|
|
282
|
+
| `AIWORKER_GATEWAY_URL` | worker | OTP / self-enroll 模式连入口 |
|
|
283
|
+
| `AIWORKER_DISPLAY_NAME` | worker | operator 端识别用 |
|
|
284
|
+
| `AIWORKER_HOME` | gateway / worker | 默认 `~/.aiworker` |
|
|
285
|
+
| `WORKER_DB_PATH` | worker | 默认 `$AIWORKER_HOME/worker.db` |
|
|
286
|
+
| `AIWORKER_FLEET_DB_PATH` | gateway | 默认 `$AIWORKER_HOME/fleet.db` |
|
|
287
|
+
| `AIWORKER_GATEWAY_PORT` | gateway | 默认 3000 |
|
|
288
|
+
| `AIWORKER_ENROLL_OTP_TTL_SEC` | gateway | OTP 过期秒数,默认 300,[30, 3600] |
|
|
289
|
+
|
|
290
|
+
完整列表见 `apps/api/.env.example` 与 `ops/compose/.env.example`。
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 故障排查(高频 3 条)
|
|
295
|
+
|
|
296
|
+
| 现象 | 原因 | 修法 |
|
|
297
|
+
|---|---|---|
|
|
298
|
+
| `aiworker fleet list` → `WebSocket Expected 101 status code` | aim.json `gatewayUrl` 缺 `/ws` 或 basicauth | 重写 `~/.aiworker/aim.json`(见上) |
|
|
299
|
+
| OTP `aiworker enroll approve` 后 worker `online: false` | gateway 版本旧(缺 BUG-009 fix,commit `233548b` 起修) | 服务器 `git pull && systemctl restart aiworker-gateway` |
|
|
300
|
+
| 公网 `/health` 返回 401 | 你忘了带 basicauth | `curl -u operator:<pwd> https://your-gateway/health` |
|
|
301
|
+
|
|
302
|
+
详见 [`docs/deployment-public-https.md` § Troubleshooting](docs/deployment-public-https.md)。
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## 安全模型
|
|
307
|
+
|
|
308
|
+
- **fleet.db / worker.db 物理隔离**:gateway 永不存 worker 的业务数据
|
|
309
|
+
- **AES-256-GCM** 加密 `registered_workers.apiTokenEnc` + `worker_secrets`
|
|
310
|
+
- **timing-safe** bearer 比较
|
|
311
|
+
- **5 channel webhook 强制验签**(Telegram secret token / WhatsApp HMAC / Lark AES + token / LINE channel signature / Web binding token)
|
|
312
|
+
- **Caddy 路径分流**:`/ws` basicauth 守 operator + 已配对 worker,`/enroll-ws` 仅接受 OTP submit;fail-closed(缺 `/etc/caddy/auth.snippet` 直接拒启动)
|
|
313
|
+
|
|
314
|
+
详见 [CLAUDE.md § Security](CLAUDE.md) 与 [`docs/architecture.md` § 加密与认证](docs/architecture.md)。
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Backup checklist
|
|
319
|
+
|
|
320
|
+
- **`AIWORKER_MASTER_KEY`** — 离线保管。丢失 = fleet.db 全部 worker 必须重 enroll
|
|
321
|
+
- **fleet.db** — gateway 卷
|
|
322
|
+
- **每个 worker 的 worker.db** — worker 自己的卷
|
|
323
|
+
- **`INTERNAL_SHARED_SECRET`** — operator 凭证
|
|
324
|
+
- **`AIWORKER_JOIN_TOKEN`** — fleet 共享 secret(self-enroll 用)
|
|
325
|
+
- **Caddy basicauth bcrypt hash** — `/etc/caddy/auth.snippet`
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Development
|
|
330
|
+
|
|
331
|
+
```sh
|
|
332
|
+
bun install
|
|
333
|
+
bun run typecheck # 9 packages 全过
|
|
334
|
+
bun run test # 全工作区
|
|
335
|
+
bun run lint
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
文档系统(PMA):[`docs/plan/`](docs/plan/) 是历史方案,[`docs/task/`](docs/task/) 是 task 跟踪,[`docs/changelog.md`](docs/changelog.md) 是发布日志。新功能按 `/pma` skill 走 investigate → proposal → implement 三阶段。
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## License
|
|
343
|
+
|
|
344
|
+
[MIT](LICENSE) © 2026 ZonEase Tech
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Status
|
|
349
|
+
|
|
350
|
+
| Module | Status |
|
|
351
|
+
|---|---|
|
|
352
|
+
| Gateway WS 控制面 | ✅ Production |
|
|
353
|
+
| 4 enrollment paths | ✅ Production |
|
|
354
|
+
| 7 LLM engines | ✅ Production |
|
|
355
|
+
| 5 channel webhooks | ✅ Production |
|
|
356
|
+
| Cron / approvals / hot-reload | ✅ Production |
|
|
357
|
+
| **CLI 重命名(单 `aiworker` 入口)** | 🚧 Implementing (PLAN-020 / FEAT-028) |
|
|
358
|
+
| **npm 发布** | ⏳ Planned (FEAT-027) |
|
|
359
|
+
| Web SPA pending UI | 🔜 Stage-2 |
|
|
360
|
+
| Multi-host HA | 🔜 Stage-2 |
|