Skip to content

Commit 4fdf870

Browse files
committed
fix(e2e): use commands-local e2e map instead of importing cli
1 parent 1239e32 commit 4fdf870

8 files changed

Lines changed: 165 additions & 48 deletions

File tree

AGENTS.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,43 @@ monorepo 多包结构:
1919
- 产品 smoke: `packages/cli/tests/e2e/smoke.e2e.test.ts``packages/rag/tests/e2e/smoke.e2e.test.ts`
2020
- 一次跑全量 e2e: 根目录 `pnpm test:e2e`
2121

22+
### 命令登记分层
23+
24+
命令**实现**`packages/commands/src/commands/`;**路径映射**由各产品 / 测试 fixture 自行维护,库本身不预设:
25+
26+
|| 文件 | 作用 |
27+
| ------------ | -------------------------------------------------- | -------------------------------------- |
28+
| 单命令导出 | `packages/commands/src/index.ts` | 从实现文件 re-export,供产品与 e2e 引用 |
29+
| bl 产品 map | `packages/cli/src/commands.ts` | `bl` 暴露的全量命令路径 |
30+
| rag 产品 map | `packages/rag/src/main.ts``commands` | `rag` 裁剪后的命令路径(如 `retrieve`) |
31+
| 契约 e2e map | `packages/commands/tests/fixtures/e2e-commands.ts` | 测试用全量 map,不依赖任何产品包 |
32+
33+
`bl --help``tools/generate-reference.ts`**`packages/cli/src/commands.ts`**,见 [command-add-remove.md](docs/agents/command-add-remove.md)
34+
2235
### `packages/cli` 目录要点
2336

2437
```
2538
packages/cli/
2639
├── src/main.ts # bl 入口(createCli + commands)
40+
├── src/commands.ts # bl 产品 command map
2741
└── tests/e2e/smoke.e2e.test.ts
2842
```
2943

30-
命令实现见 `packages/commands/src/commands/`;登记在 **`groups.ts`**`bl --help``tools/generate-reference.ts` 生成的命令手册同源,见 [command-add-remove.md](docs/agents/command-add-remove.md)
31-
3244
非代码资产:
3345

3446
- `tools/release/` — 发版自动化(CI 驱动,见 `.github/workflows/publish.yml`
35-
- `tools/generate-reference.ts` — 从 `catalog.ts` 生成命令手册到 `skills/bailian-cli/reference/`
47+
- `tools/generate-reference.ts` — 从 `packages/cli/src/commands.ts` 生成命令手册到 `skills/bailian-cli/reference/`
3648
- `tools/sync-skill-metadata.ts` — 从 `packages/cli/package.json` 同步 `skills/bailian-cli/SKILL.md``metadata.version`(与 `generate:reference` 一并由根目录 `pnpm run sync:skill-assets` 及 pre-commit 执行)
3749
- `README.md` / `README.zh.md` — npm 和 GitHub 主页
3850

3951
约定:
4052

4153
- core 是纯库,不依赖 cli(详见下方通用约定)
42-
- 文件路径与命令路径一一对应:`packages/commands/src/commands/text/chat.ts``bl text chat`
54+
- 文件路径与命令路径一一对应:`packages/commands/src/commands/text/chat.ts``bl text chat`(路径 key 由产品 map 决定,rag 可 remap)
4355
- 单级命令:`commands/<name>.ts`(如 `update.ts`);两级:`commands/<group>/<action>.ts`
44-
- 命令登记在 **`packages/commands/src/commands/groups.ts`**
56+
- 新增命令:实现 + `index.ts` 导出 + `e2e-commands.ts` 登记;bl 暴露则同步 `cli/src/commands.ts`(详见 [command-add-remove.md](docs/agents/command-add-remove.md))
4557

46-
Skill / 命令手册随 `skills/bailian-cli/``npx skills add modelstudioai/cli` 安装。`tools/generate-reference.ts`catalog 生成命令手册到 `skills/bailian-cli/reference/`(纳入 git);与 `tools/sync-skill-metadata.ts` 一起在 **pre-commit**`.vite-hooks/pre-commit`)及根脚本 `pnpm run sync:skill-assets` 中执行。
58+
Skill / 命令手册随 `skills/bailian-cli/``npx skills add modelstudioai/cli` 安装。`tools/generate-reference.ts``cli/src/commands.ts` 生成命令手册到 `skills/bailian-cli/reference/`(纳入 git);与 `tools/sync-skill-metadata.ts` 一起在 **pre-commit**`.vite-hooks/pre-commit`)及根脚本 `pnpm run sync:skill-assets` 中执行。
4759

4860
## 业务场景索引
4961

@@ -79,7 +91,7 @@ core 不应该知道 cli 的存在。具体表现:
7991

8092
- core 不写 stderr,不调 `process.exit`(用 `console.*``throw`)
8193
- core 抛的 `BailianError`,hint 字符串不出现 `bl xxx` 命令名
82-
- core 不写死域名 / region / 追踪参数(URL 集中在 `packages/cli/src/urls.ts`)
94+
- core 不写死域名 / region / 追踪参数(URL 集中在 `packages/runtime/src/urls.ts`)
8395
- core 接收 cli 通过 `Config` 注入的 metadata(`clientName` / `clientVersion`)
8496

8597
### 3. 错误处理边界:CLI 不翻译服务端错误

docs/agents/cli-e2e-tests.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44

55
E2E 按包分层,与命令实现 / 产品入口解耦:
66

7-
| 层级 | 路径 | 测什么 |
8-
| ---------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
9-
| **公共基建** | `packages/commands/tests/e2e/core/` | `createCliRunner`、skip 判定、输出目录、global-setup |
10-
| **命令契约 e2e** | `packages/commands/tests/e2e/*.e2e.test.ts` | help、缺参、dry-run、**真实集成**;跑 canonical 入口 `tests/fixtures/test-cli.ts` |
11-
| **产品 smoke** | `packages/cli/tests/e2e/smoke.e2e.test.ts``packages/rag/tests/e2e/smoke.e2e.test.ts` | 版本、root help、命令面裁剪;跑各产品 `src/main.ts` |
7+
| 层级 | 路径 | 测什么 |
8+
| ---------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
9+
| **公共基建** | `packages/commands/tests/e2e/core/` | `createCliRunner`、skip 判定、输出目录、global-setup |
10+
| **契约 e2e map** | `packages/commands/tests/fixtures/e2e-commands.ts` | 测试用全量 `{ "<path>": command }` map,仅依赖 `bailian-cli-commands` 单命令导出,不绑定任何产品 |
11+
| **命令契约 e2e** | `packages/commands/tests/e2e/*.e2e.test.ts` | help、缺参、dry-run、**真实集成**;跑 `tests/fixtures/test-cli.ts`(引用上述 fixture map) |
12+
| **产品 smoke** | `packages/cli/tests/e2e/smoke.e2e.test.ts``packages/rag/tests/e2e/smoke.e2e.test.ts` | 版本、root help、命令面裁剪;跑各产品 `src/main.ts` |
1213

1314
> `commands/tests/e2e/core` 是 e2e 测试基建,与 `packages/core``bailian-cli-core`)无关。
1415
1516
## 触发条件
1617

17-
- 新增/修改 `packages/commands/src/commands/` 下的 command(`groups.ts` 登记`defineCommand` 实现、options/usage)
18+
- 新增/修改 `packages/commands/src/commands/` 下的 command(`src/index.ts` 单命令导出`defineCommand` 实现、options/usage)
1819
- 新建或扩展 `packages/commands/tests/e2e/<topic>.e2e.test.ts` 用例
1920
- 新增/变更产品命令面(bl / rag)时同步维护对应 smoke 用例
2021
- 为命令补 help / 缺参 / dry-run / 真实集成测试
@@ -88,7 +89,8 @@ describe.skipIf(<ready>)("e2e: <topic>(DashScope …)", () => {
8889

8990
## 新增 command 检查清单
9091

91-
- [ ] `packages/commands/src/commands/groups.ts` 登记 + `packages/commands/tests/e2e/<topic>.e2e.test.ts`(新建或扩展)
92+
- [ ] `packages/commands/src/index.ts` 导出 + `tests/fixtures/e2e-commands.ts` 登记路径 + `packages/commands/tests/e2e/<topic>.e2e.test.ts`(新建或扩展)
93+
- [ ] 若 bl 也暴露该命令,同步 `packages/cli/src/commands.ts` 产品 map
9294
- [ ] 若改了 `usage` / `options` / `examples`,跑 `pnpm --filter bailian-cli run generate:reference` 更新 `skills/bailian-cli/reference/` 并提交
9395
- [ ] 顶层:分组 help + 子命令 `--help`(多子命令则各一条 help)
9496
- [ ] skip 块:每个 required flag 缺参;可 dry-run 则加一条

docs/agents/command-add-remove.md

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,47 @@
2020
仅当子组下有 ≥2 个 action 时合理(否则拍平到两级)
2121
```
2222

23-
文件路径与命令路径必须 1:1 对齐。
23+
实现文件路径与命令语义 1:1 对齐;**产品在 map 里决定暴露路径**(rag 可将 `knowledge retrieve` remap 为 `retrieve`)
2424

2525
## CLI 命令注册架构(必读)
2626

27-
命令元数据以 **`catalog.ts` 为单一登记处**;`registry.ts` 只负责解析与打印 help,不再内嵌命令表或手写 Resources 列表
27+
composable-cli:命令库只 export 单命令,**路径 map 由产品 / 测试各自注入**;`createCli` + `CommandRegistry``bailian-cli-runtime` 里解析 help
2828

2929
```
30-
commands/<...>.ts defineCommand({ name, description, usage, options, examples, run })
30+
packages/commands/src/commands/<...>.ts
31+
defineCommand({ name, description, usage, options, examples, run })
3132
32-
commands/catalog.ts export const commands: Record<string, Command>
33+
packages/commands/src/index.ts 单命令 re-export(无路径 preset)
3334
34-
┌────┴────┬──────────────────────┬─────────────────────┐
35-
↓ ↓ ↓ ↓
36-
registry.ts main.ts tools/generate-reference.ts export-schema.ts
37-
(解析/help) (入口) → skills/bailian-cli/reference/index.md + <group>.md
35+
┌────┴────────────┬─────────────────────────┬──────────────────────────┐
36+
↓ ↓ ↓ ↓
37+
cli/src/commands.ts rag/src/main.ts tests/fixtures/e2e-commands.ts (其他产品…)
38+
(bl 全量 map) (rag 裁剪 map) (契约 e2e 全量 map)
39+
↓ ↓ ↓
40+
createCli(commands, opts) → runtime/registry.ts(建树、resolve、printHelp)
41+
42+
tools/generate-reference.ts 读 cli/src/commands.ts → skills/bailian-cli/reference/
3843
```
3944

40-
- **`packages/cli/src/commands/catalog.ts`**: `import` 命令模块 + `"<path>": handler` 映射;**** `import registry.ts`(避免构建时循环依赖)
41-
- **`packages/cli/src/commands/index.ts`**: `export { commands } from "./catalog.ts"`(给包内 re-export 用)
42-
- **`packages/cli/src/registry.ts`**: `import { commands } from "./commands/catalog.ts"`,建树、`resolve``printHelp`;Commands / Global Flags 从 `Command` 元数据与 `GLOBAL_OPTIONS` **动态生成**
43-
- **`tools/generate-reference.ts`**: pre-commit / `pnpm run sync:skill-assets` 时读 `catalog.ts`,写 `skills/bailian-cli/reference/index.md`(索引) + `skills/bailian-cli/reference/<一级命令>.md`(详情,勿手改)。该目录**纳入 git**,随 `npx skills add modelstudioai/cli` 分发
45+
- **`packages/commands/src/index.ts`**: `export { default as textChat } from "./commands/text/chat.ts"` 等;****`"<path>": handler` 映射
46+
- **`packages/cli/src/commands.ts`**: bl 产品 map;`main.ts` 传入 `createCli`
47+
- **`packages/rag/src/main.ts`**: rag 产品 map(内联);路径可不同于 bl
48+
- **`packages/commands/tests/fixtures/e2e-commands.ts`**: 契约 e2e 全量 map;**** import `packages/cli`
49+
- **`packages/runtime/src/registry.ts`**: 从注入的 `Record<string, Command>` 建树;Commands / Global Flags 从 `Command` 元数据与 `GLOBAL_OPTIONS` **动态生成**
50+
- **`tools/generate-reference.ts`**: pre-commit / `pnpm run sync:skill-assets` 时读 **`packages/cli/src/commands.ts`**,写 `skills/bailian-cli/reference/index.md`(索引) + `skills/bailian-cli/reference/<一级命令>.md`(详情,勿手改)。该目录**纳入 git**,随 `npx skills add modelstudioai/cli` 分发
4451

45-
已删除、勿再引用:`commands/help.ts``registry.ts` 内联 `new CommandRegistry({...})``printRootHelp` 手写命令行
52+
已删除、勿再引用:`packages/cli/src/commands/catalog.ts``groups.ts``packages/cli/src/registry.ts``config/export-schema.ts`
4653

4754
## 必查清单
4855

4956
### A. 代码层
5057

51-
- [ ] **新建/删除/移动**对应的 `packages/cli/src/commands/<...>.ts` 文件
52-
- [ ] **`packages/cli/src/commands/catalog.ts`**:
53-
- 增删 `import xxx from "./.../xxx.ts"`
54-
-`export const commands` 里增删 `"<group> <action>": xxx`(key 与 `defineCommand({ name })` 一致)
55-
- [ ] **不要**`registry.ts` 里重复登记命令(已从 catalog 读取)
56-
- [ ] 如果命令需要跳过入口的默认 DashScope API key 引导(`ensureApiKey`),在对应 `defineCommand` 上设 `skipDefaultApiKeySetup: true`(字段定义见 `packages/core/src/types/command.ts`;`main.ts` 根据已解析的 `command` 读取)
57-
- [ ] **`config/export-schema.ts`**: 若新命令不适合作为 agent tool,评估是否加入 `SKIP_PREFIXES`;该文件在 `run()``import("../catalog.ts")`,勿顶层 import catalog 以免循环依赖
58+
- [ ] **新建/删除/移动**对应的 `packages/commands/src/commands/<...>.ts` 文件
59+
- [ ] **`packages/commands/src/index.ts`**: 增删 `export { default as xxx } from "./commands/.../xxx.ts"`
60+
- [ ] **`packages/commands/tests/fixtures/e2e-commands.ts`**: 增删 import 与 `"<path>": xxx`(契约 e2e 命令面)
61+
- [ ] **`packages/cli/src/commands.ts`**(bl 暴露该命令时): 同步 import 与 map key(key 与 `defineCommand({ name })` 一致)
62+
- [ ] **`packages/rag/src/main.ts`**(rag 暴露该命令时): 同步 import 与 map key(路径可按 rag 产品约定 remap)
63+
- [ ] 如果命令需要跳过入口的默认 DashScope API key 引导(`ensureApiKey`),在对应 `defineCommand` 上设 `skipDefaultApiKeySetup: true`(字段定义见 `packages/core/src/types/command.ts`;`createCli` 根据已解析的 `command` 读取)
5864

5965
### B. 文档层
6066

@@ -64,13 +70,14 @@ registry.ts main.ts tools/generate-reference.ts export-schema.ts
6470

6571
### C. 测试层
6672

67-
- [ ][cli-e2e-tests.md](cli-e2e-tests.md) 新建或更新 `packages/cli/tests/e2e/<topic>.e2e.test.ts`
73+
- [ ][cli-e2e-tests.md](cli-e2e-tests.md) 新建或更新 `packages/commands/tests/e2e/<topic>.e2e.test.ts`
74+
- [ ] bl / rag 命令面变更时,同步对应 smoke:`packages/cli/tests/e2e/smoke.e2e.test.ts``packages/rag/tests/e2e/smoke.e2e.test.ts`
6875
- [ ] 删除命令时一并删对应 e2e
6976

7077
### D. 重命名特殊处理
7178

7279
- [ ] 全仓 grep **旧命令名字符串**,确保以下位置全部更新:
73-
- `catalog.ts` 的 key
80+
- 各产品 / fixture map 的 key(`cli/src/commands.ts``e2e-commands.ts``rag/src/main.ts` 等)
7481
- error hints(cli 层)
7582
- `skills/bailian-cli/reference/`(重建后检查并提交)
7683
- README 示例
@@ -79,15 +86,17 @@ registry.ts main.ts tools/generate-reference.ts export-schema.ts
7986
## 完成后自查
8087

8188
```sh
82-
pnpm run sync:skill-assets # reference/ + SKILL metadata.version 与 catalog / package.json 一致
89+
pnpm run sync:skill-assets # reference/ + SKILL metadata.version 与 cli/commands.ts / package.json 一致
8390
node packages/cli/src/main.ts <new-command> --help
8491
node packages/cli/src/main.ts # 根 help 列表含新命令
85-
vp test packages/cli/tests/e2e/<topic>.e2e.test.ts # 相关 e2e
92+
pnpm --filter bailian-cli-commands test tests/e2e/<topic>.e2e.test.ts
93+
pnpm --filter bailian-cli test tests/e2e/smoke.e2e.test.ts # bl 命令面变更时
8694
```
8795

8896
## 常见漏点
8997

90-
- ✗ 只改了命令文件,忘了 **`catalog.ts`** → 命令不存在或 help 里没有
98+
- ✗ 只改了命令文件,忘了 **`index.ts` 导出** → 产品 / e2e 无法 import
99+
- ✗ 忘了 **`e2e-commands.ts`** → 契约 e2e 跑不起来或缺命令
100+
- ✗ bl 要暴露却忘了 **`cli/src/commands.ts`**`bl --help` 里没有、reference 也不会生成
91101
- ✗ 手改 **`skills/bailian-cli/reference/*.md`** → 下次 generate 被覆盖;应改 `defineCommand` 后重新 generate 并提交
92-
- ✗ 在 `export-schema.ts` 顶层 `import catalog` → 可能与 registry 循环依赖
93102
- ✗ 单 action 的子组是反模式,新增时优先拍平为两级

packages/cli/src/commands.d.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/commands/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
node_modules
22
dist
3-
tests/**/*.d.ts
43
*.log
54
.DS_Store
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import type { Command } from "bailian-cli-core";
2+
import {
3+
authLogin,
4+
authStatus,
5+
authLogout,
6+
textChat,
7+
textOmni,
8+
imageGenerate,
9+
imageEdit,
10+
videoGenerate,
11+
videoEdit,
12+
videoRef,
13+
videoTaskGet,
14+
videoDownload,
15+
visionDescribe,
16+
configShow,
17+
configSet,
18+
update,
19+
appCall,
20+
appList,
21+
memoryAdd,
22+
memorySearch,
23+
memoryList,
24+
memoryUpdate,
25+
memoryDelete,
26+
memoryProfileCreate,
27+
memoryProfileGet,
28+
knowledgeRetrieve,
29+
mcpCall,
30+
mcpList,
31+
mcpTools,
32+
searchWeb,
33+
speechSynthesize,
34+
speechRecognize,
35+
fileUpload,
36+
consoleCall,
37+
usageFree,
38+
usageFreetier,
39+
usageStats,
40+
pipelineRun,
41+
pipelineValidate,
42+
advisorRecommend,
43+
workspaceList,
44+
quotaList,
45+
quotaRequest,
46+
quotaHistory,
47+
quotaCheck,
48+
} from "bailian-cli-commands";
49+
50+
// 契约 e2e 全量命令面:测试关注点,不绑定任何产品 preset。
51+
// 路径映射由测试 fixture 维护;新增命令时需同步更新本 map 与 src/index.ts 导出。
52+
export const e2eCommands: Record<string, Command> = {
53+
"auth login": authLogin,
54+
"auth status": authStatus,
55+
"auth logout": authLogout,
56+
"text chat": textChat,
57+
omni: textOmni,
58+
"image generate": imageGenerate,
59+
"image edit": imageEdit,
60+
"video generate": videoGenerate,
61+
"video edit": videoEdit,
62+
"video ref": videoRef,
63+
"video task get": videoTaskGet,
64+
"video download": videoDownload,
65+
"vision describe": visionDescribe,
66+
"config show": configShow,
67+
"config set": configSet,
68+
update,
69+
"app call": appCall,
70+
"app list": appList,
71+
"memory add": memoryAdd,
72+
"memory search": memorySearch,
73+
"memory list": memoryList,
74+
"memory update": memoryUpdate,
75+
"memory delete": memoryDelete,
76+
"memory profile create": memoryProfileCreate,
77+
"memory profile get": memoryProfileGet,
78+
"knowledge retrieve": knowledgeRetrieve,
79+
"mcp call": mcpCall,
80+
"mcp list": mcpList,
81+
"mcp tools": mcpTools,
82+
"search web": searchWeb,
83+
"speech synthesize": speechSynthesize,
84+
"speech recognize": speechRecognize,
85+
"file upload": fileUpload,
86+
"console call": consoleCall,
87+
"usage free": usageFree,
88+
"usage freetier": usageFreetier,
89+
"usage stats": usageStats,
90+
"pipeline run": pipelineRun,
91+
"pipeline validate": pipelineValidate,
92+
"advisor recommend": advisorRecommend,
93+
"workspace list": workspaceList,
94+
"quota list": quotaList,
95+
"quota request": quotaRequest,
96+
"quota history": quotaHistory,
97+
"quota check": quotaCheck,
98+
};

packages/commands/tests/fixtures/test-cli.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { createCli } from "bailian-cli-runtime";
2-
import { commands } from "../../../cli/src/commands.ts";
2+
import { e2eCommands } from "./e2e-commands.ts";
33

4-
// 契约 e2e 专用 canonical 入口:全量 commands, bl 命令面一致
5-
void createCli(commands, {
4+
// 契约 e2e 专用 canonical 入口:全量 commands,独立于 bl/rag 产品
5+
void createCli(e2eCommands, {
66
binName: "bl",
77
version: "0.0.0-test",
88
clientName: "bailian-cli",

packages/commands/tsconfig.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,5 @@
1717
"isolatedModules": true,
1818
"verbatimModuleSyntax": true,
1919
"skipLibCheck": true
20-
},
21-
"exclude": ["tests/**/*"]
20+
}
2221
}

0 commit comments

Comments
 (0)