@zonease/aiworker-cli 0.2.1 → 0.3.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 +216 -167
- package/aiworker.js +178 -171
- package/drizzle/worker/0003_rare_cloak.sql +7 -0
- package/drizzle/worker/meta/0003_snapshot.json +873 -0
- package/drizzle/worker/meta/_journal.json +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,184 +1,173 @@
|
|
|
1
1
|
# AIWorker
|
|
2
2
|
|
|
3
|
-
自托管 Agent Runtime — 由 **Brain provider**(知识 / 记忆 / 技能)与 **Executor provider**(OpenAI 兼容
|
|
3
|
+
自托管 Agent Runtime — 由 **Brain provider**(知识 / 记忆 / 技能)与 **Executor provider**(OpenAI 兼容 / claude-code / codex / gemini-cli / qwen-code / cursor / MCP)组合而成。
|
|
4
4
|
|
|
5
|
-
工作站、服务器、k8s pod、docker container 都能跑成一个 worker 加入同一个 fleet。Operator
|
|
5
|
+
工作站、服务器、k8s pod、docker container 都能跑成一个 worker 加入同一个 fleet。Operator 用一个 CLI 控制所有 worker。
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- **4
|
|
10
|
-
- **WS 控制面**:operator
|
|
11
|
-
- **多 LLM engine**:`http
|
|
12
|
-
- **多 channel**:Telegram / WhatsApp / Lark / LINE / Web
|
|
13
|
-
- **Cron / per-tool approvals / hot-reload / fallback chain**
|
|
14
|
-
- **数据物理隔离**:fleet.db(gateway)与 worker.db(每 worker)AES-256-GCM
|
|
15
|
-
-
|
|
9
|
+
- **4 种入网路径**:OTP-attended(worker deployer 零凭证)/ self-enroll(unattended 批量)/ 手动 pair / docker auto-launch
|
|
10
|
+
- **WS 控制面**:operator + worker 共享同一 gateway 入口,按 path 分流(`/ws` basicauth + `/enroll-ws` OTP 专用)
|
|
11
|
+
- **多 LLM engine**:`http` (OpenAI / DeepSeek / SiliconFlow / 任意 OpenAI 兼容) / `claude-code` / `codex` / `acp` (gemini / qwen) / `cursor` / `mcp`
|
|
12
|
+
- **多 channel webhook**:Telegram / WhatsApp / Lark / LINE / Web,全部强制验签
|
|
13
|
+
- **Cron / per-tool approvals / hot-reload / fallback chain** 内建
|
|
14
|
+
- **数据物理隔离**:fleet.db(gateway)与 worker.db(每 worker)AES-256-GCM 各自加密
|
|
15
|
+
- **三档部署**:裸跑 / systemd / docker compose
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
---
|
|
18
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
|
-
```
|
|
19
|
+
## 🚀 30 秒 demo
|
|
33
20
|
|
|
34
|
-
|
|
21
|
+
**目标**:本机起一个 worker,加入远端 gateway,发一条消息让 worker 用 LLM 回。
|
|
35
22
|
|
|
36
|
-
|
|
23
|
+
```
|
|
24
|
+
┌──────────────────────────┐ OTP enroll ┌──────────────────────────┐
|
|
25
|
+
│ 你的工作站 │ wss://<gateway>/ │ 远端 gateway │
|
|
26
|
+
│ │ /enroll-ws │ │
|
|
27
|
+
│ aiworker serve │ ───────────────────────► │ /root/.bun/bin/aiworker │
|
|
28
|
+
│ (workerId 自动 mint) │ │ gateway start (systemd) │
|
|
29
|
+
│ listening :9217 │ ◄─────── OTP YDCR-ZD8M ──│ │
|
|
30
|
+
│ │ │ fleet.db │
|
|
31
|
+
└──────────┬───────────────┘ └─────┬────────────────────┘
|
|
32
|
+
│ │
|
|
33
|
+
│ ┌─────────────────────────────────────────────┴──┐
|
|
34
|
+
│ │ Step 4: operator 在 gateway 同机 loopback │
|
|
35
|
+
│ │ ws://127.0.0.1:9218/ws (空 token bypass) │
|
|
36
|
+
│ │ $ aiworker enroll list │
|
|
37
|
+
│ │ $ aiworker enroll approve YDCR-ZD8M │
|
|
38
|
+
│ └─────────────────────────────────────────────┬──┘
|
|
39
|
+
│ │
|
|
40
|
+
│ ◄─────── enrollment.approved (deviceToken) ────┤
|
|
41
|
+
│ worker.online=true 写 fleet.db │
|
|
42
|
+
│ │
|
|
43
|
+
│ Step 6: chat (operator → gateway → worker) │
|
|
44
|
+
│ ◄─────── chat.send 'hello' ────────────────────┤
|
|
45
|
+
│ orchestrator → executor (claude-code) │
|
|
46
|
+
│ orchestrator → ... → done │
|
|
47
|
+
├───── chat.message echo ──────────────────────► │
|
|
48
|
+
▼ ▼
|
|
49
|
+
pkill / SIGTERM fleet.db 持久化
|
|
50
|
+
```
|
|
37
51
|
|
|
38
|
-
|
|
39
|
-
- Hono OpenAPIHono / Bun.serve / Drizzle ORM / SQLite / Zod / consola
|
|
40
|
-
- React 19 + TanStack Router/Query + shadcn/ui + Tailwind v4(web SPA)
|
|
52
|
+
**Worker 端**(你的工作站,零 fleet 凭证):
|
|
41
53
|
|
|
42
|
-
|
|
54
|
+
```sh
|
|
55
|
+
bun install -g @zonease/aiworker-cli # 或 npm install -g
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
export AIWORKER_GATEWAY_URL='wss://your-gateway.example/'
|
|
58
|
+
export AIWORKER_DISPLAY_NAME='my-laptop'
|
|
59
|
+
aiworker serve
|
|
60
|
+
```
|
|
45
61
|
|
|
46
|
-
|
|
62
|
+
输出:
|
|
47
63
|
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
aiworker serve
|
|
57
|
-
aiworker
|
|
58
|
-
|
|
64
|
+
```
|
|
65
|
+
┌────────────────────────────────────────────────────────────────────────────┐
|
|
66
|
+
│ ⚠️ AIWORKER first-run setup │
|
|
67
|
+
│ AIWORKER_MASTER_KEY (写入 ~/.aiworker/.env, chmod 0600) │
|
|
68
|
+
│ <64 hex chars — 离线备份> │
|
|
69
|
+
└────────────────────────────────────────────────────────────────────────────┘
|
|
70
|
+
[worker] id=w_ntssfzwwzzq0
|
|
71
|
+
[worker] AIWORKER_BOOTSTRAP_TOKEN=wtk_VhW4ea1JrfCJFdSQ...
|
|
72
|
+
√ [aiworker serve] worker listening on :9217 (config v1)
|
|
73
|
+
i [aiworker serve] OTP enrolling to wss://your-gateway.example/enroll-ws
|
|
74
|
+
┌─────────────────────┐
|
|
75
|
+
│ OTP: YDCR-ZD8M │
|
|
76
|
+
│ expires in 300s │
|
|
77
|
+
└─────────────────────┘
|
|
59
78
|
```
|
|
60
79
|
|
|
61
|
-
|
|
80
|
+
**Operator 端**(gateway 主机或 basicauth 远端):
|
|
62
81
|
|
|
63
82
|
```sh
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
aiworker enroll list # 看 pending OTP
|
|
84
|
+
aiworker enroll approve YDCR-ZD8M # ✔ 已批准
|
|
85
|
+
aiworker fleet list # online: true
|
|
86
|
+
aiworker chat w_ntssfzwwzzq0 'hello' # NDJSON 流式输出
|
|
67
87
|
```
|
|
68
88
|
|
|
69
|
-
|
|
89
|
+
完整端到端实测见 [docs/changelog.md](docs/changelog.md) 11:50 条目。
|
|
70
90
|
|
|
71
91
|
---
|
|
72
92
|
|
|
73
|
-
##
|
|
93
|
+
## Install
|
|
74
94
|
|
|
75
|
-
###
|
|
95
|
+
### 已发布
|
|
76
96
|
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
|
|
97
|
+
```sh
|
|
98
|
+
bun install -g @zonease/aiworker-cli # ← 当前 latest 0.2.1(含 in-process gateway / OTP enroll / 6 LLM engine)
|
|
99
|
+
# 或
|
|
100
|
+
npm install -g @zonease/aiworker-cli
|
|
80
101
|
```
|
|
81
102
|
|
|
82
|
-
|
|
103
|
+
binary 跑在 `~/.bun/bin/aiworker` 或 `$(npm bin -g)/aiworker`。第一次跑任意命令时自动 mint master key 写到 `~/.aiworker/.env`(chmod 0600)。
|
|
83
104
|
|
|
84
|
-
|
|
85
|
-
|---|---|---|
|
|
86
|
-
| 朋友/客户/CI 临时装 worker | **OTP(推荐)** | worker deployer **零凭证**,operator 看 8 字符 OTP 后 approve |
|
|
87
|
-
| k8s/docker compose 批量 unattended | self-enroll | env 配 `AIWORKER_JOIN_TOKEN` 自动入网 |
|
|
88
|
-
| 高安全单 worker 手动 | 手动 pair | `aiworker pair --bootstrap-token wtk_...` |
|
|
89
|
-
| docker fast-launch(gateway 同机) | `aiworker fleet launch` | gateway supervisor 自己拉容器 |
|
|
105
|
+
### 本地开发
|
|
90
106
|
|
|
91
|
-
|
|
107
|
+
```sh
|
|
108
|
+
git clone https://github.com/ZonEaseTech/aiworker
|
|
109
|
+
cd aiworker && bun install
|
|
110
|
+
bun apps/cli/src/aiworker.ts <subcmd> # = aiworker <subcmd>
|
|
111
|
+
```
|
|
92
112
|
|
|
93
|
-
|
|
113
|
+
下面所有 `aiworker ...` 命令在本地开发态等价 `bun apps/cli/src/aiworker.ts ...`。
|
|
94
114
|
|
|
95
|
-
|
|
115
|
+
---
|
|
96
116
|
|
|
97
|
-
|
|
98
|
-
# 1. 装 bun(如果没装)
|
|
99
|
-
curl -fsSL https://bun.sh/install | bash
|
|
117
|
+
## 4 种入网路径
|
|
100
118
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
119
|
+
| 场景 | 用 | Worker 端凭证 | Operator 介入 |
|
|
120
|
+
|---|---|---|---|
|
|
121
|
+
| 朋友/客户/CI 临时装 worker | **OTP(推荐)** | 零(worker 不持任何 fleet 共享 secret) | 看 8 字符 OTP → approve |
|
|
122
|
+
| k8s/docker compose 批量 unattended | self-enroll | `AIWORKER_JOIN_TOKEN`(fleet 共享) | 无(自动入网) |
|
|
123
|
+
| 高安全单 worker 手动 | 手动 pair | worker 启动后输出 `wtk_xxx` bootstrap token | `aiworker pair --bootstrap-token wtk_...` |
|
|
124
|
+
| docker fast-launch(gateway 同机) | `aiworker fleet launch` | gateway 自动注入 | 一行命令 |
|
|
104
125
|
|
|
105
|
-
|
|
106
|
-
# 控制台显示**一次**,请离线备份。
|
|
107
|
-
aiworker init
|
|
126
|
+
### OTP(推荐)
|
|
108
127
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
export
|
|
128
|
+
Worker:
|
|
129
|
+
```sh
|
|
130
|
+
export AIWORKER_GATEWAY_URL='wss://your-gateway.example/'
|
|
131
|
+
export AIWORKER_DISPLAY_NAME='my-laptop' # 可选,默认 hostname
|
|
112
132
|
aiworker serve
|
|
113
133
|
```
|
|
114
134
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
```
|
|
118
|
-
i [aiworker serve] OTP enrolling to wss://your-gateway.example/enroll-ws; awaiting operator approval
|
|
119
|
-
┌─────────────────────┐
|
|
120
|
-
│ OTP: 9CDT-94BK │
|
|
121
|
-
│ expires in 300s │
|
|
122
|
-
└─────────────────────┘
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
把 OTP 报给 operator。
|
|
126
|
-
|
|
127
|
-
### Operator
|
|
128
|
-
|
|
135
|
+
Operator:
|
|
129
136
|
```sh
|
|
130
|
-
aiworker enroll list
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
aiworker enroll approve 9CDT-94BK
|
|
134
|
-
# ✔ 已批准
|
|
135
|
-
|
|
136
|
-
aiworker fleet list
|
|
137
|
-
# {"workers":[{"workerId":"w_xxx","displayName":"my-laptop","online":true,...}]}
|
|
137
|
+
aiworker enroll list # → pending [{ otp, workerId, displayName }]
|
|
138
|
+
aiworker enroll approve <OTP>
|
|
138
139
|
```
|
|
139
140
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
---
|
|
143
|
-
|
|
144
|
-
## 路径 2:self-enroll(自动化批量)
|
|
145
|
-
|
|
146
|
-
Worker 端 env 多两个,省去 operator approve:
|
|
141
|
+
### self-enroll(自动化)
|
|
147
142
|
|
|
143
|
+
Worker:
|
|
148
144
|
```sh
|
|
149
|
-
export AIWORKER_GATEWAY_URL=
|
|
150
|
-
export AIWORKER_JOIN_TOKEN=
|
|
151
|
-
export AIWORKER_DISPLAY_NAME=
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
bun apps/cli/src/aiworker.ts serve --port 9217
|
|
155
|
-
# 自动加入;operator 端 aiworker fleet list 直接见到
|
|
145
|
+
export AIWORKER_GATEWAY_URL='wss://operator:<basicauth-pwd>@your-gateway.example/ws'
|
|
146
|
+
export AIWORKER_JOIN_TOKEN='<gateway 配置的 join token>'
|
|
147
|
+
export AIWORKER_DISPLAY_NAME='ci-runner-12'
|
|
148
|
+
aiworker serve
|
|
149
|
+
# operator 端立即 aiworker fleet list 见到
|
|
156
150
|
```
|
|
157
151
|
|
|
158
152
|
> ⚠️ URL 含 basicauth + JOIN_TOKEN 是 fleet 共享 secret,泄露面大。CI 可接受,朋友机器不要给。
|
|
159
153
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
## 路径 3:手动 pair(高安全)
|
|
154
|
+
### 手动 pair(高安全)
|
|
163
155
|
|
|
164
156
|
```sh
|
|
165
|
-
# Worker
|
|
166
|
-
|
|
157
|
+
# Worker:
|
|
158
|
+
aiworker serve --gateway 'wss://operator:<pwd>@gateway/ws'
|
|
167
159
|
# 抓 stdout 的 wtk_xxx
|
|
168
|
-
bun apps/cli/src/aiworker.ts serve --port 9217 --gateway wss://operator:<pwd>@gateway/ws
|
|
169
160
|
|
|
170
|
-
# Operator
|
|
171
|
-
aiworker pair --url wss://operator:<pwd>@gateway/ws \
|
|
161
|
+
# Operator:
|
|
162
|
+
aiworker pair --url 'wss://operator:<pwd>@gateway/ws' \
|
|
172
163
|
--worker-url http://<worker-host>:9217 \
|
|
173
164
|
--bootstrap-token wtk_xxx \
|
|
174
165
|
--display-name production-1
|
|
175
166
|
```
|
|
176
167
|
|
|
177
|
-
> 限制:gateway
|
|
168
|
+
> 限制:gateway 必须 inbound 到 worker `:9217` 验 token。worker 在 NAT 后用 OTP 替代。
|
|
178
169
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
## 路径 4:docker auto-launch
|
|
170
|
+
### docker auto-launch
|
|
182
171
|
|
|
183
172
|
需要 gateway 启用 `AIWORKER_GATEWAY_CAN_LAUNCH=true` + `docker.sock:ro` mount。
|
|
184
173
|
|
|
@@ -187,49 +176,46 @@ aiworker fleet launch --display-name demo
|
|
|
187
176
|
# gateway supervisor 自动 docker run + scrape bootstrap token + pair
|
|
188
177
|
```
|
|
189
178
|
|
|
190
|
-
详见 [`docs/deployment.md`](docs/deployment.md)
|
|
179
|
+
详见 [`docs/deployment.md`](docs/deployment.md) supervisor overlay。
|
|
191
180
|
|
|
192
181
|
---
|
|
193
182
|
|
|
194
|
-
## Operator
|
|
183
|
+
## Operator cheat sheet
|
|
195
184
|
|
|
196
185
|
```sh
|
|
197
186
|
# fleet 状态
|
|
198
|
-
aiworker fleet list
|
|
199
|
-
aiworker fleet
|
|
200
|
-
aiworker fleet remove <workerId> # 摘除(deviceToken 立即失效)
|
|
187
|
+
aiworker fleet list # 谁在线
|
|
188
|
+
aiworker fleet remove <workerId> # 摘除(deviceToken 立即失效)
|
|
201
189
|
|
|
202
|
-
#
|
|
190
|
+
# chat(流式 NDJSON)
|
|
203
191
|
aiworker chat <workerId> 'hello'
|
|
204
192
|
aiworker chat <workerId> '继续' --conversation-id <prev-id>
|
|
205
193
|
|
|
206
194
|
# 配置(乐观锁必须带 --if-match)
|
|
207
|
-
aiworker config get <workerId>
|
|
195
|
+
aiworker config get <workerId> # 读出含 version
|
|
208
196
|
aiworker config set <workerId> "$(cat new.json)" --if-match <version>
|
|
209
197
|
|
|
210
|
-
# Token
|
|
198
|
+
# Token 轮换
|
|
211
199
|
aiworker token rotate <workerId>
|
|
212
200
|
|
|
213
201
|
# OTP 审批
|
|
214
|
-
aiworker enroll list
|
|
215
|
-
aiworker enroll approve <OTP>
|
|
216
|
-
aiworker enroll reject <OTP>
|
|
202
|
+
aiworker enroll list / approve <OTP> / reject <OTP>
|
|
217
203
|
|
|
218
204
|
# 日志订阅
|
|
219
205
|
aiworker logs <workerId> --follow --tail 200
|
|
220
206
|
|
|
221
|
-
#
|
|
207
|
+
# Per-tool approvals
|
|
222
208
|
aiworker approvals list
|
|
223
|
-
aiworker approvals grant <workerId> <taskId> <toolCallId>
|
|
209
|
+
aiworker approvals grant <workerId> <taskId> <toolCallId> # allow
|
|
224
210
|
aiworker approvals grant <workerId> <taskId> <toolCallId> --deny
|
|
225
211
|
|
|
226
|
-
#
|
|
212
|
+
# Cron
|
|
227
213
|
aiworker schedule list <workerId>
|
|
228
|
-
aiworker schedule add
|
|
214
|
+
aiworker schedule add <workerId> --expression '0 9 * * *' --prompt '早报' --channel web --chat-id daily
|
|
229
215
|
aiworker schedule remove <workerId> <jobId>
|
|
230
216
|
```
|
|
231
217
|
|
|
232
|
-
|
|
218
|
+
Operator 端首次需写 `~/.aiworker/aim.json`:
|
|
233
219
|
|
|
234
220
|
```sh
|
|
235
221
|
mkdir -p ~/.aiworker
|
|
@@ -244,22 +230,89 @@ EOF
|
|
|
244
230
|
chmod 600 ~/.aiworker/aim.json
|
|
245
231
|
```
|
|
246
232
|
|
|
247
|
-
|
|
233
|
+
> gateway 同机 loopback:用 `ws://127.0.0.1:9218/ws`,无需 basicauth/token(loopback bypass)。
|
|
248
234
|
|
|
249
235
|
---
|
|
250
236
|
|
|
251
|
-
## Worker 配 LLM
|
|
237
|
+
## Worker 配 LLM executor
|
|
238
|
+
|
|
239
|
+
新 worker 默认 `executor: { engine: 'http', variant: 'default' }` 但缺 OpenAI key 会失败。配真实 LLM:
|
|
240
|
+
|
|
241
|
+
### 选 1:claude-code(本地已 `claude login`)
|
|
252
242
|
|
|
253
243
|
```sh
|
|
254
|
-
|
|
255
|
-
aiworker config
|
|
244
|
+
# 1. 拿 worker 当前 config + version
|
|
245
|
+
aiworker config get <workerId>
|
|
246
|
+
# → { "version": 1, "config": {...} }
|
|
247
|
+
|
|
248
|
+
# 2. 切到 claude-code default variant(model=sonnet, timeout=120s)
|
|
249
|
+
NEW='{
|
|
250
|
+
"brains": [],
|
|
251
|
+
"brainWriteTarget": "",
|
|
252
|
+
"brainRetrieval": "first-match",
|
|
253
|
+
"executor": { "engine": "claude-code", "variant": "default" },
|
|
254
|
+
"channels": [],
|
|
255
|
+
"evolution": { "enabled": false, "observationRetentionDays": 7 }
|
|
256
|
+
}'
|
|
257
|
+
aiworker config set <workerId> "$NEW" --if-match 1
|
|
258
|
+
|
|
259
|
+
# 3. chat 验证
|
|
260
|
+
aiworker chat <workerId> '请用中文回我一句话'
|
|
261
|
+
# {"kind":"accepted",...}
|
|
262
|
+
# {"kind":"chat.message","payload":{"role":"assistant","content":"...claude 真实回复..."}}
|
|
263
|
+
# {"kind":"done","payload":{"finishReason":"stop"}}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
要求:worker 进程所在主机能跑 `claude` CLI(PATH 含 `~/.claude/local/claude` 或 npm 全局),且 `~/.claude.json` 有效(`claude login` 已完成)。
|
|
267
|
+
|
|
268
|
+
`opus-plan` variant 切到 opus + plan 模式:`"executor": { "engine": "claude-code", "variant": "opus-plan" }`。
|
|
269
|
+
|
|
270
|
+
### 选 2:OpenAI 兼容 (OpenAI / DeepSeek / SiliconFlow / etc.)
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"executor": {
|
|
275
|
+
"engine": "http",
|
|
276
|
+
"variant": "default",
|
|
277
|
+
"overrides": {
|
|
278
|
+
"baseUrl": "https://api.deepseek.com/v1",
|
|
279
|
+
"model": "deepseek-chat",
|
|
280
|
+
"apiKeyRef": "secret://openai/deepseek"
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
256
284
|
```
|
|
257
285
|
|
|
258
|
-
|
|
286
|
+
`apiKeyRef` 必须先 register 到 worker 的 `SecretsVault`(POST `/api/worker/secrets`);明文 secret 永不进 `worker_config.configJson`。
|
|
287
|
+
|
|
288
|
+
### 选 3:ACP gemini / qwen
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{ "executor": { "engine": "acp", "variant": "gemini" } }
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
要求:worker 主机有 `gemini` CLI(`npm install -g @google/generative-ai-cli`)+ `~/.gemini/` auth。
|
|
295
|
+
|
|
296
|
+
### 选 4:codex / cursor / mcp
|
|
297
|
+
|
|
298
|
+
详见 [`docs/executor-engines.md`](docs/executor-engines.md)(含每 engine 安装/auth recipe)。
|
|
259
299
|
|
|
260
300
|
---
|
|
261
301
|
|
|
262
|
-
##
|
|
302
|
+
## Architecture & deployment
|
|
303
|
+
|
|
304
|
+
详见:
|
|
305
|
+
- [`docs/architecture.md`](docs/architecture.md) — monorepo 布局、数据流、安全模型、env 全表
|
|
306
|
+
- [`docs/gateway.md`](docs/gateway.md) — WS 协议(METHODS / EVENTS)+ 4 enroll path 实现
|
|
307
|
+
- [`docs/deployment.md`](docs/deployment.md) — 三档部署 run book
|
|
308
|
+
- [`docs/deployment-public-https.md`](docs/deployment-public-https.md) — 可选 Cloudflare + Caddy 公网叠加层(含 BUG-007 fail-closed basicauth)
|
|
309
|
+
- [`docs/executor-engines.md`](docs/executor-engines.md) — 每 LLM engine 的 auth/install recipe
|
|
310
|
+
|
|
311
|
+
```
|
|
312
|
+
apps/{api, cli, web} + packages/{core, gateway, gateway-proto, shared, storage-sqlite, fs-layout}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
部署形态:
|
|
263
316
|
|
|
264
317
|
| 形态 | 适用 | 入口 | docker |
|
|
265
318
|
|------|------|------|--------|
|
|
@@ -267,19 +320,17 @@ aiworker config set <workerId> "$NEW" --if-match <current-version>
|
|
|
267
320
|
| **systemd**(Linux 推荐) | 服务器长跑 | `aiworker install systemd [--user\|--system]` | 无 |
|
|
268
321
|
| **docker compose** | 不愿装 bun / per-worker 隔离 | `ops/compose/docker-compose.yml`(GHCR 镜像) | 有 |
|
|
269
322
|
|
|
270
|
-
详见 [`docs/deployment.md`](docs/deployment.md);公网 HTTPS(Cloudflare + Caddy)单独叠加层在 [`docs/deployment-public-https.md`](docs/deployment-public-https.md)。
|
|
271
|
-
|
|
272
323
|
---
|
|
273
324
|
|
|
274
325
|
## 关键 env
|
|
275
326
|
|
|
276
327
|
| 变量 | 用于 | 说明 |
|
|
277
328
|
|---|---|---|
|
|
278
|
-
| `AIWORKER_MASTER_KEY` | gateway / worker | 64 hex;丢了 fleet.db 解不开 — **必须组织级离线备份** |
|
|
279
|
-
| `INTERNAL_SHARED_SECRET` | gateway / 远程 operator | ≥16 chars;远程
|
|
329
|
+
| `AIWORKER_MASTER_KEY` | gateway / worker | 64 hex;丢了 fleet.db / worker.db 解不开 — **必须组织级离线备份** |
|
|
330
|
+
| `INTERNAL_SHARED_SECRET` | gateway / 远程 operator | ≥16 chars;远程 operator bearer |
|
|
280
331
|
| `AIWORKER_JOIN_TOKEN` | gateway / self-enroll worker | self-enroll 模式触发;与 INTERNAL_SHARED_SECRET 解耦 |
|
|
281
332
|
| `AIWORKER_GATEWAY_URL` | worker | OTP / self-enroll 模式连入口 |
|
|
282
|
-
| `AIWORKER_DISPLAY_NAME` | worker | operator
|
|
333
|
+
| `AIWORKER_DISPLAY_NAME` | worker | operator 端识别用(默认 hostname) |
|
|
283
334
|
| `AIWORKER_HOME` | gateway / worker | 默认 `~/.aiworker` |
|
|
284
335
|
| `WORKER_DB_PATH` | worker | 默认 `$AIWORKER_HOME/worker.db` |
|
|
285
336
|
| `AIWORKER_FLEET_DB_PATH` | gateway | 默认 `$AIWORKER_HOME/fleet.db` |
|
|
@@ -287,19 +338,18 @@ aiworker config set <workerId> "$NEW" --if-match <current-version>
|
|
|
287
338
|
| `PORT` | worker | 默认 `9217` |
|
|
288
339
|
| `AIWORKER_ENROLL_OTP_TTL_SEC` | gateway | OTP 过期秒数,默认 300,[30, 3600] |
|
|
289
340
|
|
|
290
|
-
|
|
341
|
+
完整列表:`apps/api/.env.example` + `ops/compose/.env.example`。
|
|
291
342
|
|
|
292
343
|
---
|
|
293
344
|
|
|
294
|
-
##
|
|
345
|
+
## 故障排查(高频)
|
|
295
346
|
|
|
296
347
|
| 现象 | 原因 | 修法 |
|
|
297
348
|
|---|---|---|
|
|
298
349
|
| `aiworker fleet list` → `WebSocket Expected 101 status code` | aim.json `gatewayUrl` 缺 `/ws` 或 basicauth | 重写 `~/.aiworker/aim.json`(见上) |
|
|
299
|
-
|
|
|
300
|
-
|
|
|
301
|
-
|
|
302
|
-
详见 [`docs/deployment-public-https.md` § Troubleshooting](docs/deployment-public-https.md)。
|
|
350
|
+
| 公网 `/health` 返回 401 | Caddy basicauth | `curl -u operator:<pwd> https://your-gateway/health` |
|
|
351
|
+
| OTP enroll 后 `aiworker chat` `executor error: OpenAI API key is not configured` | worker 没配 LLM | 走"Worker 配 LLM executor"段,切 claude-code / 配 OpenAI key |
|
|
352
|
+
| systemd `aiworker-gateway` exit 1 `gateway 入口未找到` | 用了 0.2.0 旧 cli | `bun install -g @zonease/aiworker-cli@latest`(≥0.2.1)+ restart |
|
|
303
353
|
|
|
304
354
|
---
|
|
305
355
|
|
|
@@ -308,10 +358,8 @@ aiworker config set <workerId> "$NEW" --if-match <current-version>
|
|
|
308
358
|
- **fleet.db / worker.db 物理隔离**:gateway 永不存 worker 的业务数据
|
|
309
359
|
- **AES-256-GCM** 加密 `registered_workers.apiTokenEnc` + `worker_secrets`
|
|
310
360
|
- **timing-safe** bearer 比较
|
|
311
|
-
- **5 channel webhook 强制验签**(Telegram
|
|
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)。
|
|
361
|
+
- **5 channel webhook 强制验签**(Telegram / WhatsApp / Lark / LINE / Web binding token)
|
|
362
|
+
- **Caddy 路径分流**:`/ws` basicauth 守 operator + 已配对 worker,`/enroll-ws` 仅接受 OTP submit;fail-closed(缺 `/etc/caddy/auth.snippet` 直接拒启动,BUG-007)
|
|
315
363
|
|
|
316
364
|
---
|
|
317
365
|
|
|
@@ -335,7 +383,7 @@ bun run test # 全工作区
|
|
|
335
383
|
bun run lint
|
|
336
384
|
```
|
|
337
385
|
|
|
338
|
-
文档系统(PMA):[`docs/plan/`](docs/plan/)
|
|
386
|
+
文档系统(PMA workflow):[`docs/plan/`](docs/plan/) 历史方案、[`docs/task/`](docs/task/) task 跟踪、[`docs/changelog.md`](docs/changelog.md) 发布日志。新功能按 `/pma` skill 走 investigate → proposal → implement 三阶段。
|
|
339
387
|
|
|
340
388
|
---
|
|
341
389
|
|
|
@@ -350,11 +398,12 @@ bun run lint
|
|
|
350
398
|
| Module | Status |
|
|
351
399
|
|---|---|
|
|
352
400
|
| Gateway WS 控制面 | ✅ Production |
|
|
353
|
-
| 4 enrollment paths | ✅ Production |
|
|
354
|
-
|
|
|
355
|
-
| 5 channel webhooks | ✅ Production |
|
|
356
|
-
| Cron / approvals / hot-reload | ✅ Production |
|
|
357
|
-
|
|
|
358
|
-
|
|
|
401
|
+
| 4 enrollment paths(OTP / self-enroll / pair / launch) | ✅ Production |
|
|
402
|
+
| 6 LLM engines(http / claude-code / acp / codex / cursor / mcp) | ✅ Production |
|
|
403
|
+
| 5 channel webhooks(Telegram / WhatsApp / Lark / LINE / Web) | ✅ Production |
|
|
404
|
+
| Cron / per-tool approvals / hot-reload | ✅ Production |
|
|
405
|
+
| 单 `aiworker` CLI(PLAN-020 / FEAT-028) | ✅ GA |
|
|
406
|
+
| npm 发布(`@zonease/aiworker-cli`) | ✅ Latest 0.2.1 |
|
|
407
|
+
| In-process gateway(npm install 场景,REFACTOR-004) | ✅ GA |
|
|
359
408
|
| Web SPA pending UI | 🔜 Stage-2 |
|
|
360
409
|
| Multi-host HA | 🔜 Stage-2 |
|