@zonease/aiworker-cli 0.9.2 → 0.9.3
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 +177 -381
- package/aiworker-bun.js +293 -289
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,492 +1,288 @@
|
|
|
1
1
|
# AIWorker
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**English** · [简体中文](./README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
presence、audit 和 admin surface。Executor 是 bring-your-own 外部 agent runtime:
|
|
7
|
-
Codex、Claude Code、Hermes、OpenClaw、Cursor 等继续拥有自己的 MCP、skills、
|
|
8
|
-
plugins、auth、sandbox、approval 和 native sessions,AIWorker 只通过薄 adapter
|
|
9
|
-
调用、观察和聚合它们。
|
|
5
|
+
Self-hosted, lightweight **Project Brain + Worker/Fleet aggregation runtime**.
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
scope 绑定到岗位、候选人池或简历库;legal、finance、ops 等 Soul 也应以各自
|
|
14
|
-
业务对象、资料、审核和归档流程为中心建模。
|
|
15
|
-
|
|
16
|
-
工作站、服务器、k8s pod、docker container 都能跑成一个 worker 加入同一个 fleet。Operator 用一个 CLI 控制所有 worker。
|
|
17
|
-
|
|
18
|
-
## Operator topology(一图 canonical)
|
|
7
|
+
- **Worker** owns the Project Brain (filesystem is the source of truth), worker.db, and conversations. External executors (Codex / Claude Code / Hermes / OpenClaw / Cursor, etc.) are invoked through a thin adapter only.
|
|
8
|
+
- **Gateway is an optional control plane**: a single worker runs without one. With multiple workers, the gateway aggregates presence, routing, and audit — it never holds brain or conversation data.
|
|
19
9
|
|
|
20
10
|
```text
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
11
|
+
Operator / Admin
|
|
12
|
+
| aiworker fleet ...
|
|
13
|
+
| WS basicauth + token
|
|
14
|
+
v
|
|
15
|
+
+------------------------------------------------+
|
|
16
|
+
| AIWorker Gateway (optional control plane) |
|
|
17
|
+
| fleet.db : pointers + audit only |
|
|
18
|
+
| no brain no chat data no secrets |
|
|
19
|
+
+------+-------------+-------------+-------------+
|
|
20
|
+
v v v WS relay
|
|
21
|
+
Worker A Worker B ... Worker N
|
|
22
|
+
|
|
|
23
|
+
| a single worker also runs without a gateway
|
|
24
|
+
v
|
|
25
|
+
+------------------------------------------------+
|
|
26
|
+
| Per-worker data plane |
|
|
27
|
+
| |
|
|
28
|
+
| worker.db identity / config / chat |
|
|
29
|
+
| AES-256-GCM |
|
|
30
|
+
| |
|
|
31
|
+
| Project Brain filesystem authoritative |
|
|
32
|
+
| AGENT / SOUL / USER |
|
|
33
|
+
| memories / brain skills |
|
|
34
|
+
| policy / admission state |
|
|
35
|
+
| |
|
|
36
|
+
| Thin Adapter health / run / stream |
|
|
37
|
+
| cancel / resume |
|
|
38
|
+
| | |
|
|
39
|
+
| v invoke |
|
|
40
|
+
| External Engine |
|
|
41
|
+
| Codex / Claude Code / Hermes |
|
|
42
|
+
| OpenClaw / Cursor / ACP / MCP / HTTP |
|
|
43
|
+
| | |
|
|
44
|
+
| v loads ambient |
|
|
45
|
+
| user/host MCP / skills / plugins |
|
|
46
|
+
| auth / native sessions |
|
|
47
|
+
| (not owned by AIWorker) |
|
|
48
|
+
+------------------------------------------------+
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
要点:
|
|
53
|
-
|
|
54
|
-
- **Gateway = control plane**:fleet.db 只存 worker 指针 / presence / audit;从不缓存 conversations / messages / secrets,也不主动持有 brain 资产。
|
|
55
|
-
- **Worker = data plane**:worker.db 与 Project Brain 都在 worker 本机;fleet 视角通过 gateway WS 发指令读 worker,**不**反向 fetch worker REST。
|
|
56
|
-
- **External executor only inside the worker**:Codex / Claude Code / Hermes / OpenClaw / Cursor 等 engine 在 worker 内由薄 adapter 调用,永不被 gateway 直接接触;engine 自己持 user/host 级 MCP / skills / plugins / auth / native sessions,AIWorker 不默认隔离这些 ambient capabilities。
|
|
57
|
-
|
|
58
|
-
## Features
|
|
59
|
-
|
|
60
|
-
- **Project Brain**:每个业务作用域一份 5 类 brain 资产 — identity(`AGENT/SOUL/USER`)、memory(`MEMORY.md` + `memories/`)、brain skills(`.aiworker/skills/**`)、policy & drafts(`policy.json` / `toolsets.json` / `capability-packs.json` / `.aiworker/mcp.json`)、admission state(roadmap);filesystem 为权威,便于迁移和审计
|
|
61
|
-
- **Worker/Fleet 聚合**:gateway 管 workers、presence、audit、routing;worker 自持 worker.db、Project Brain 和外部 executor adapter
|
|
62
|
-
- **4 种入网路径**:OTP-attended(worker deployer 零凭证)/ self-enroll(unattended 批量)/ 手动 pair / docker auto-launch
|
|
63
|
-
- **WS 控制面**:operator + worker 共享同一 gateway 入口,按 path 分流(`/ws` basicauth + `/enroll-ws` OTP 专用)
|
|
64
|
-
- **Bring-your-own executor**:`http` baseline / `claude-code` / `codex` / `acp` (gemini / qwen) / `cursor` / `mcp`,外部 engine 自己管理 user/host 级能力
|
|
65
|
-
- **多 channel webhook**:Telegram / WhatsApp / Lark / LINE / Web,全部强制验签
|
|
66
|
-
- **Cron / per-tool approvals / hot-reload / fallback chain** 内建
|
|
67
|
-
- **数据物理隔离**:fleet.db(gateway)与 worker.db(每 worker)AES-256-GCM 各自加密
|
|
68
|
-
- **三档部署**:裸跑 / systemd / docker compose
|
|
51
|
+
A single worker can run standalone — the gateway is needed only when you want to aggregate multiple workers. The control plane and the data plane are physically isolated: fleet.db never stores brain / conversations / secrets, and worker.db is never reverse-fetched by the gateway. Full architecture and dual-view mermaid diagrams: [`docs/architecture.md`](docs/architecture.md). Whether this build meets the Project Brain governance node target: [`docs/governance-node-status.md`](docs/governance-node-status.md).
|
|
69
52
|
|
|
70
53
|
---
|
|
71
54
|
|
|
72
|
-
##
|
|
73
|
-
|
|
74
|
-
**目标**:本机起一个 worker,加入远端 gateway,发一条消息让 worker 用 LLM 回。
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
┌──────────────────────────┐ OTP enroll ┌──────────────────────────┐
|
|
78
|
-
│ 你的工作站 │ wss://<gateway>/ │ 远端 gateway │
|
|
79
|
-
│ │ /enroll-ws │ │
|
|
80
|
-
│ aiworker serve │ ───────────────────────► │ /root/.bun/bin/aiworker │
|
|
81
|
-
│ (workerId 自动 mint) │ │ gateway start (systemd) │
|
|
82
|
-
│ listening :9217 │ ◄─────── OTP YDCR-ZD8M ──│ │
|
|
83
|
-
│ │ │ fleet.db │
|
|
84
|
-
└──────────┬───────────────┘ └─────┬────────────────────┘
|
|
85
|
-
│ │
|
|
86
|
-
│ ┌─────────────────────────────────────────────┴──┐
|
|
87
|
-
│ │ Step 4: operator 在 gateway 同机 loopback │
|
|
88
|
-
│ │ ws://127.0.0.1:9218/ws (空 token bypass) │
|
|
89
|
-
│ │ $ aiworker fleet enroll list │
|
|
90
|
-
│ │ $ aiworker fleet enroll approve YDCR-ZD8M │
|
|
91
|
-
│ └─────────────────────────────────────────────┬──┘
|
|
92
|
-
│ │
|
|
93
|
-
│ ◄─────── enrollment.approved (deviceToken) ────┤
|
|
94
|
-
│ worker.online=true 写 fleet.db │
|
|
95
|
-
│ │
|
|
96
|
-
│ Step 6: chat (operator → gateway → worker) │
|
|
97
|
-
│ ◄─────── chat.send 'hello' ────────────────────┤
|
|
98
|
-
│ orchestrator → executor (claude-code) │
|
|
99
|
-
│ orchestrator → ... → done │
|
|
100
|
-
├───── chat.message echo ──────────────────────► │
|
|
101
|
-
▼ ▼
|
|
102
|
-
pkill / SIGTERM fleet.db 持久化
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
**Worker 端**(你的工作站,零 fleet 凭证):
|
|
55
|
+
## Install
|
|
106
56
|
|
|
107
57
|
```sh
|
|
108
|
-
bun install -g @zonease/aiworker-cli
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
export AIWORKER_DISPLAY_NAME='my-laptop'
|
|
112
|
-
aiworker serve
|
|
58
|
+
bun install -g @zonease/aiworker-cli
|
|
59
|
+
# or `bunx @zonease/aiworker-cli --help` (when Bun is already installed)
|
|
60
|
+
# or `npx` / `npm install -g` (Bun is still required at runtime)
|
|
113
61
|
```
|
|
114
62
|
|
|
115
|
-
|
|
63
|
+
The CLI is Bun-native. The first run mints a master key and writes it to `~/.aiworker/.env` (chmod 0600). **The master key must be backed up offline at the org level** — if it is lost, worker.db / fleet.db cannot be decrypted and every worker must re-enroll.
|
|
116
64
|
|
|
117
|
-
|
|
118
|
-
┌────────────────────────────────────────────────────────────────────────────┐
|
|
119
|
-
│ ⚠️ AIWORKER first-run setup │
|
|
120
|
-
│ AIWORKER_MASTER_KEY (写入 ~/.aiworker/.env, chmod 0600) │
|
|
121
|
-
│ <64 hex chars — 离线备份> │
|
|
122
|
-
└────────────────────────────────────────────────────────────────────────────┘
|
|
123
|
-
[worker] id=w_ntssfzwwzzq0
|
|
124
|
-
[worker] AIWORKER_BOOTSTRAP_TOKEN=wtk_VhW4ea1JrfCJFdSQ...
|
|
125
|
-
√ [aiworker serve] worker listening on :9217 (config v1)
|
|
126
|
-
i [aiworker serve] OTP enrolling to wss://your-gateway.example/enroll-ws
|
|
127
|
-
┌─────────────────────┐
|
|
128
|
-
│ OTP: YDCR-ZD8M │
|
|
129
|
-
│ expires in 300s │
|
|
130
|
-
└─────────────────────┘
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
**Operator 端**(gateway 主机或 basicauth 远端):
|
|
134
|
-
|
|
135
|
-
```sh
|
|
136
|
-
aiworker fleet enroll list # 看 pending OTP
|
|
137
|
-
aiworker fleet enroll approve YDCR-ZD8M # ✔ 已批准
|
|
138
|
-
aiworker fleet list # online: true
|
|
139
|
-
aiworker fleet chat w_ntssfzwwzzq0 'hello' # NDJSON 流式输出
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
完整端到端实测见 [docs/changelog.md](docs/changelog.md) 11:50 条目。
|
|
65
|
+
Full install and per-platform binaries: [`docs/deployment.md`](docs/deployment.md).
|
|
143
66
|
|
|
144
67
|
---
|
|
145
68
|
|
|
146
|
-
##
|
|
69
|
+
## Start a worker (single host, no gateway)
|
|
147
70
|
|
|
148
|
-
|
|
71
|
+
The most common path: turn the current business directory into a worker scope, start a local server + admin UI, and chat through the CLI. **No fleet credentials required.**
|
|
149
72
|
|
|
150
73
|
```sh
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
# 已安装 Bun 时也可免全局安装:
|
|
154
|
-
bunx @zonease/aiworker-cli --help
|
|
155
|
-
|
|
156
|
-
# npm / npx 也可作为分发入口,但运行时仍需要 bun 在 PATH:
|
|
157
|
-
npx @zonease/aiworker-cli --help
|
|
158
|
-
npm install -g @zonease/aiworker-cli
|
|
74
|
+
cd ~/code/my-project
|
|
75
|
+
aiworker up --soul developer # one shot: init + executor select + doctor + serve
|
|
159
76
|
```
|
|
160
77
|
|
|
161
|
-
|
|
78
|
+
`aiworker up` lays down the Project Brain layout under `<cwd>/.aiworker/` (worker.db, master key, persona, brain skills), runs the preflight checks, and starts the worker HTTP/admin server (default `:9217`). Pick a Soul from `developer` / `hr-recruiting` / `finance-ops` / `qa-reviewer` / `general-assistant` — Souls shape persona / risk preferences / default brief sections; governance kernel behavior is the same across all Souls.
|
|
162
79
|
|
|
163
|
-
|
|
164
|
-
新项目默认使用安全的 `http/default` stub executor;准备好 Codex / Claude 等本机 CLI 后,用 `aiworker executor select --engine codex --apply` 显式切换 task executor,再用 `aiworker executor doctor --engine codex` 检查 engine CLI 和可选 project executor overlay。`.aiworker/executor-capabilities.json` 只是 bootstrap hint / best-effort projection helper,不是 executor effective capability 的完整来源。
|
|
80
|
+
Step-by-step alternative:
|
|
165
81
|
|
|
166
82
|
```sh
|
|
167
|
-
|
|
168
|
-
aiworker
|
|
83
|
+
aiworker init --soul developer # only lay out files
|
|
84
|
+
aiworker executor select --engine claude-code --apply # pick executor (see "Configure the LLM" below)
|
|
85
|
+
aiworker executor doctor --engine claude-code # check engine CLI + project overlay
|
|
86
|
+
aiworker doctor # overall diagnostics (PASS / WARN / INFO)
|
|
87
|
+
aiworker brain status # inspect brain assets
|
|
88
|
+
aiworker serve --port 9217 --host 127.0.0.1 # start the server
|
|
89
|
+
aiworker run --message 'hello' --chat-id demo # one-shot CLI turn (no server)
|
|
169
90
|
```
|
|
170
91
|
|
|
171
|
-
|
|
92
|
+
After it is running:
|
|
172
93
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
bun apps/cli/src/aiworker.ts <subcmd> # = aiworker <subcmd>
|
|
177
|
-
```
|
|
94
|
+
- Admin UI: `http://127.0.0.1:9217/admin/` (loopback by default; public hosts must front it with external auth — see below)
|
|
95
|
+
- Bearer token: `<scope>/.aiworker/local/bootstrap-token.txt`. REST calls must include `Authorization: Bearer <token>`.
|
|
96
|
+
- Brain and conversations stay local. The only outbound traffic is whatever the external executor itself talks to (its own LLM provider).
|
|
178
97
|
|
|
179
|
-
|
|
98
|
+
Full CLI reference: [`docs/cli.md`](docs/cli.md).
|
|
180
99
|
|
|
181
100
|
---
|
|
182
101
|
|
|
183
|
-
##
|
|
102
|
+
## Start a fleet (multiple workers + gateway)
|
|
184
103
|
|
|
185
|
-
|
|
186
|
-
|---|---|---|---|
|
|
187
|
-
| 朋友/客户/CI 临时装 worker | **OTP(推荐)** | 零(worker 不持任何 fleet 共享 secret) | 看 8 字符 OTP → approve |
|
|
188
|
-
| k8s/docker compose 批量 unattended | self-enroll | `AIWORKER_JOIN_TOKEN`(fleet 共享) | 无(自动入网) |
|
|
189
|
-
| 高安全单 worker 手动 | 手动 pair | worker 启动后输出 `wtk_xxx` bootstrap token | `aiworker fleet pair --bootstrap-token wtk_...` |
|
|
190
|
-
| docker fast-launch(gateway 同机) | `aiworker fleet launch` | gateway 自动注入 | 一行命令 |
|
|
104
|
+
The gateway aggregates multiple workers into a fleet: one operator CLI controls all of them, while each worker keeps owning its own brain, conversations, and secrets.
|
|
191
105
|
|
|
192
|
-
###
|
|
106
|
+
### 1) Start the gateway
|
|
193
107
|
|
|
194
|
-
Worker:
|
|
195
108
|
```sh
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
aiworker serve
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
Operator:
|
|
202
|
-
```sh
|
|
203
|
-
aiworker fleet enroll list # → pending [{ otp, workerId, displayName }]
|
|
204
|
-
aiworker fleet enroll approve <OTP>
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### self-enroll(自动化)
|
|
109
|
+
# Dev / single host: foreground
|
|
110
|
+
aiworker gateway start --host 127.0.0.1 --port 9218
|
|
208
111
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
export AIWORKER_JOIN_TOKEN='<gateway 配置的 join token>'
|
|
213
|
-
export AIWORKER_DISPLAY_NAME='ci-runner-12'
|
|
214
|
-
aiworker serve
|
|
215
|
-
# operator 端立即 aiworker fleet list 见到
|
|
112
|
+
# Server long-run: systemd
|
|
113
|
+
aiworker gateway install systemd --user
|
|
114
|
+
systemctl --user start aiworker-gateway
|
|
216
115
|
```
|
|
217
116
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
### 手动 pair(高安全)
|
|
117
|
+
When binding to a non-loopback host you must set:
|
|
221
118
|
|
|
222
119
|
```sh
|
|
223
|
-
#
|
|
224
|
-
|
|
225
|
-
# 抓 stdout 的 wtk_xxx
|
|
226
|
-
|
|
227
|
-
# Operator:
|
|
228
|
-
aiworker fleet pair --url 'wss://operator:<pwd>@gateway/ws' \
|
|
229
|
-
--worker-url http://<worker-host>:9217 \
|
|
230
|
-
--bootstrap-token wtk_xxx \
|
|
231
|
-
--display-name production-1
|
|
120
|
+
export INTERNAL_SHARED_SECRET='<≥16 chars>' # bearer for remote operators
|
|
121
|
+
# Front /ws and /admin/* with Caddy / Cloudflare Access / Logto / etc. (fail-closed)
|
|
232
122
|
```
|
|
233
123
|
|
|
234
|
-
|
|
124
|
+
Public deployment + Caddy basicauth template: [`docs/deployment-public-https.md`](docs/deployment-public-https.md).
|
|
235
125
|
|
|
236
|
-
###
|
|
126
|
+
### 2) Enroll a worker (OTP recommended)
|
|
237
127
|
|
|
238
|
-
|
|
128
|
+
The most common path — the worker side carries no fleet credentials, the operator approves an 8-character OTP:
|
|
239
129
|
|
|
240
130
|
```sh
|
|
241
|
-
|
|
242
|
-
|
|
131
|
+
# Worker side:
|
|
132
|
+
aiworker init --soul developer
|
|
133
|
+
printf '%s\n' \
|
|
134
|
+
"AIWORKER_GATEWAY_URL=wss://your-gateway.example/" \
|
|
135
|
+
"AIWORKER_DISPLAY_NAME=my-laptop" \
|
|
136
|
+
>> .aiworker/local/.env
|
|
137
|
+
aiworker serve
|
|
138
|
+
# stdout prints an OTP, e.g. YDCR-ZD8M
|
|
243
139
|
```
|
|
244
140
|
|
|
245
|
-
详见 [`docs/deployment.md`](docs/deployment.md) supervisor overlay。
|
|
246
|
-
|
|
247
|
-
---
|
|
248
|
-
|
|
249
|
-
## Operator cheat sheet
|
|
250
|
-
|
|
251
141
|
```sh
|
|
252
|
-
#
|
|
253
|
-
aiworker fleet list
|
|
254
|
-
aiworker fleet
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
aiworker fleet chat <workerId> 'hello'
|
|
258
|
-
aiworker fleet chat <workerId> '继续' --conversation-id <prev-id>
|
|
259
|
-
|
|
260
|
-
# 配置(乐观锁必须带 --if-match)
|
|
261
|
-
aiworker fleet config get <workerId> # 读出含 version
|
|
262
|
-
aiworker fleet config set <workerId> "$(cat new.json)" --if-match <version>
|
|
263
|
-
|
|
264
|
-
# Token 轮换
|
|
265
|
-
aiworker fleet token rotate <workerId>
|
|
266
|
-
|
|
267
|
-
# OTP 审批
|
|
268
|
-
aiworker fleet enroll list / approve <OTP> / reject <OTP>
|
|
142
|
+
# Operator side:
|
|
143
|
+
aiworker fleet enroll list # see pending OTPs
|
|
144
|
+
aiworker fleet enroll approve YDCR-ZD8M # approve
|
|
145
|
+
aiworker fleet list # the worker is now visible
|
|
146
|
+
```
|
|
269
147
|
|
|
270
|
-
|
|
271
|
-
aiworker fleet logs <workerId> --follow --tail 200
|
|
148
|
+
The other three enrollment paths (self-enroll for unattended batch setups / manual pair for high-security single-worker / docker auto-launch): [`docs/gateway.md`](docs/gateway.md).
|
|
272
149
|
|
|
273
|
-
|
|
274
|
-
aiworker fleet approvals list
|
|
275
|
-
aiworker fleet approvals grant <workerId> <taskId> <toolCallId> # allow
|
|
276
|
-
aiworker fleet approvals grant <workerId> <taskId> <toolCallId> --deny
|
|
277
|
-
|
|
278
|
-
# Cron
|
|
279
|
-
aiworker fleet schedule list <workerId>
|
|
280
|
-
aiworker fleet schedule add <workerId> --expression '0 9 * * *' --prompt '早报' --channel web --chat-id daily
|
|
281
|
-
aiworker fleet schedule remove <workerId> <jobId>
|
|
282
|
-
```
|
|
150
|
+
### 3) Operator gateway config
|
|
283
151
|
|
|
284
|
-
|
|
152
|
+
The operator side needs `~/.aiworker/aiworker.json` on first use:
|
|
285
153
|
|
|
286
154
|
```sh
|
|
287
|
-
mkdir -p ~/.aiworker
|
|
155
|
+
mkdir -p ~/.aiworker && chmod 700 ~/.aiworker
|
|
288
156
|
cat > ~/.aiworker/aiworker.json <<EOF
|
|
289
157
|
{
|
|
290
158
|
"gatewayUrl": "wss://operator:<basicauth-pwd>@your-gateway.example/ws",
|
|
291
159
|
"deviceId": "op-$(uuidgen)",
|
|
292
|
-
"deviceToken": "<INTERNAL_SHARED_SECRET>"
|
|
293
|
-
"defaultWorkerId": ""
|
|
160
|
+
"deviceToken": "<INTERNAL_SHARED_SECRET>"
|
|
294
161
|
}
|
|
295
162
|
EOF
|
|
296
163
|
chmod 600 ~/.aiworker/aiworker.json
|
|
297
164
|
```
|
|
298
165
|
|
|
299
|
-
>
|
|
166
|
+
> Same-host loopback skips basicauth and the token: just use `ws://127.0.0.1:9218/ws`.
|
|
300
167
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
## Worker 配 LLM executor
|
|
304
|
-
|
|
305
|
-
新 worker 默认 `executor: { engine: 'http', variant: 'default' }` 但缺 OpenAI key 会失败。配真实 LLM:
|
|
306
|
-
|
|
307
|
-
### 选 1:claude-code(本地已 `claude login`)
|
|
168
|
+
### 4) Common operator commands
|
|
308
169
|
|
|
309
170
|
```sh
|
|
310
|
-
#
|
|
311
|
-
aiworker fleet
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
# 2. 切到 claude-code default variant(model=sonnet, timeout=120s)
|
|
315
|
-
NEW='{
|
|
316
|
-
"brains": [
|
|
317
|
-
{
|
|
318
|
-
"id": "local-filesystem",
|
|
319
|
-
"type": "filesystem",
|
|
320
|
-
"priority": 100,
|
|
321
|
-
"readOnly": false,
|
|
322
|
-
"config": {}
|
|
323
|
-
}
|
|
324
|
-
],
|
|
325
|
-
"brainWriteTarget": "local-filesystem",
|
|
326
|
-
"brainRetrieval": "first-match",
|
|
327
|
-
"executor": { "engine": "claude-code", "variant": "default" },
|
|
328
|
-
"channels": [],
|
|
329
|
-
"evolution": { "enabled": false, "observationRetentionDays": 7 }
|
|
330
|
-
}'
|
|
331
|
-
aiworker fleet config set <workerId> "$NEW" --if-match 1
|
|
332
|
-
|
|
333
|
-
# 3. 如果是在该 worker 主机 / 项目目录内调试,可只读确认 brain source / skills / memories
|
|
334
|
-
aiworker brain status
|
|
335
|
-
aiworker brain skills
|
|
336
|
-
aiworker brain memories --limit 20
|
|
337
|
-
|
|
338
|
-
# 4. chat 验证
|
|
339
|
-
aiworker fleet chat <workerId> '请用中文回我一句话'
|
|
340
|
-
# {"kind":"accepted",...}
|
|
341
|
-
# {"kind":"chat.message","payload":{"role":"assistant","content":"...claude 真实回复..."}}
|
|
342
|
-
# {"kind":"done","payload":{"finishReason":"stop"}}
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
要求:worker 进程所在主机能跑 `claude` CLI(PATH 含 `~/.claude/local/claude` 或 npm 全局),且 `~/.claude.json` 有效(`claude login` 已完成)。
|
|
171
|
+
# State
|
|
172
|
+
aiworker fleet list
|
|
173
|
+
aiworker fleet remove <workerId>
|
|
346
174
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
```json
|
|
352
|
-
{
|
|
353
|
-
"executor": {
|
|
354
|
-
"engine": "http",
|
|
355
|
-
"variant": "default",
|
|
356
|
-
"overrides": {
|
|
357
|
-
"baseUrl": "https://api.deepseek.com/v1",
|
|
358
|
-
"model": "deepseek-chat",
|
|
359
|
-
"apiKeyRef": "secret://openai/deepseek"
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
`apiKeyRef` 必须先 register 到 worker 的 `SecretsVault`(POST `/api/worker/secrets`);明文 secret 永不进 `worker_config.configJson`。
|
|
175
|
+
# Chat (streaming NDJSON)
|
|
176
|
+
aiworker fleet chat <workerId> 'hello'
|
|
177
|
+
aiworker fleet chat <workerId> 'continue' --conversation-id <prev-id>
|
|
366
178
|
|
|
367
|
-
|
|
179
|
+
# Worker config (optimistic-locked)
|
|
180
|
+
aiworker fleet config get <workerId> # returns version + config
|
|
181
|
+
aiworker fleet config set <workerId> "$NEW_CFG" --if-match <version>
|
|
368
182
|
|
|
369
|
-
|
|
370
|
-
|
|
183
|
+
# Token rotation / logs / cron / per-tool approvals
|
|
184
|
+
aiworker fleet token rotate <workerId>
|
|
185
|
+
aiworker fleet logs <workerId> --follow --tail 200
|
|
186
|
+
aiworker fleet schedule list <workerId>
|
|
187
|
+
aiworker fleet schedule add <workerId> --expression '0 9 * * *' --prompt 'morning brief' --channel web --chat-id daily
|
|
188
|
+
aiworker fleet approvals list
|
|
189
|
+
aiworker fleet approvals grant <workerId> <taskId> <toolCallId> # allow
|
|
190
|
+
aiworker fleet approvals grant <workerId> <taskId> <toolCallId> --deny
|
|
371
191
|
```
|
|
372
192
|
|
|
373
|
-
要求:worker 主机有 `gemini` CLI(`npm install -g @google/generative-ai-cli`)+ `~/.gemini/` auth。
|
|
374
|
-
|
|
375
|
-
### 选 4:codex / cursor / mcp
|
|
376
|
-
|
|
377
|
-
详见 [`docs/executor-engines.md`](docs/executor-engines.md)(含每 engine 安装/auth recipe)。
|
|
378
|
-
|
|
379
193
|
---
|
|
380
194
|
|
|
381
|
-
##
|
|
195
|
+
## Configure the LLM executor
|
|
382
196
|
|
|
383
|
-
|
|
384
|
-
- [`docs/architecture.md`](docs/architecture.md) — monorepo 布局、数据流、安全模型、env 全表
|
|
385
|
-
- [`docs/gateway.md`](docs/gateway.md) — WS 协议(METHODS / EVENTS)+ 4 enroll path 实现
|
|
386
|
-
- [`docs/deployment.md`](docs/deployment.md) — 三档部署 run book
|
|
387
|
-
- [`docs/deployment-public-https.md`](docs/deployment-public-https.md) — 可选 Cloudflare + Caddy 公网叠加层(含 BUG-007 fail-closed basicauth)
|
|
388
|
-
- [`docs/executor-engines.md`](docs/executor-engines.md) — 每 LLM engine 的 auth/install recipe
|
|
197
|
+
A new worker defaults to `executor: { engine: 'http', variant: 'default' }` and must be switched to a real LLM before it can do anything.
|
|
389
198
|
|
|
390
|
-
```
|
|
391
|
-
|
|
199
|
+
```sh
|
|
200
|
+
# Local:
|
|
201
|
+
aiworker executor select --engine claude-code --variant default --apply
|
|
202
|
+
aiworker executor doctor --engine claude-code
|
|
203
|
+
|
|
204
|
+
# Remote, for a worker in the fleet:
|
|
205
|
+
aiworker fleet config get <workerId> # grab version + current config
|
|
206
|
+
aiworker fleet config set <workerId> "$NEW" --if-match <version>
|
|
392
207
|
```
|
|
393
208
|
|
|
394
|
-
|
|
209
|
+
Supported engines: `http` (OpenAI / DeepSeek / SiliconFlow / any chat-completions-compatible API), `claude-code`, `codex`, `acp` (gemini / qwen), `cursor`, `mcp`.
|
|
395
210
|
|
|
396
|
-
|
|
397
|
-
|------|------|------|--------|
|
|
398
|
-
| **裸跑** | 开发 / CI | `aiworker gateway start` / `aiworker serve` 前台 | 无 |
|
|
399
|
-
| **systemd**(Linux 推荐) | 服务器长跑 | `aiworker gateway install systemd [--user\|--system]` | 无 |
|
|
400
|
-
| **docker compose** | 不愿装 bun / per-worker 隔离 | `ops/compose/docker-compose.yml`(GHCR 镜像) | 有 |
|
|
211
|
+
Per-engine install / auth recipes (including `claude login`, `codex auth`, secret vault writes, ACP CLI installs): [`docs/executor-engines.md`](docs/executor-engines.md).
|
|
401
212
|
|
|
402
213
|
---
|
|
403
214
|
|
|
404
|
-
##
|
|
215
|
+
## Deployment shapes
|
|
405
216
|
|
|
406
|
-
|
|
|
217
|
+
| Shape | When | Entry |
|
|
407
218
|
|---|---|---|
|
|
408
|
-
|
|
|
409
|
-
|
|
|
410
|
-
|
|
|
411
|
-
| `AIWORKER_GATEWAY_URL` | worker | OTP / self-enroll 模式连入口 |
|
|
412
|
-
| `AIWORKER_DISPLAY_NAME` | worker | operator 端识别用(默认 hostname) |
|
|
413
|
-
| `AIWORKER_HOME` | gateway / worker | 默认 `~/.aiworker` |
|
|
414
|
-
| `WORKER_DB_PATH` | worker | 默认 `$AIWORKER_HOME/worker.db` |
|
|
415
|
-
| `AIWORKER_FLEET_DB_PATH` | gateway | 默认 `$AIWORKER_HOME/fleet.db` |
|
|
416
|
-
| `AIWORKER_GATEWAY_PORT` | gateway | 默认 `9218` |
|
|
417
|
-
| `AIWORKER_GATEWAY_HOST` | gateway | 默认 `127.0.0.1`;非 loopback 需 `INTERNAL_SHARED_SECRET` |
|
|
418
|
-
| `PORT` | worker | 默认 `9217` |
|
|
419
|
-
| `AIWORKER_WORKER_HOST` | worker CLI | 默认 `127.0.0.1`;`aiworker serve --host` 可覆盖 |
|
|
420
|
-
| `AIWORKER_ADMIN_EXTERNAL_AUTH` | gateway / worker CLI | `1` / `true` 表示 `/admin/*` 已由 Caddy / Access / allowlist 等外部层保护 |
|
|
421
|
-
| `AIWORKER_ENROLL_OTP_TTL_SEC` | gateway | OTP 过期秒数,默认 300,[30, 3600] |
|
|
422
|
-
|
|
423
|
-
完整列表:`apps/api/.env.example` + `ops/compose/.env.example`。
|
|
424
|
-
|
|
425
|
-
---
|
|
219
|
+
| Bare-process | dev / CI | `aiworker gateway start` / `aiworker serve` in the foreground |
|
|
220
|
+
| systemd (Linux preferred) | server long-run | `aiworker {gateway,worker} install systemd [--user\|--system]` |
|
|
221
|
+
| docker compose | no Bun on host / per-worker isolation | `ops/compose/docker-compose.yml` (GHCR images) |
|
|
426
222
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
| 现象 | 原因 | 修法 |
|
|
430
|
-
|---|---|---|
|
|
431
|
-
| `aiworker fleet list` → `WebSocket Expected 101 status code` | aiworker.json `gatewayUrl` 缺 `/ws` 或 basicauth | 重写 `~/.aiworker/aiworker.json`(见上) |
|
|
432
|
-
| 公网 `/health` 返回 401 | Caddy basicauth | `curl -u operator:<pwd> https://your-gateway/health` |
|
|
433
|
-
| OTP enroll 后 `aiworker fleet chat` `executor error: OpenAI API key is not configured` | worker 没配 LLM | 走"Worker 配 LLM executor"段,切 claude-code / 配 OpenAI key |
|
|
434
|
-
| systemd `aiworker-gateway` exit 1 `gateway 入口未找到` | 用了 0.2.0 旧 cli | `bun install -g @zonease/aiworker-cli@latest`(≥0.2.1)+ restart |
|
|
223
|
+
See [`docs/deployment.md`](docs/deployment.md).
|
|
435
224
|
|
|
436
225
|
---
|
|
437
226
|
|
|
438
|
-
##
|
|
227
|
+
## Key environment variables
|
|
228
|
+
|
|
229
|
+
| Variable | Purpose |
|
|
230
|
+
|---|---|
|
|
231
|
+
| `AIWORKER_MASTER_KEY` | 64 hex; AES master key for worker / gateway databases; **must be backed up offline** |
|
|
232
|
+
| `INTERNAL_SHARED_SECRET` | Remote-operator bearer when the gateway is exposed publicly or off loopback (≥16 chars) |
|
|
233
|
+
| `AIWORKER_GATEWAY_URL` | Worker-side gateway URL (path + basicauth); for project workers prefer `.aiworker/local/.env` |
|
|
234
|
+
| `AIWORKER_DISPLAY_NAME` | Worker label in the fleet list (defaults to hostname); persisted per worker in `.aiworker/local/.env` |
|
|
235
|
+
| `AIWORKER_HOME` | Explicit worker state root; project scope auto-resolves to `<project>/.aiworker/local` |
|
|
236
|
+
| `AIWORKER_ADMIN_EXTERNAL_AUTH` | Set to `1` if `/admin/*` is fronted by Caddy / Cloudflare Access / Logto / etc. |
|
|
439
237
|
|
|
440
|
-
|
|
441
|
-
- **AES-256-GCM** 加密 `registered_workers.apiTokenEnc` + `worker_secrets`
|
|
442
|
-
- **timing-safe** bearer 比较
|
|
443
|
-
- **5 channel webhook 强制验签**(Telegram / WhatsApp / Lark / LINE / Web binding token)
|
|
444
|
-
- **Caddy 路径分流**:`/ws` basicauth 守 operator + 已配对 worker,`/enroll-ws` 仅接受 OTP submit;fail-closed(缺 `/etc/caddy/auth.snippet` 直接拒启动,BUG-007)
|
|
445
|
-
- **`/admin/*`(fleet + worker UI)** 与 `/ws`、`/api/*` 同等级,公网必须走 basicauth / Cloudflare Access / IP allowlist / Logto 等外部鉴权。`aiworker {gateway start, serve}` 默认挂 `/admin/*`,但在非 loopback host 上实际服务 admin bundle 时会 fail closed:要么绑定 `127.0.0.1`,要么 `--no-serve-web` / `AIWORKER_*_NO_SERVE_WEB=1` 关闭 admin,要么确认外部鉴权已覆盖后设置 `AIWORKER_ADMIN_EXTERNAL_AUTH=1`。这不是应用内登录开关,只是防止误把公开 admin 静态资源裸跑。
|
|
238
|
+
Full list: `apps/api/.env.example` + `ops/compose/.env.example`, or [`docs/architecture.md` § Environment](docs/architecture.md).
|
|
446
239
|
|
|
447
240
|
---
|
|
448
241
|
|
|
449
|
-
##
|
|
242
|
+
## More
|
|
450
243
|
|
|
451
|
-
-
|
|
452
|
-
-
|
|
453
|
-
-
|
|
454
|
-
-
|
|
455
|
-
-
|
|
456
|
-
-
|
|
244
|
+
- [`docs/architecture.md`](docs/architecture.md) — monorepo layout, data flow, security model, Brain Governance Kernel decision, full env table
|
|
245
|
+
- [`docs/governance-node-status.md`](docs/governance-node-status.md) — source-backed assessment of whether this build meets the Project Brain governance node target
|
|
246
|
+
- [`docs/gateway.md`](docs/gateway.md) — WS protocol (METHODS / EVENTS) and the four enrollment paths
|
|
247
|
+
- [`docs/deployment.md`](docs/deployment.md) — three deployment shapes runbook + troubleshooting + backup checklist
|
|
248
|
+
- [`docs/deployment-public-https.md`](docs/deployment-public-https.md) — public-internet Cloudflare + Caddy overlay (including the BUG-007 fail-closed fix)
|
|
249
|
+
- [`docs/executor-engines.md`](docs/executor-engines.md) — per-engine auth/install
|
|
250
|
+
- [`docs/cli.md`](docs/cli.md) — full CLI reference
|
|
251
|
+
- [`scripts/governance-kernel-harness.ts`](scripts/governance-kernel-harness.ts) — Brain Governance Kernel regression harness (compact / full × source-local / cli-release-local)
|
|
252
|
+
- [`docs/changelog.md`](docs/changelog.md) — release history and end-to-end test notes
|
|
457
253
|
|
|
458
254
|
---
|
|
459
255
|
|
|
460
256
|
## Development
|
|
461
257
|
|
|
462
258
|
```sh
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
bun run test
|
|
466
|
-
bun run lint
|
|
259
|
+
git clone https://github.com/ZonEaseTech/aiworker
|
|
260
|
+
cd aiworker && bun install
|
|
261
|
+
bun run typecheck && bun run lint && bun run test
|
|
467
262
|
```
|
|
468
263
|
|
|
469
|
-
|
|
264
|
+
New features go through the `/pma` skill in three stages: investigate → proposal → implement. Backend uses `/pma-bun`, frontend uses `/pma-web`, code review uses `/pma-cr`. Docs: [`docs/plan/`](docs/plan/) / [`docs/task/`](docs/task/) / [`docs/changelog.md`](docs/changelog.md).
|
|
470
265
|
|
|
471
266
|
---
|
|
472
267
|
|
|
473
|
-
##
|
|
474
|
-
|
|
475
|
-
[MIT](LICENSE) © 2026 ZonEase Tech
|
|
268
|
+
## Status
|
|
476
269
|
|
|
477
|
-
|
|
270
|
+
> Before going to production, read the conformance table and residual-boundary section in [`docs/governance-node-status.md`](docs/governance-node-status.md). Pre-1.0 the CLI / API / config does not guarantee backwards compatibility (an explicit AGENTS.md commitment).
|
|
478
271
|
|
|
479
|
-
|
|
272
|
+
CLI npm latest: **0.9.3**.
|
|
480
273
|
|
|
481
274
|
| Module | Status |
|
|
482
275
|
|---|---|
|
|
483
|
-
|
|
|
484
|
-
|
|
|
485
|
-
|
|
|
486
|
-
|
|
|
487
|
-
|
|
|
488
|
-
|
|
|
489
|
-
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
276
|
+
| Worker / Fleet control plane / 4 enrollment paths / 6 LLM engines / 5 channel webhooks / cron / per-tool approvals / hot reload | ✅ Production |
|
|
277
|
+
| Brain Governance Kernel (admission state machine + secret-scan defense + canonical memory boundary + truthful decision events + bypass detection) | ✅ GA |
|
|
278
|
+
| Governance Kernel regression harness (5×2 matrix on source + cli-release-local with 600+ checks) + long-running serve multi-turn REST regression | ✅ GA |
|
|
279
|
+
| Brain admission `memory-add` materializer | ✅ MVP (other kinds return `unsupported`; post-apply rollback not yet implemented) |
|
|
280
|
+
| Heavy LLM-backed Brain decider | 🔜 opt-in; defaults to `evaluator=heuristic` `mode=observe_only` |
|
|
281
|
+
| Cross-scope hard isolation (runtime-enforced) | 🔜 currently filesystem-conventional, not runtime-isolated |
|
|
282
|
+
| Web SPA pending UI / Multi-host HA | 🔜 Stage-2 |
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
[MIT](LICENSE) © 2026 ZonEase Tech
|