@xcompiler/cli 0.2.3 → 0.2.4

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/docs/deploy.md ADDED
@@ -0,0 +1,381 @@
1
+ # XCompiler 部署指南(deploy)
2
+
3
+ > 适用版本:`@xcompiler/cli ≥ 0.1.0`
4
+ > 两种部署方式:
5
+ >
6
+ > 1. **本地(Local)**:宿主机直接装 Node 24 + Python 3,用 `npm link` 暴露 `xcompiler` 命令。开发与单机生产首选。
7
+ > 2. **Docker**:多阶段构建的 `xcompiler:latest` 镜像 + `docker compose`。适合 CI、共享服务器、网络隔离的生产环境。
8
+
9
+ ---
10
+
11
+ ## 0. 前置条件(两种方式通用)
12
+
13
+ | 组件 | 版本 | 用途 |
14
+ |---|---|---|
15
+ | **LLM 服务** | OpenRouter API key(默认 Free mode)**或** 任一 OpenAI-compatible endpoint;Ollama 可作为本地备选 | XCompiler 的所有 Agent 推理 |
16
+ | **Git** | 任意现代版本 | XCompiler 在 workspace 内做 snapshot/revert(每个 Step 一次提交)|
17
+ | **Python 3.11+** | (仅 `sandbox=subprocess` 必需,docker 模式可省)| 沙盒内运行 pip / pytest |
18
+
19
+ > **网络要求**:沙盒在 `pip install -r requirements.txt` 时需要可达的 PyPI 镜像。建议在 shell 注入:
20
+ > `PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple`(或阿里云、内网 mirror)。
21
+
22
+ ---
23
+
24
+ ## 1. 本地部署(Local)
25
+
26
+ ### 1.1 安装 Node 与依赖
27
+
28
+ ```bash
29
+ # Linux/macOS
30
+ curl -fsSL https://nodejs.org/dist/v24.18.0/node-v24.18.0-linux-x64.tar.xz | sudo tar -xJ -C /opt
31
+ export PATH=/opt/node-v24.18.0-linux-x64/bin:$PATH
32
+ node -v # v24.x
33
+
34
+ # 克隆并装包
35
+ git clone <repo-url> xcompiler && cd xcompiler
36
+ npm ci
37
+ ```
38
+
39
+ ### 1.2 配置
40
+
41
+ ```bash
42
+ cp .env.example .env
43
+ # 编辑 .env:
44
+ # OPENROUTER_API_KEY=<your-key>
45
+ # OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
46
+ # OPENROUTER_MODEL=qwen/qwen3-coder:free
47
+
48
+ cp config.example.yaml config.yaml
49
+ # 关键字段(详见 README.md 与 docs/openrouter.md):
50
+ # llm.providers.<name>.type: openai | ollama
51
+ # llm.roles.{Planner|Architect|Coder|Tester|Debugger}: provider 名数组
52
+ # agent.sandboxes.python.mode / agent.sandboxes.typescript.mode: subprocess | docker
53
+ # agent.max_rounds_per_step / max_debug_rounds_per_step / max_debug_retries
54
+ ```
55
+
56
+ ### 1.3 构建并安装为全局命令
57
+
58
+ ```bash
59
+ npm run build # tsup -> dist/
60
+ npm link # 注册 xcompiler / xcompiler_build / xcompiler_run 到 $PATH
61
+
62
+ xcompiler --help
63
+ xcompiler --version
64
+ ```
65
+
66
+ > **不想 `npm link`?** 直接用 `npx`:`npx -p . xcompiler --help`,
67
+ > 或在开发期 `npm run dev -- build -i workspace/intake.md`(tsx 直跑 TS)。
68
+
69
+ ### 1.4 烟测
70
+
71
+ ```bash
72
+ # 1) 单测(不依赖 LLM/网络)
73
+ npm run typecheck
74
+ npm test # 完整 Vitest 回归(含本机回环网络测试)
75
+
76
+ # 2) OpenRouter endpoint 烟测(需 .env 中 OPENROUTER_API_KEY 可用)
77
+ set -a
78
+ . ./.env
79
+ set +a
80
+ curl https://openrouter.ai/api/v1/models \
81
+ -H "Authorization: Bearer $OPENROUTER_API_KEY"
82
+
83
+ # 3) 端到端编排
84
+ mkdir -p /tmp/hello-demo && cat > /tmp/hello-demo/intake.md <<'EOF'
85
+ 开发一个 Python 包 hello,提供 hello.greet(name) -> str;至少 3 个 pytest 用例。
86
+ EOF
87
+ xcompiler build -o /tmp/hello-demo -i /tmp/hello-demo/intake.md --yes
88
+ xcompiler run /tmp/hello-demo/phasePlan.json
89
+ ```
90
+
91
+ ### 1.5 升级
92
+
93
+ ```bash
94
+ cd xcompiler
95
+ git pull
96
+ npm ci
97
+ npm run build
98
+ # npm link 一次性建立的符号链接会自动指向新 dist/
99
+ ```
100
+
101
+ ### 1.6 卸载
102
+
103
+ ```bash
104
+ npm unlink -g @xcompiler/cli
105
+ rm -rf <repo>/node_modules <repo>/dist
106
+ ```
107
+
108
+ ---
109
+
110
+ ## 1.7 单文件可执行程序(无 Node 依赖)
111
+
112
+ > 适合分发到**没有 Node 环境**的目标机器。打出来的可执行程序内嵌了 Node 24 + 全部 JS 依赖,
113
+ > 终端用户只需要把单文件 `xcompiler` / `xcompiler.exe` 解压后直接运行即可。
114
+ >
115
+ > ⚠️ **注意**:单文件可执行程序仍然需要目标机器自带 **Python 3.11+ / git** —— 它们用于沙盒(pip / pytest)和 snapshot/revert。这是 XCompiler 自身的运行期依赖,不在打包范围内。
116
+
117
+ ### 1.7.1 本机原生打包与全目标发版
118
+
119
+ ```bash
120
+ # 自动识别当前 Linux/macOS 的架构,只打本机可直接运行的目标
121
+ npm run package
122
+
123
+ # 发版模式:linux-x64 / linux-arm64 / macos-arm64 / win-x64 全部打包
124
+ npm run package:all
125
+ ```
126
+
127
+ 全目标模式会由 `@yao-pkg/pkg` 按需下载各平台的 Node 基础二进制,因此首次执行需要访问其 GitHub Releases;CI 发版固定使用该入口。本机原生模式只需要当前平台的基础二进制。
128
+
129
+ 产物布局:
130
+
131
+ ```
132
+ dist/pkg/
133
+ ├── xcompiler-linux-x64/
134
+ │ ├── xcompiler # ELF 64-bit, x86_64
135
+ │ ├── README.md LICENSE NOTICE
136
+ │ ├── config.example.yaml .env.example
137
+ ├── xcompiler-linux-x64.tar.gz # 打包发布用
138
+ ├── xcompiler-linux-arm64/
139
+ │ ├── xcompiler # ELF 64-bit, aarch64
140
+ │ └── ...(同上)
141
+ ├── xcompiler-linux-arm64.tar.gz
142
+ ├── xcompiler-macos-arm64/
143
+ │ ├── xcompiler # Mach-O 64-bit, arm64(已 ad-hoc 签名)
144
+ │ └── ...
145
+ ├── xcompiler-macos-arm64.tar.gz
146
+ ├── xcompiler-win-x64/
147
+ │ ├── xcompiler.exe # PE32+, x86_64 — ⚠️ v0.1.0 未在 Windows 实机验证
148
+ │ └── ...
149
+ └── xcompiler-win-x64.zip # 需要本机有 zip 命令;否则只产生目录
150
+ ```
151
+
152
+ > **macOS Apple Silicon 原生目标为 macos-arm64**;`npm run package` 会在 Apple Silicon Mac 上自动选择该目标。
153
+ > 关键点:
154
+ >
155
+ > - `--no-bytecode` 已默认开启 — 解决 V8 bytecode snapshot 在 Node 24 readline / NDJSON HTTP 流场景下的 SIGSEGV。
156
+ > - 强制代码签名 — macOS 本机使用系统 `codesign` 执行并验证 ad-hoc 签名;Linux 交叉打包 macOS 目标时使用 `ldid`。
157
+ > - macos-x64(Intel Mac)会在 Intel Mac 上被自动选择,也可显式执行 `npm run package:macos-x64`。
158
+
159
+ ### 1.7.2 单目标打包
160
+
161
+ ```bash
162
+ npm run package:linux-x64
163
+ npm run package:linux-arm64
164
+ npm run package:macos-arm64
165
+ npm run package:macos-x64
166
+ npm run package:win-x64
167
+
168
+ # 或直接调脚本
169
+ ./scripts/package.sh linux-x64 win-x64
170
+ ./scripts/package.sh macos-arm64 macos-x64
171
+ ./scripts/package.sh native
172
+ ./scripts/package.sh all
173
+ TARGETS="linux-arm64" ./scripts/package.sh
174
+ ```
175
+
176
+ ### 1.7.3 终端用户的使用流程
177
+
178
+ **Linux**:
179
+
180
+ ```bash
181
+ tar -xzf xcompiler-linux-x64.tar.gz
182
+ cd xcompiler-linux-x64
183
+ cp config.example.yaml ~/.xc/config.yaml # 按需编辑
184
+ ./xcompiler --help
185
+ ./xcompiler build -i intake.md -o ~/myproj --yes
186
+ ./xcompiler run ~/myproj/phasePlan.json
187
+ ```
188
+
189
+ **Windows**(PowerShell):
190
+
191
+ > ⚠️ **v0.1.0 状态**:`xcompiler-win-x64.exe` 已能成功打包,但**尚未在 Windows 实机上端到端验证**(沙盒 / git snapshot / pytest 流程)。建议作为预览版试用,遇到问题请提 issue。Linux / macOS Apple Silicon 已通过完整回归。
192
+
193
+ ```powershell
194
+ Expand-Archive xcompiler-win-x64.zip
195
+ cd xcompiler-win-x64
196
+ copy config.example.yaml $env:USERPROFILE\.xc\config.yaml
197
+ .\xcompiler.exe --help
198
+ .\xcompiler.exe build -i intake.md -o C:\myproj --yes
199
+ .\xcompiler.exe run C:\myproj\phasePlan.json
200
+ ```
201
+
202
+ ### 1.7.4 实现细节(如何打的包)
203
+
204
+ | 阶段 | 工具 | 输入 → 输出 |
205
+ |---|---|---|
206
+ | 1. 构建 CJS 单包 | [tsup.pkg.config.ts](../tsup.pkg.config.ts) | `src/cli/xcompiler.ts` → `dist/pkg-build/xcompiler.cjs`(约 1.7 MB,已 inline 全部依赖)|
207
+ | 2. 跨平台编译 | `@yao-pkg/pkg` (vercel/pkg 维护活跃 fork) | `xcompiler.cjs` + 内置 Node20 → 各目标平台 native binary(约 55 MB)|
208
+ | 3. 压缩发布 | `tar` / `zip` | `xcompiler-<target>/` → `xcompiler-<target>.tar.gz` / `.zip`(约 21 MB)|
209
+ | 4. 完整性校验 | `sha256sum` / `shasum` | 所有压缩包 → `dist/pkg/SHA256SUMS` |
210
+
211
+ 脚本主入口:[scripts/package.sh](../scripts/package.sh)。配置都集中在 `tsup.pkg.config.ts` 与 `package.json -> scripts`。
212
+
213
+ > **为什么不打 `xcompiler_build` / `xcompiler_run` 单独的 exe?**
214
+ > `xcompiler` 是统一入口,`xcompiler build` ≡ `xcompiler_build`,`xcompiler run` ≡ `xcompiler_run`。一个 60 MB 的可执行文件
215
+ > 可以承担全部子命令;如果想要 `xcompiler_build.exe` 这种命名,复制重命名即可,行为不变。
216
+
217
+ > **Windows .zip 需要 zip 命令**:选择 Windows 目标但检测不到 `zip` 时,脚本会终止发版,避免留下不完整的发布产物。Linux / WSL 上可执行 `apt install zip` 安装。
218
+
219
+
220
+ ---
221
+
222
+ ## 2. Docker 部署
223
+
224
+ ### 2.1 镜像结构
225
+
226
+ [Dockerfile](../Dockerfile) 是两阶段:
227
+
228
+ | Stage | 基础镜像 | 用途 |
229
+ |---|---|---|
230
+ | `build` | `node:20-bookworm-slim` | `npm ci` + `npm run build` 生成 `dist/` |
231
+ | `runtime` | `node:20-bookworm-slim` + `python3 / python3-venv / git / docker.io / tini` | 仅装 production deps,运行 `xcompiler` |
232
+
233
+ 启动时 `tini` 做 PID 1,运行用户为 `xcompiler (uid=1000)`,工作目录 `/workspace` 以 volume 形式暴露。
234
+
235
+ ### 2.2 构建镜像
236
+
237
+ ```bash
238
+ cd xcompiler
239
+ docker build -t xcompiler:latest .
240
+ # 或带版本 tag:docker build -t xcompiler:0.1.3 -t xcompiler:latest .
241
+ ```
242
+
243
+ ### 2.3 配置文件准备
244
+
245
+ ```bash
246
+ cp .env.example .env
247
+ cp config.example.yaml config.yaml
248
+ mkdir -p workspace
249
+ ```
250
+
251
+ ### 2.4 用 docker compose 跑(推荐)
252
+
253
+ [docker-compose.yml](../docker-compose.yml) 已挂好:
254
+ - `./workspace -> /workspace`(编排产出)
255
+ - `./config.yaml -> /home/xcompiler/app/config.yaml:ro`
256
+ - `/var/run/docker.sock -> /var/run/docker.sock`(DooD:让容器内 xcompiler 能起 sibling 沙盒容器)
257
+
258
+ ```bash
259
+ # 看帮助
260
+ docker compose run --rm xcompiler --help
261
+
262
+ # 编译需求 -> phasePlan.json + 当前阶段 plan.P<N>.json(写到指定输出目录)
263
+ docker compose run --rm xcompiler build \
264
+ -i /workspace/intake.md \
265
+ -c /home/xcompiler/app/config.yaml \
266
+ -o /workspace/hello-demo \
267
+ --yes
268
+
269
+ # 执行当前阶段计划
270
+ docker compose run --rm xcompiler run \
271
+ /workspace/<project>/phasePlan.json \
272
+ -c /home/xcompiler/app/config.yaml
273
+ ```
274
+
275
+ > **DooD 的 GID 注入**:宿主 `/var/run/docker.sock` 的属主 GID 通常是 `999` 或 `998`。
276
+ > 默认 `group_add: ["999"]`;如果不同,请:
277
+ >
278
+ > ```bash
279
+ > DOCKER_GID=$(stat -c '%g' /var/run/docker.sock) docker compose run --rm xcompiler ...
280
+ > ```
281
+
282
+ ### 2.5 直接 `docker run`(不要 compose)
283
+
284
+ ```bash
285
+ docker run --rm -it \
286
+ --env-file .env \
287
+ -v "$PWD/workspace:/workspace" \
288
+ -v "$PWD/config.yaml:/home/xcompiler/app/config.yaml:ro" \
289
+ -v /var/run/docker.sock:/var/run/docker.sock \
290
+ --group-add "$(stat -c '%g' /var/run/docker.sock)" \
291
+ -w /workspace \
292
+ xcompiler:latest \
293
+ build -i /workspace/intake.md -c /home/xcompiler/app/config.yaml --yes
294
+ ```
295
+
296
+ ### 2.6 沙盒模式选择
297
+
298
+ `config.yaml -> agent.sandboxes.<language>.mode`:
299
+
300
+ | 模式 | 适用场景 | 说明 |
301
+ |---|---|---|
302
+ | `subprocess` | **容器部署唯一支持项** / 轻量本地 | 直接在宿主或 XCompiler 镜像内创建语言专属本地沙盒。简单,最快。默认推荐。 |
303
+ | `docker` | **仅限宿主部署使用** | 在宿主 docker daemon 上起 sibling 容器(image 由 `agent.sandboxes.<language>.docker.image` 指定)。 |
304
+
305
+ > ⚠️ **容器内不可使用 `mode: docker`**。XCompiler 启动时会检测运行环境(`/.dockerenv` / `/proc/1/cgroup` / `XC_IN_CONTAINER` env),若检测到在容器内且当前语言 sandbox 使用 Docker,将报错退出并提示改用 `subprocess`。
306
+ >
307
+ > 原因:DooD 路径错位、`docker.sock` GID 冲突、sibling 容器看不到 XCompiler 容器内的 `/workspace` 路径。
308
+ >
309
+ > 如确需绕过(宿主与容器路径完全一致的可控调试场景):`-e XC_IN_CONTAINER=0`。
310
+
311
+ [Dockerfile](../Dockerfile) 已预设 `ENV XC_IN_CONTAINER=1`。
312
+
313
+ ### 2.7 内置 Ollama(可选备份)
314
+
315
+ 默认配置不需要内置 Ollama。如要在同一 compose 中跑 Ollama 作为 `type: ollama` 备选 provider,
316
+ 编辑 [docker-compose.yml](../docker-compose.yml) 取消注释 `ollama` 服务与对应 volume,然后:
317
+
318
+ ```bash
319
+ docker compose up -d ollama
320
+ docker compose exec ollama ollama pull gemma4:31b
321
+ docker compose exec ollama ollama pull qwen3-coder:30b
322
+ # 在 .env 里把 OLLAMA_BASE_URL 改成 http://ollama:11434
323
+ ```
324
+
325
+ ### 2.8 升级
326
+
327
+ ```bash
328
+ cd xcompiler
329
+ git pull
330
+ docker build -t xcompiler:latest .
331
+ # compose run 会自动用新镜像;workspace 与 config.yaml 不会被 rebuild 影响
332
+ ```
333
+
334
+ ### 2.9 清理
335
+
336
+ ```bash
337
+ docker compose down
338
+ docker rmi xcompiler:latest
339
+ # workspace/ 与 .env / config.yaml 是宿主文件,保留或手动删
340
+ ```
341
+
342
+ ---
343
+
344
+ ## 3. 常见问题
345
+
346
+ | 现象 | 原因 | 处置 |
347
+ |---|---|---|
348
+ | `pip install` 在沙盒里 DNS 失败 | 宿主到 PyPI 不通 | 设 `PIP_INDEX_URL=<可达镜像>` 注入到 XCompiler 进程环境 |
349
+ | docker 模式下沙盒容器找不到工程文件 | 用了 `./workspace` 相对路径 | 改成绝对路径或 `$(pwd)/workspace` |
350
+ | `EACCES: /var/run/docker.sock` | `xcompiler` 用户不在宿主 docker 组 | `DOCKER_GID=$(stat -c '%g' /var/run/docker.sock) docker compose ...` |
351
+ | 长时 LLM 调用后 `audit.jsonl` 没事件 | (已修)旧版异步 appendFile 排队丢失 | 升级到当前版本:审计已改为 `appendFileSync` |
352
+ | `Plan schema 校验失败` | LLM 返回 plan 字段类型异常 | 查看 `<workspace>/docs/.draft/plan.invalid.json` 定位字段,必要时调高 `agent.max_rounds_per_step` 或换更强模型作为 Planner |
353
+ | 测试阶段一直被 DEBUG 重试到 max | 实现层 bug,DEBUG 也修不动 | 看 `<workspace>/.xcompiler/audit.jsonl` 里 `pytest stderr (tail)`;必要时手动改 SUT 后 `xcompiler run --from S<id>` 续跑 |
354
+
355
+ ---
356
+
357
+ ## 4. 目录约定
358
+
359
+ 部署完成后的工作区典型结构:
360
+
361
+ ```
362
+ <workspace>/
363
+ ├── intake.md # 需求输入(用户提供)
364
+ ├── config.yaml # 本次运行的配置
365
+ ├── phasePlan.json # 阶段总览与当前阶段指针
366
+ ├── plan.P1.json # 当前阶段的 V 模型执行计划
367
+ ├── requirements.txt # 由 pythonRequirements 在 xcompiler run 启动时种入
368
+ ├── docs/
369
+ │ ├── requirements.md
370
+ │ ├── architecture.md
371
+ │ ├── tasks.md
372
+ │ ├── refactor.md
373
+ │ ├── delivery.md
374
+ │ ├── process_log.md # AuditLogger 自动生成
375
+ │ ├── history/ # 同名旧文档归档
376
+ │ └── .draft/ # 失败 plan 等中间产物
377
+ ├── src/ # CODE 阶段产出
378
+ ├── tests/ # UNIT / INTEGRATION / MODULE / FUNCTIONAL 测试产出
379
+ ├── .sandbox/venv/ # subprocess 沙盒虚拟环境
380
+ └── .xcompiler/audit.jsonl # 审计事件流(同步落盘)
381
+ ```
@@ -36,7 +36,7 @@ OPENROUTER_MODEL=openrouter/free
36
36
  ```
37
37
 
38
38
  `.env` is ignored by git. Do not commit real API keys.
39
- `config.yaml` and `llm_scores.yaml` are local runtime files; keep them outside commits. The package ships `config.example.yaml` and `.env.example` only as templates.
39
+ `config.yaml`, `llm_scores.yaml`, and `llm_scores_user.yaml` are local files; keep them outside commits. The package ships `config.example.yaml` and `.env.example` only as templates. `llm_scores.yaml` is maintained by XCompiler; do not edit it directly.
40
40
 
41
41
  ## 2. Configure XCompiler
42
42
 
@@ -107,6 +107,15 @@ roles:
107
107
 
108
108
  Keep the default cluster score band (`cluster_score_min: 0.2`, `cluster_score_max: 0.5`) when `openrouter/free` is a safety net. Raise `cluster_score_max` toward `1.0` only when you intentionally want the aggregated route to compete with dedicated models.
109
109
 
110
+ For manual local priority overrides, create `llm_scores_user.yaml` beside `config.yaml`:
111
+
112
+ ```yaml
113
+ openrouter_free: 0.3
114
+ local_openai: 0
115
+ ```
116
+
117
+ User overrides take precedence over the dynamic `llm_scores.yaml` snapshot. Use `0` to disable a provider; use `0.1..1` to pin its effective priority. This file is local runtime policy and should not be committed.
118
+
110
119
  ## 5. Optional Local Backups
111
120
 
112
121
  Local OpenAI-compatible endpoints:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcompiler/cli",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "XCompiler — AI Software Factory: V-model driven, multi-LLM orchestrated software development agent.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -42,7 +42,11 @@
42
42
  "dist/acp",
43
43
  "config.example.yaml",
44
44
  ".env.example",
45
+ "debug-wiki",
46
+ "docs/assets",
45
47
  "docs/acp.md",
48
+ "docs/XCompiler_design.md",
49
+ "docs/deploy.md",
46
50
  "docs/openrouter.md",
47
51
  "docs/plugin_api.md",
48
52
  "docs/self_bootstrap.md",