@zonease/aiworker-cli 0.9.1 → 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.
Files changed (3) hide show
  1. package/README.md +177 -381
  2. package/aiworker-bun.js +293 -289
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,492 +1,288 @@
1
1
  # AIWorker
2
2
 
3
- 轻量自托管 **Project Brain + Worker/Fleet aggregation runtime**。
3
+ **English** · [简体中文](./README.zh-CN.md)
4
4
 
5
- AIWorker 负责 Project Brain、worker identity/state、gateway routing、fleet
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
- 这里的 Project worker host/workspace 上服务的业务作用域,不等同于
12
- software project。developer Soul 可以把 scope 绑定到代码仓库;HR Soul 可以把
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
- Operator / Admin │
23
- │ $ aiworker fleet ... $ aiworker gateway ... │
24
- └───────────────────┬──────────────────────────────────────────┘
25
- │ WS /ws (basicauth) + /enroll-ws (OTP)
26
-
27
- ┌──────────────────────────────────────────────────────────────┐
28
- AIWorker Gateway (control plane) │
29
- fleet.db: registered_workers + audit_events │
30
- 只持指针 / presence / routing / audit ── 不持 brain / 对话 │
31
- └───────────────────┬──────────────────────────────────────────┘
32
- │ WS frame relay
33
- ┌────────────────────┼────────────────────┐
34
- ▼ ▼ ▼
35
- ┌──────────┐ ┌──────────┐ ┌──────────┐
36
- Worker A │ │ Worker B │ │ Worker N │
37
- └────┬─────┘ └────┬─────┘ └────┬─────┘
38
- │ │ │
39
- ▼ (data plane, per worker) ...
40
- ┌─────────────────────────────────────────────────────────────┐
41
- worker.db (identity + config + conversations, AES-256-GCM) │
42
- Project Brain (filesystem 权威,5 类资产) │
43
- Thin Executor Adapter → External Engine │
44
- │ health / run / stream / cancel / resume │
45
- │ └─→ user/host MCP / skills / │
46
- │ plugins / auth / sessions │
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
- 详见 [`docs/architecture.md` § Product Positioning](docs/architecture.md#product-positioning)(同一份 mermaid 图,operator dataplane 视角分开画);部署形态对照见 [`docs/deployment.md`](docs/deployment.md)
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
- ## 🚀 30 秒 demo
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 # 或 npm install -g
109
-
110
- export AIWORKER_GATEWAY_URL='wss://your-gateway.example/'
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
- ## Install
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
- bun install -g @zonease/aiworker-cli
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
- AIWorker CLI Bun-native:`npx` / `npm install -g` 不会把 runtime 改成 Node。没有 Bun 时,CLI 会提示安装 Bun 或改用 GitHub Releases standalone binary。binary 跑在 `~/.bun/bin/aiworker` `$(npm bin -g)/aiworker`。第一次跑任意命令时自动 mint master key 写到 `~/.aiworker/.env`(chmod 0600)。
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
- **项目级 worker**(PLAN-023,可选):`aiworker up --soul developer` 会在当前目录 `<cwd>/.aiworker/` 落 Project Brain layout(每个 worker-bound business scope 一份独立 worker.db / master key / persona / brain skills;不要求当前目录是 git repo,也不要求 scope 是软件工程项目),随后完成 brain/runtime 静态预检并启动本地 HTTP/admin。executor(claude / codex / cursor / Hermes / OpenClaw 等)默认是 operator 自己提供的外部运行时,可能加载 user/host 级 MCP、skills、plugins、auth 和 native sessions;AIWorker 不默认做 executor isolation。`aiworker scope` 诊断当前命中的 layout;显式拆步时仍可用 `aiworker init` / `aiworker doctor` / `aiworker serve`。详见 [docs/cli.md §`aiworker up`](docs/cli.md)。
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
- cd ~/code/my-project
168
- aiworker up --soul developer --port 9217
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
- ```sh
174
- git clone https://github.com/ZonEaseTech/aiworker
175
- cd aiworker && bun install
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
- 下面所有 `aiworker ...` 命令在本地开发态等价 `bun apps/cli/src/aiworker.ts ...`。
98
+ Full CLI reference: [`docs/cli.md`](docs/cli.md).
180
99
 
181
100
  ---
182
101
 
183
- ## 4 种入网路径
102
+ ## Start a fleet (multiple workers + gateway)
184
103
 
185
- | 场景 | | Worker 端凭证 | Operator 介入 |
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
- ### OTP(推荐)
106
+ ### 1) Start the gateway
193
107
 
194
- Worker:
195
108
  ```sh
196
- export AIWORKER_GATEWAY_URL='wss://your-gateway.example/'
197
- export AIWORKER_DISPLAY_NAME='my-laptop' # 可选,默认 hostname
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
- Worker:
210
- ```sh
211
- export AIWORKER_GATEWAY_URL='wss://operator:<basicauth-pwd>@your-gateway.example/ws'
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
- > ⚠️ URL basicauth + JOIN_TOKEN fleet 共享 secret,泄露面大。CI 可接受,朋友机器不要给。
219
-
220
- ### 手动 pair(高安全)
117
+ When binding to a non-loopback host you must set:
221
118
 
222
119
  ```sh
223
- # Worker:
224
- aiworker serve --gateway 'wss://operator:<pwd>@gateway/ws'
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
- > 限制:gateway 必须 inbound worker `:9217` 验 token。worker 在 NAT 后用 OTP 替代。
124
+ Public deployment + Caddy basicauth template: [`docs/deployment-public-https.md`](docs/deployment-public-https.md).
235
125
 
236
- ### docker auto-launch
126
+ ### 2) Enroll a worker (OTP recommended)
237
127
 
238
- 需要 gateway 启用 `AIWORKER_GATEWAY_CAN_LAUNCH=true` + `docker.sock:ro` mount。
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
- aiworker fleet launch --display-name demo
242
- # gateway supervisor 自动 docker run + scrape bootstrap token + pair
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
- # fleet 状态
253
- aiworker fleet list # 谁在线
254
- aiworker fleet remove <workerId> # 摘除(deviceToken 立即失效)
255
-
256
- # chat(流式 NDJSON)
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
- # Per-tool approvals
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
- Operator 端首次需写 `~/.aiworker/aiworker.json`:
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
- > gateway 同机 loopback:用 `ws://127.0.0.1:9218/ws`,无需 basicauth/token(loopback bypass)。
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
- # 1. 拿 worker 当前 config + version
311
- aiworker fleet config get <workerId>
312
- # { "version": 1, "config": {...} }
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
- `opus-plan` variant 切到 opus + plan 模式:`"executor": { "engine": "claude-code", "variant": "opus-plan" }`。
348
-
349
- ### 2:OpenAI 兼容 (OpenAI / DeepSeek / SiliconFlow / etc.)
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
- ### 3:ACP gemini / qwen
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
- ```json
370
- { "executor": { "engine": "acp", "variant": "gemini" } }
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
- ## Architecture & deployment
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
- apps/{api, cli, web} + packages/{core, gateway, gateway-proto, shared, storage-sqlite, fs-layout}
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
- | 形态 | 适用 | 入口 | docker |
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
- ## 关键 env
215
+ ## Deployment shapes
405
216
 
406
- | 变量 | 用于 | 说明 |
217
+ | Shape | When | Entry |
407
218
  |---|---|---|
408
- | `AIWORKER_MASTER_KEY` | gateway / worker | 64 hex;丢了 fleet.db / worker.db 解不开 **必须组织级离线备份** |
409
- | `INTERNAL_SHARED_SECRET` | gateway / 远程 operator | ≥16 chars;远程 operator bearer |
410
- | `AIWORKER_JOIN_TOKEN` | gateway / self-enroll worker | self-enroll 模式触发;与 INTERNAL_SHARED_SECRET 解耦 |
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
- - **fleet.db / worker.db 物理隔离**:gateway 永不存 worker 的业务数据
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
- ## Backup checklist
242
+ ## More
450
243
 
451
- - **`AIWORKER_MASTER_KEY`**离线保管。丢失 = fleet.db 全部 worker 必须重 enroll
452
- - **fleet.db**gateway
453
- - **每个 worker worker.db** worker 自己的卷
454
- - **`INTERNAL_SHARED_SECRET`**operator 凭证
455
- - **`AIWORKER_JOIN_TOKEN`**fleet 共享 secret(self-enroll 用)
456
- - **Caddy basicauth bcrypt hash** — `/etc/caddy/auth.snippet`
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
- bun install
464
- bun run typecheck # 9 packages 全过
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
- 文档系统(PMA workflow):[`docs/plan/`](docs/plan/) 历史方案、[`docs/task/`](docs/task/) task 跟踪、[`docs/changelog.md`](docs/changelog.md) 发布日志。新功能按 `/pma` skill 走 investigate → proposal → implement 三阶段。
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
- ## License
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
- ## Status
272
+ CLI npm latest: **0.9.3**.
480
273
 
481
274
  | Module | Status |
482
275
  |---|---|
483
- | Gateway WS 控制面 | ✅ Production |
484
- | 4 enrollment paths(OTP / self-enroll / pair / launch) | ✅ Production |
485
- | 6 LLM engines(http / claude-code / acp / codex / cursor / mcp) | ✅ Production |
486
- | 5 channel webhooks(Telegram / WhatsApp / Lark / LINE / Web) | Production |
487
- | Cron / per-tool approvals / hot-reload | Production |
488
- | `aiworker` CLI(PLAN-020 / FEAT-028) | GA |
489
- | npm 发布(`@zonease/aiworker-cli`) | Latest 0.2.1 |
490
- | In-process gateway(npm install 场景,REFACTOR-004) | ✅ GA |
491
- | Web SPA pending UI | 🔜 Stage-2 |
492
- | Multi-host HA | 🔜 Stage-2 |
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