Skip to content

Commit f3b8591

Browse files
committed
Merge branch 'main' into feat/model-usage-and-detail
2 parents 8b99617 + 0e85777 commit f3b8591

86 files changed

Lines changed: 2218 additions & 1828 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/agents/cli-e2e-tests.md

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,86 @@
11
# CLI E2E 测试规范
22

3+
## 架构分层
4+
5+
| 层级 | 路径 | 测什么 |
6+
| --------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------- |
7+
| **共享基建** | `packages/e2e` | gating、子进程 runner、output、globalSetup(`private`,不发布) |
8+
| **命令 E2E** | `packages/commands/tests/e2e` | help、缺参、dry-run、live(gated);每用例最小路由 |
9+
| **bl smoke** | `packages/cli/tests/e2e/registry.smoke.e2e.test.ts` | 产品 map 全部 path `--help`、分组 help、根 help |
10+
| **kscli smoke** | `packages/kscli/tests/e2e/registry.smoke.e2e.test.ts` |`kscli/src/commands.ts` 推导 path/分组;identity(`--version``search --help` path) |
11+
| **runtime** | `packages/runtime/tests` | `proxy.e2e`、console 跨域 flag 拒绝 |
12+
13+
**依赖边界**`e2e``core``commands/tests``e2e` + `commands/src`;产品 tests → `e2e` + 各自 `src`**禁止**产品 import `commands/tests/**`(子进程 spawn harness 路径除外)。
14+
315
## 触发条件
416

517
- 新增/修改 `packages/commands/src/commands` 下的 command 实现
618
- 新增/修改 `packages/cli/src/commands.ts``bl` 命令路径 map
7-
- 新建或扩展 `packages/cli/tests/e2e/*.e2e.test.ts` 用例
8-
- 为命令补 help / 缺参 / dry-run / 真实集成测试
19+
- 新建或扩展 `packages/commands/tests/e2e/<topic>.e2e.test.ts`
20+
- 新增 bl 产品 path → `registry.smoke` 自动覆盖 leaf path;commands topic 测试在 `topic-routes.ts` 补最小路由
21+
22+
跑测与环境变量见 `.cursor/skills/bailian-cli-e2e/SKILL.md`
923

10-
以上情况必须同步维护 `packages/cli/tests/e2e/<topic>.e2e.test.ts`。跑测与环境变量见 `.cursor/skills/bailian-cli-e2e/SKILL.md`
24+
> **规则**:共享 command 行为在 `commands/tests/e2e`;产品 map、identity、CLI-only 命令留在对应产品 `tests/e2e`
1125
1226
## 文件与工具
1327

14-
- 路径:`packages/cli/tests/e2e/<kebab-topic>.e2e.test.ts`
15-
- 框架:`vite-plus/test`;子进程跑 CLI:`runCli` from `./helpers.ts`
28+
### commands E2E
29+
30+
- 路径:`packages/commands/tests/e2e/<kebab-topic>.e2e.test.ts`
31+
- 子进程:`runCommandE2e(routes, args)` from `./helpers.ts`(spawn `harness/main.ts``routes` 为本 topic 最小 path → export 映射)
32+
- fixtures:`packages/commands/tests/e2e/fixtures/`
33+
- 路由常量:`topic-routes.ts`(按 topic 维护,****全量产品 map)
34+
35+
### 产品 smoke
36+
37+
- bl:`runCli` from `packages/cli/tests/e2e/helpers.ts`
38+
- kscli:`runKscli` from `packages/kscli/tests/e2e/helpers.ts`
39+
40+
### 共享
41+
42+
- gating / output / runner:`e2e/gating``e2e/output``e2e/runner`
43+
- globalSetup:根 `vite.config.ts``packages/e2e/src/global-setup.ts`
1644
- 解析 JSON stdout:`parseStdoutJson`;输出目录:`makeE2eOutputDir(e2eLabelFromMetaUrl(import.meta.url))`
1745
- 长任务:`cliTimeoutPrefix()`;视频用例加 `test(..., 3_600_000)` 等显式超时
1846

1947
## 双层 describe(固定结构)
2048

2149
```ts
22-
// 1) 不 skip:分组 + --help,无密钥、无真实 API
50+
// 1) 不 skip:--help,无密钥、无真实 API(分组 help 由 bl registry.smoke 覆盖)
2351
describe("e2e: <topic>", () => {
24-
test("<group> 分组展示子命令帮助且成功退出", ...);
2552
test("<subcommand> --help 正常退出", ...);
2653
});
2754

28-
// 2) skipIf:缺参 / dry-run / 真实集成;原有集成用例放最后、勿改逻辑
55+
// 2) skipIf:缺参 / dry-run / 真实集成
2956
describe.skipIf(<ready>)("e2e: <topic>(DashScope …)", () => {
3057
test("缺少 --<flag> 时退出为用法错误 (2)", ...);
3158
test("<cmd> --dry-run ...", ...); // 若适用
3259
test("【model】真实流程", ..., LONG_TIMEOUT);
3360
});
3461
```
3562

36-
## skip 条件(helpers.ts
63+
## skip 条件(`e2e/gating`,commands helpers re-export
3764

38-
| 场景 | 条件 |
39-
| ------------------- | ----------------------------------------------------- |
40-
| 文本/搜索/记忆/配置 | `isDashScopeE2EReady()` |
41-
| 图像/语音 | `isBailianE2EMediaEnabled() && isDashScopeE2EReady()` |
42-
| 视频 | `isBailianE2EVideoEnabled() && isDashScopeE2EReady()` |
43-
| 知识库 | `isKnowledgeE2EReady()` |
44-
| 视频 download/task | 另需 `BAILIAN_E2E_VIDEO_TASK_ID` |
65+
| 场景 | 条件 |
66+
| ----------------------- | ---------------------------------------------------------------------------------------------------------- |
67+
| 文本/搜索/记忆/配置 | `isDashScopeE2EReady()` |
68+
| 图像/语音 | `isBailianE2EMediaEnabled() && isDashScopeE2EReady()` |
69+
| 视频 | `isBailianE2EVideoEnabled() && isDashScopeE2EReady()` |
70+
| 视频 download/task | 另需 `BAILIAN_E2E_VIDEO_TASK_ID` |
71+
| 知识库 chat/search live | `isChatE2EReady()` / `isSearchE2EReady()``knowledge chat/search`,需 `BAILIAN_WORKSPACE_ID` + agent ID) |
4572

4673
## 用例类型
4774

48-
1. **分组 help**`runCli(["image"])``exitCode === 0`,stdout+stderr 含子命令名
49-
2. **--help**`runCli([..., "--help"])` → stderr 含主要 flags
50-
3. **缺参**:带一个无害全局 flag(如 `--quiet`)且不传 required flag → `exitCode === 2`,stderr 匹配 `--flag|Missing required argument`
51-
4. **--dry-run**:仅当实现在联网/上传/写盘**之前**返回;断言 stdout JSON/文本,不入网
52-
5. **真实集成**:保留既有用例名称与断言;放在 skip 块**末尾**
75+
1. **--help**`runCommandE2e(ROUTES, [..., "--help"])` → stderr 含主要 flags
76+
2. **缺参**:带无害全局 flag(如 `--quiet`)且不传 required flag → `exitCode === 2`
77+
3. **--dry-run**:实现在联网/上传/写盘**之前**返回;断言 stdout JSON/文本
78+
4. **真实集成**:放在 skip 块**末尾**
79+
80+
## 增删命令同步
81+
82+
- **commands export** + **topic 路由**`topic-routes.ts` 或测试文件内 `ROUTES`)+ **产品 map**`cli/commands.ts` / `kscli/commands.ts`
83+
- 分组 help 由产品 `registry.smoke` 负责,无需在 commands 重复
5384

5485
## 安全与例外
5586

@@ -60,24 +91,36 @@ describe.skipIf(<ready>)("e2e: <topic>(DashScope …)", () => {
6091

6192
## 新增 command 检查清单
6293

63-
- [ ] `packages/commands/src/index.ts` 导出 + `packages/cli/src/commands.ts` 暴露路径 + `tests/e2e/<topic>.e2e.test.ts`(新建或扩展)
94+
- [ ] `packages/commands/src/index.ts` 导出 + `packages/cli/src/commands.ts` 暴露路径 + `topic-routes.ts` 补最小路由
95+
- [ ] `packages/commands/tests/e2e/<topic>.e2e.test.ts`(新建或扩展)
6496
- [ ] 若改了 `usageArgs` / `flags` / `exampleArgs`,跑 `pnpm --filter bailian-cli run generate:reference` 更新 `skills/bailian-cli/reference/` 并提交
65-
- [ ] 顶层:分组 help + 子命令 `--help`多子命令则各一条 help)
97+
- [ ] 子命令 `--help`分组 help 由 bl `registry.smoke` 覆盖
6698
- [ ] skip 块:每个 required flag 缺参;可 dry-run 则加一条
6799
- [ ] 至少一条真实集成(或说明为何仅 smoke);不破坏已有集成用例顺序
68-
- [ ] `pnpm test packages/cli/tests/e2e/<file>` 通过
100+
- [ ] `vp test packages/commands/tests/e2e/<file>` 通过
101+
102+
## 调试命令
103+
104+
```sh
105+
pnpm --filter bailian-cli-commands exec vp test packages/commands/tests/e2e/text-chat.e2e.test.ts
106+
pnpm --filter bailian-cli exec vp test packages/cli/tests/e2e/registry.smoke.e2e.test.ts
107+
pnpm --filter knowledge-studio-cli exec vp test packages/kscli/tests/e2e/registry.smoke.e2e.test.ts
108+
pnpm --filter bailian-cli-runtime exec vp test packages/runtime/tests/proxy.e2e.test.ts
109+
```
69110

70111
## 示例片段
71112

72113
```ts
114+
import { FOO_ROUTES } from "./topic-routes.ts";
115+
73116
test("foo bar 缺少 --prompt 时退出为用法错误 (2)", async () => {
74-
const { stderr, exitCode } = await runCli(["foo", "bar", "--quiet"]);
117+
const { stderr, exitCode } = await runCommandE2e(FOO_ROUTES, ["foo", "bar", "--quiet"]);
75118
expect(exitCode).toBe(2);
76119
expect(stderr).toMatch(/--prompt|Missing required argument/i);
77120
});
78121

79122
test("foo bar --dry-run 仅输出计划", async () => {
80-
const { stdout, stderr, exitCode } = await runCli([
123+
const { stdout, stderr, exitCode } = await runCommandE2e(FOO_ROUTES, [
81124
"foo",
82125
"bar",
83126
"--dry-run",
@@ -97,4 +140,4 @@ test("foo bar --dry-run 仅输出计划", async () => {
97140
- **E2E**:单条/少量调用、断言固定、可进 `vp test`(见上文 skip 条件)
98141
- **批量压测**`packages/cli/tests/stress/run.mjs` + `targets/*.mjs`,并发 + 报告,**仅手动** `pnpm run test:stress -- <target>`
99142

100-
勿把压测并入 E2E 或默认 CI。详见 [stress-batch-tests.md](stress-batch-tests.md)
143+
勿把压测并入 E2E 或默认 CI。详见 [stress-batch-tests.md](stress-batch-tests.md).

docs/agents/command-add-remove.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,17 @@ packages/commands/src/index.ts
9292

9393
### D. 测试层
9494

95-
- [ ][cli-e2e-tests.md](cli-e2e-tests.md) 新建或更新 `packages/cli/tests/e2e/<topic>.e2e.test.ts`
96-
- [ ] 删除命令时一并删对应 e2e / README 示例 / reference 生成结果
97-
- [ ] 如果 shared command 在不同入口路径下复用,至少确保 `bl` 入口 e2e 覆盖;`kscli` 入口改动需补对应入口测试或手工 smoke
95+
- [ ][cli-e2e-tests.md](cli-e2e-tests.md) 新建或更新 `packages/commands/tests/e2e/<topic>.e2e.test.ts`
96+
- [ ] 同步 `packages/commands/tests/e2e/topic-routes.ts`(该 topic 的最小 path → export 映射)
97+
- [ ] bl 产品 path 变更由 `registry.smoke` 自动覆盖;kscli 变更同步 `kscli/src/commands.ts``registry.smoke`
98+
- [ ] 删除命令时一并删对应 commands e2e / README 示例 / reference / topic 路由条目
99+
- [ ] 如果 shared command 在不同入口路径下复用,至少确保 commands e2e 覆盖 `bl` path;`kscli` 入口改动需补对应 smoke 或说明不测 flat path live
98100

99101
### E. 重命名特殊处理
100102

101103
- [ ] 全仓 grep **旧命令名字符串**,确保以下位置全部更新:
102104
- `packages/cli/src/commands.ts` map key
103-
- `packages/kscli/src/main.ts` map key(如适用)
105+
- `packages/kscli/src/commands.ts` map key(如适用)
104106
- 用户可见 hint / README / tests
105107
- `skills/bailian-cli/reference/`(重建后检查并提交)
106108
- [ ] 检查 `usageArgs` / `exampleArgs` 没有硬编码旧的 `bl <path>` 前缀
@@ -111,7 +113,7 @@ packages/commands/src/index.ts
111113
pnpm run sync:skill-assets
112114
pnpm -F bailian-cli exec tsx src/main.ts <new-command> --help
113115
pnpm -F bailian-cli exec tsx src/main.ts
114-
vp test packages/cli/tests/e2e/<topic>.e2e.test.ts
116+
vp test packages/commands/tests/e2e/<topic>.e2e.test.ts
115117
```
116118

117119
如改了 `kscli` 入口:

packages/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"ajv": "catalog:",
6060
"boxen": "catalog:",
6161
"chalk": "catalog:",
62+
"e2e": "workspace:*",
6263
"typescript": "^6.0.2",
6364
"undici": "catalog:",
6465
"vite-plus": "0.1.22",

0 commit comments

Comments
 (0)