benchloop-client 0.2.20__tar.gz

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 (49) hide show
  1. benchloop_client-0.2.20/.gitignore +15 -0
  2. benchloop_client-0.2.20/.python-version +1 -0
  3. benchloop_client-0.2.20/PKG-INFO +144 -0
  4. benchloop_client-0.2.20/README.md +132 -0
  5. benchloop_client-0.2.20/benchloop-cli-design.md +322 -0
  6. benchloop_client-0.2.20/bmcli_examples.sh +208 -0
  7. benchloop_client-0.2.20/pyproject.toml +35 -0
  8. benchloop_client-0.2.20/src/aliyun/bmcli/__init__.py +9 -0
  9. benchloop_client-0.2.20/src/aliyun/bmcli/__main__.py +26 -0
  10. benchloop_client-0.2.20/src/aliyun/bmcli/cli.py +138 -0
  11. benchloop_client-0.2.20/src/aliyun/bmcli/client.py +179 -0
  12. benchloop_client-0.2.20/src/aliyun/bmcli/commands/__init__.py +1 -0
  13. benchloop_client-0.2.20/src/aliyun/bmcli/commands/_common.py +84 -0
  14. benchloop_client-0.2.20/src/aliyun/bmcli/commands/ap_cmd.py +1029 -0
  15. benchloop_client-0.2.20/src/aliyun/bmcli/commands/artifacts.py +365 -0
  16. benchloop_client-0.2.20/src/aliyun/bmcli/commands/group_data.py +195 -0
  17. benchloop_client-0.2.20/src/aliyun/bmcli/commands/jobs.py +174 -0
  18. benchloop_client-0.2.20/src/aliyun/bmcli/commands/metrics.py +257 -0
  19. benchloop_client-0.2.20/src/aliyun/bmcli/commands/overview.py +70 -0
  20. benchloop_client-0.2.20/src/aliyun/bmcli/commands/pull.py +348 -0
  21. benchloop_client-0.2.20/src/aliyun/bmcli/commands/report.py +227 -0
  22. benchloop_client-0.2.20/src/aliyun/bmcli/commands/tasks.py +174 -0
  23. benchloop_client-0.2.20/src/aliyun/bmcli/commands/trajectory.py +318 -0
  24. benchloop_client-0.2.20/src/aliyun/bmcli/config.py +152 -0
  25. benchloop_client-0.2.20/src/aliyun/bmcli/exit_codes.py +15 -0
  26. benchloop_client-0.2.20/src/aliyun/bmcli/ids.py +87 -0
  27. benchloop_client-0.2.20/src/aliyun/bmcli/output.py +167 -0
  28. benchloop_client-0.2.20/src/aliyun/bmcli/runtime.py +149 -0
  29. benchloop_client-0.2.20/src/aliyun/bmcli/version_check.py +199 -0
  30. benchloop_client-0.2.20/tests/__init__.py +0 -0
  31. benchloop_client-0.2.20/tests/conftest.py +59 -0
  32. benchloop_client-0.2.20/tests/test_cli_options.py +56 -0
  33. benchloop_client-0.2.20/tests/test_client.py +101 -0
  34. benchloop_client-0.2.20/tests/test_cmd_ap_cmd.py +790 -0
  35. benchloop_client-0.2.20/tests/test_cmd_artifacts.py +493 -0
  36. benchloop_client-0.2.20/tests/test_cmd_metrics.py +535 -0
  37. benchloop_client-0.2.20/tests/test_cmd_overview.py +104 -0
  38. benchloop_client-0.2.20/tests/test_cmd_pull.py +185 -0
  39. benchloop_client-0.2.20/tests/test_cmd_report.py +319 -0
  40. benchloop_client-0.2.20/tests/test_cmd_tasks_jobs.py +327 -0
  41. benchloop_client-0.2.20/tests/test_cmd_trajectory.py +534 -0
  42. benchloop_client-0.2.20/tests/test_config.py +231 -0
  43. benchloop_client-0.2.20/tests/test_exit_code_behavior.py +127 -0
  44. benchloop_client-0.2.20/tests/test_exit_codes.py +27 -0
  45. benchloop_client-0.2.20/tests/test_group_data.py +113 -0
  46. benchloop_client-0.2.20/tests/test_ids.py +135 -0
  47. benchloop_client-0.2.20/tests/test_runtime.py +20 -0
  48. benchloop_client-0.2.20/tests/test_version_check.py +138 -0
  49. benchloop_client-0.2.20/uv.lock +309 -0
@@ -0,0 +1,15 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ .omc/
8
+ .omx/
9
+ *.egg-info
10
+
11
+ # Virtual environments
12
+ .venv
13
+
14
+ # IDE files
15
+ .idea/
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: benchloop_client
3
+ Version: 0.2.20
4
+ Summary: Benchloop CLI — command line tool for benchmark analysis data (metrics, trajectory, reports, artifacts).
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: httpx>=0.25.2
7
+ Requires-Dist: tomli>=1.1.0; python_version < '3.13'
8
+ Requires-Dist: typer>=0.9.4
9
+ Provides-Extra: dev
10
+ Requires-Dist: pytest>=8.0; extra == 'dev'
11
+ Description-Content-Type: text/markdown
12
+
13
+ # benchloop-client (`bl`, `bmcli`)
14
+
15
+ Command line tool for fetching and downloading benchmark analysis data
16
+ (run metrics, trajectory, pre-analysis reports, task/job lists, and artifacts)
17
+ by `group_id` / `job_id`.
18
+
19
+ > PyPI package name is `benchloop_client`; the installed commands are `bl` and `bmcli`.
20
+
21
+ ## Install package
22
+
23
+ ```
24
+ pip install benchloop_client
25
+
26
+ bl --api-key $BENCH_LOOP_API_KEY overview get -j $JOB_ID
27
+ bl --api-key $BENCH_LOOP_API_KEY metrics get -j $JOB_ID
28
+
29
+ # Option 2: config ~/.benchloop/config.toml by cli, and run bl without --api-key option:
30
+ bl config set --api-key $BENCHLOOP_API_KEY --host https://benchmark-analysis.alibaba-inc.com
31
+
32
+ bl overview get -j $JOB_ID
33
+ bl metrics get -j $JOB_ID
34
+
35
+ ```
36
+
37
+ The CLI checks PyPI for a newer release in the background at most once every
38
+ 24 hours. Update notices include the current/latest versions and the upgrade
39
+ command. Notices are written only to stderr, so JSON output remains pipeable.
40
+
41
+ ## Install and run from source
42
+
43
+ ```bash
44
+ # with uv (recommended)
45
+ uv sync
46
+ uv run bl --help
47
+
48
+ # or editable install with pip
49
+ python -m venv .venv && source .venv/bin/activate
50
+ pip install -e .
51
+ bl --help
52
+ ```
53
+
54
+ ## Auth & config
55
+
56
+ Authentication uses a personal api key sent as the `X-API-Key` header.
57
+
58
+ Precedence: CLI flag > env var > `~/.benchloop/config.toml` > default.
59
+
60
+ - Env: `BENCHLOOP_API_KEY` (or `BENCHMARK_API_KEY`), `BENCHLOOP_HOST`, `BENCHLOOP_OUTPUT_DIR`
61
+ - Default host (prod): `https://benchmark-analysis.alibaba-inc.com`
62
+ - Pre host: `https://pre-benchmark-analysis.alibaba-inc.com`
63
+
64
+ ```bash
65
+ bl config set --api-key $BENCHLOOP_API_KEY --host https://benchmark-analysis.alibaba-inc.com
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ Two-segment `bl <resource> <action>` form. `get` prints a JSON array to
71
+ stdout (pipeable to `jq`); `download` writes the standard file layout.
72
+
73
+ ```bash
74
+ bl metrics get -j J123 | jq '.[0]'
75
+ bl metrics download -g G1 --scope all -o ./out
76
+ bl trajectory download -g G1,G2 -o ./out
77
+ bl trajectory download --task-id TASK_ID -o ./out
78
+ bl report download -j J123 -o ./out
79
+ bl report get -g G123
80
+ bl report download -g G123 -o ./out
81
+ bl jobs get -g G1 --all # get supports --all (auto-paginate)
82
+ bl jobs download -g G1 # download is always full
83
+ bl artifacts download -g G1 -o ./out
84
+ bl pull -g G1 --with metrics,trajectory,jobs,artifacts -o ./out
85
+ ```
86
+
87
+ Group downloads always auto-paginate and include every Job in the Group. In
88
+ particular, `trajectory`, detailed `metrics`, `report`, and `artifacts` enumerate
89
+ the complete Job list instead of relying on the backend Group endpoints that
90
+ return at most 1000 Jobs. Existing aggregate files keep their original paths:
91
+
92
+ ```text
93
+ out/G1/trajectory.json
94
+ out/G1/detail_metrics.json
95
+ out/G1_report.md
96
+ out/G1/J123_report.md
97
+ out/G1/J123/<artifact-name>
98
+ ```
99
+
100
+ `report download -g` writes both the Group summary report and each Job report.
101
+ `pull -g` uses the same complete download behavior for every selected resource.
102
+ Use `--skip-existing` to resume file-based downloads after an interruption.
103
+
104
+ IDs accept repeated flags, comma-separated values, and `-` to read from stdin.
105
+ `-g` and `-j` are mutually exclusive in a single command. For trajectory
106
+ downloads, `--task-id` is a third mutually exclusive input mode.
107
+
108
+ ### Download filtered trajectories by task ID
109
+
110
+ The benchmark analysis Jobs page can turn the current filters into a trajectory
111
+ download task. Copy the command shown by the page and run it locally:
112
+
113
+ ```bash
114
+ bl trajectory download --task-id TASK_ID -o ./out
115
+ ```
116
+
117
+ The CLI fetches the task's complete job ID list, downloads job trajectories with
118
+ fixed concurrency, and prints count/ETA progress to stderr. It creates
119
+ `./out/TASK_ID_trajectories.zip`, containing one `<jobId>_trajectory.json` per
120
+ successful job and a `manifest.json` with total, success, and failure details.
121
+ If only some jobs fail, the successful files are still archived and the command
122
+ exits with code `1`. If every job fails, no empty ZIP is created.
123
+
124
+ ## Exit codes
125
+
126
+ | code | meaning |
127
+ | ---- | ------- |
128
+ | 0 | all success |
129
+ | 1 | partial failure (some ids failed) |
130
+ | 2 | usage / parameter error |
131
+ | 3 | auth failure (HTTP 401) |
132
+ | 4 | network / timeout |
133
+
134
+ stdout carries data only; logs and progress go to stderr. `--quiet` suppresses
135
+ non-error logs, `--verbose` adds debug logs.
136
+
137
+
138
+ ## Release new package
139
+
140
+ ```
141
+ uv build
142
+ twine check dist/benchloop_client-0.1.7-py3-none-any.whl
143
+ twine upload dist/benchloop_client-0.1.7-py3-none-any.whl --verbose
144
+ ```
@@ -0,0 +1,132 @@
1
+ # benchloop-client (`bl`, `bmcli`)
2
+
3
+ Command line tool for fetching and downloading benchmark analysis data
4
+ (run metrics, trajectory, pre-analysis reports, task/job lists, and artifacts)
5
+ by `group_id` / `job_id`.
6
+
7
+ > PyPI package name is `benchloop_client`; the installed commands are `bl` and `bmcli`.
8
+
9
+ ## Install package
10
+
11
+ ```
12
+ pip install benchloop_client
13
+
14
+ bl --api-key $BENCH_LOOP_API_KEY overview get -j $JOB_ID
15
+ bl --api-key $BENCH_LOOP_API_KEY metrics get -j $JOB_ID
16
+
17
+ # Option 2: config ~/.benchloop/config.toml by cli, and run bl without --api-key option:
18
+ bl config set --api-key $BENCHLOOP_API_KEY --host https://benchmark-analysis.alibaba-inc.com
19
+
20
+ bl overview get -j $JOB_ID
21
+ bl metrics get -j $JOB_ID
22
+
23
+ ```
24
+
25
+ The CLI checks PyPI for a newer release in the background at most once every
26
+ 24 hours. Update notices include the current/latest versions and the upgrade
27
+ command. Notices are written only to stderr, so JSON output remains pipeable.
28
+
29
+ ## Install and run from source
30
+
31
+ ```bash
32
+ # with uv (recommended)
33
+ uv sync
34
+ uv run bl --help
35
+
36
+ # or editable install with pip
37
+ python -m venv .venv && source .venv/bin/activate
38
+ pip install -e .
39
+ bl --help
40
+ ```
41
+
42
+ ## Auth & config
43
+
44
+ Authentication uses a personal api key sent as the `X-API-Key` header.
45
+
46
+ Precedence: CLI flag > env var > `~/.benchloop/config.toml` > default.
47
+
48
+ - Env: `BENCHLOOP_API_KEY` (or `BENCHMARK_API_KEY`), `BENCHLOOP_HOST`, `BENCHLOOP_OUTPUT_DIR`
49
+ - Default host (prod): `https://benchmark-analysis.alibaba-inc.com`
50
+ - Pre host: `https://pre-benchmark-analysis.alibaba-inc.com`
51
+
52
+ ```bash
53
+ bl config set --api-key $BENCHLOOP_API_KEY --host https://benchmark-analysis.alibaba-inc.com
54
+ ```
55
+
56
+ ## Usage
57
+
58
+ Two-segment `bl <resource> <action>` form. `get` prints a JSON array to
59
+ stdout (pipeable to `jq`); `download` writes the standard file layout.
60
+
61
+ ```bash
62
+ bl metrics get -j J123 | jq '.[0]'
63
+ bl metrics download -g G1 --scope all -o ./out
64
+ bl trajectory download -g G1,G2 -o ./out
65
+ bl trajectory download --task-id TASK_ID -o ./out
66
+ bl report download -j J123 -o ./out
67
+ bl report get -g G123
68
+ bl report download -g G123 -o ./out
69
+ bl jobs get -g G1 --all # get supports --all (auto-paginate)
70
+ bl jobs download -g G1 # download is always full
71
+ bl artifacts download -g G1 -o ./out
72
+ bl pull -g G1 --with metrics,trajectory,jobs,artifacts -o ./out
73
+ ```
74
+
75
+ Group downloads always auto-paginate and include every Job in the Group. In
76
+ particular, `trajectory`, detailed `metrics`, `report`, and `artifacts` enumerate
77
+ the complete Job list instead of relying on the backend Group endpoints that
78
+ return at most 1000 Jobs. Existing aggregate files keep their original paths:
79
+
80
+ ```text
81
+ out/G1/trajectory.json
82
+ out/G1/detail_metrics.json
83
+ out/G1_report.md
84
+ out/G1/J123_report.md
85
+ out/G1/J123/<artifact-name>
86
+ ```
87
+
88
+ `report download -g` writes both the Group summary report and each Job report.
89
+ `pull -g` uses the same complete download behavior for every selected resource.
90
+ Use `--skip-existing` to resume file-based downloads after an interruption.
91
+
92
+ IDs accept repeated flags, comma-separated values, and `-` to read from stdin.
93
+ `-g` and `-j` are mutually exclusive in a single command. For trajectory
94
+ downloads, `--task-id` is a third mutually exclusive input mode.
95
+
96
+ ### Download filtered trajectories by task ID
97
+
98
+ The benchmark analysis Jobs page can turn the current filters into a trajectory
99
+ download task. Copy the command shown by the page and run it locally:
100
+
101
+ ```bash
102
+ bl trajectory download --task-id TASK_ID -o ./out
103
+ ```
104
+
105
+ The CLI fetches the task's complete job ID list, downloads job trajectories with
106
+ fixed concurrency, and prints count/ETA progress to stderr. It creates
107
+ `./out/TASK_ID_trajectories.zip`, containing one `<jobId>_trajectory.json` per
108
+ successful job and a `manifest.json` with total, success, and failure details.
109
+ If only some jobs fail, the successful files are still archived and the command
110
+ exits with code `1`. If every job fails, no empty ZIP is created.
111
+
112
+ ## Exit codes
113
+
114
+ | code | meaning |
115
+ | ---- | ------- |
116
+ | 0 | all success |
117
+ | 1 | partial failure (some ids failed) |
118
+ | 2 | usage / parameter error |
119
+ | 3 | auth failure (HTTP 401) |
120
+ | 4 | network / timeout |
121
+
122
+ stdout carries data only; logs and progress go to stderr. `--quiet` suppresses
123
+ non-error logs, `--verbose` adds debug logs.
124
+
125
+
126
+ ## Release new package
127
+
128
+ ```
129
+ uv build
130
+ twine check dist/benchloop_client-0.1.7-py3-none-any.whl
131
+ twine upload dist/benchloop_client-0.1.7-py3-none-any.whl --verbose
132
+ ```
@@ -0,0 +1,322 @@
1
+ # Benchloop CLI (`bl`, `bmcli`) 命令行设计
2
+
3
+ > 状态:设计稿,待确认。实现将放在独立 Python 模块 `aliyun.bmcli`(主命令 `bl`,兼容别名 `bmcli`)。
4
+ > 后端需扩展 `/openapi/**` 接口(个人 api_key 鉴权),尽量复用既有 `/openapi`。
5
+
6
+ ---
7
+
8
+ ## 1. 目标与范围
9
+
10
+ 提供给算法同学按 **单个或多个 group_id / job_id** 拉取基准评测数据的命令行工具:
11
+
12
+ - `run_metrics`(查询 / 下载)— Group(Overall/Detail) & Job
13
+ - `trajectory`(查询 / 下载)— Group & Job
14
+ - 预分析报告 report(查询 / 下载)— Group & Job
15
+ - Group / Task / Job 运行统计 overview(仅查询)
16
+ - Task 列表 / Job 列表(查询 / 下载)— Group
17
+ - Artifacts 产物(仅下载)— Group & Job
18
+
19
+ **鉴权**:个人 api_key(HTTP 头 `X-API-Key`),对应后端 `mcp_auth_tokens` → `work_no`。
20
+
21
+ **约定**:所有 `查询(get)` 返回 **JSON 数组**;即使只有一条数据,也包在数组里。
22
+
23
+ ---
24
+
25
+ ## 2. 命令总体结构
26
+
27
+ 统一采用 `名词(资源) + 动词` 的两段式:
28
+
29
+ ```
30
+ bl <resource> <action> [ids...] [options]
31
+ ```
32
+
33
+ - `action = get` → 查询,结果打印到 stdout(JSON 数组)
34
+ - `action = download`→ 下载,按规定的文件布局写入磁盘
35
+
36
+ 按规格天然区分:`overview` 只有 `get`,`artifacts` 只有 `download`,其余资源两者都有。
37
+
38
+ | resource | get | download | 适用维度 |
39
+ | ------------ | :-: | :------: | ----------- |
40
+ | `metrics` | ✓ | ✓ | Group / Job |
41
+ | `trajectory` | ✓ | ✓ | Group / Job |
42
+ | `report` | ✓ | ✓ | Group / Job |
43
+ | `overview` | ✓ | — | Group / Job |
44
+ | `tasks` | ✓ | ✓ | Group |
45
+ | `jobs` | ✓ | ✓ | Group |
46
+ | `artifacts` | — | ✓ | Group / Job |
47
+
48
+ > 设计取舍:`get/download` 拆成子命令,而非用 `-o` 有无来切换——这样能精确表达「某资源只可查/只可下」,`bl <resource> --help` 也更清晰。
49
+
50
+ ---
51
+
52
+ ## 3. ID 入参约定
53
+
54
+ group / job 用显式互斥语义的旗标,**可重复、可逗号分隔、可从 stdin/文件**:
55
+
56
+ ```
57
+ -g, --group <id> Group ID,可重复或逗号分隔: -g G1 -g G2 / -g G1,G2
58
+ -j, --job <id> Job ID, 可重复或逗号分隔
59
+ -g - 从 stdin 读取(支持管道)
60
+ ```
61
+
62
+ - 一条命令里 `-g` 与 `-j` 不同时出现(如 `metrics get -g G1 -j J9`)。
63
+ - 各资源对维度的支持见上表;传入不支持的维度时报参数错误。
64
+
65
+ ---
66
+
67
+ ## 4. 全局选项(所有命令通用)
68
+
69
+ ```
70
+ --api-key KEY 个人 api_key(优先级最高)
71
+ --host URL 覆盖后端 base URL
72
+ -o, --output-dir DIR download 输出根目录(默认当前目录 .)
73
+ --pretty / --no-pretty JSON 是否缩进(默认 pretty)
74
+ --timeout SEC 单请求超时(默认 300)
75
+ --retry N 失败重试次数(默认 2,指数退避)
76
+ -v, --verbose 调试日志到 stderr
77
+ -q, --quiet 只输出错误
78
+ --config PATH 指定配置文件路径
79
+ --version / --help
80
+ ```
81
+
82
+ **配置与优先级**:`命令行旗标 > 环境变量 > 配置文件 > 默认值`
83
+
84
+ - 环境变量:`bmcli_API_KEY`、`bmcli_HOST`、`bmcli_OUTPUT_DIR`
85
+ - 配置文件:`~/.benchloop/config.toml`
86
+
87
+ ```toml
88
+ # ~/.benchloop/config.toml
89
+ [profile]
90
+ # 线上: https://benchmark-analysis.alibaba-inc.com 预发: https://pre-benchmark-analysis.alibaba-inc.com
91
+ host = "https://benchmark-analysis.alibaba-inc.com"
92
+ api_key = "xxxxxxxx"
93
+ ```
94
+
95
+ ---
96
+
97
+ ## 5. 各命令详细设计
98
+
99
+ ### 5.1 run_metrics — `bl metrics`
100
+
101
+ ```
102
+ bl metrics get [-g GroupID...] [-j JobID...] [--scope overall|detail|all]
103
+ bl metrics download [-g GroupID...] [-j JobID...] [--scope overall|detail|all] [-o DIR]
104
+ ```
105
+
106
+ - `--scope` 仅对 Group 生效(默认 `all`,即 overall + detail):
107
+ - `overall` → Group 汇总指标
108
+ - `detail` → Group 下每个 Job 的 run_metrics 聚合
109
+ - Job 维度忽略 `--scope`,直接取该 Job 的 run_metrics。
110
+
111
+ **下载文件布局**
112
+
113
+ | 维度 | 文件 |
114
+ | ----------- | --------------------------------- |
115
+ | Group overall | `{group_id}/overall_metrics.json` |
116
+ | Group detail | `{group_id}/detail_metrics.json` |
117
+ | Job | `{job_id}_run_metrics.json` |
118
+
119
+ ### 5.2 trajectory — `bl trajectory`
120
+
121
+ ```
122
+ bl trajectory get [-g GroupID...] [-j JobID...]
123
+ bl trajectory download [-g GroupID...] [-j JobID...] [-o DIR]
124
+ ```
125
+
126
+ **下载文件布局**
127
+
128
+ | 维度 | 文件 |
129
+ | ----- | --------------------------- |
130
+ | Group | `{group_id}/trajectory.json` |
131
+ | Job | `{job_id}_trajectory.json` |
132
+
133
+ ### 5.3 预分析报告 — `bl report`
134
+
135
+ ```
136
+ bl report get [-g GroupID...] [-j JobID...]
137
+ bl report download [-g GroupID...] [-j JobID...] [-o DIR]
138
+ ```
139
+
140
+ - `get` 时返回 JSON 数组。Job 报告包含 `fail_reason`、`sub_fail_reason`;Group 报告还包含组内 Job 的两级错误分布统计。
141
+
142
+ **下载文件布局**
143
+
144
+ | 维度 | 文件 |
145
+ | ----- | ------------------------- |
146
+ | Group | `{group_id}_report.md` |
147
+ | Job | `{job_id}_report.md` |
148
+
149
+ ### 5.4 运行统计 overview — `bl overview`(仅查询)
150
+
151
+ ```
152
+ bl overview get -g GroupID... --scope summary # Group Overview(eval_summary)
153
+ bl overview get -g GroupID... --scope tasks # Group Task Overview(组内 task 维度统计,eval_tasks)
154
+ bl overview get -g GroupID... # Group:summary + tasks(--scope all,默认)
155
+ bl overview get -j JobID... # Job Overview(jobs/{id} + jobs/stats)
156
+ ```
157
+
158
+ - 仅 `get`,不提供下载;维度由 `-g`/`-j` 决定;Group 维度的 `--scope summary|tasks|all`(默认 all)与 `metrics get` 的 `--scope` 保持一致。输出 JSON 数组。
159
+
160
+ ### 5.5 Task 列表 — `bl tasks`(Group)
161
+
162
+ ```
163
+ bl tasks get -g GroupID... [--page N] [--page-size M] [--all] [--search ...] [--status ...]
164
+ bl tasks download -g GroupID... [-o DIR]
165
+ ```
166
+
167
+ - `--all`:自动翻页拉全量(download 默认全量)。
168
+ - 文件:`{group_id}/task_list.json`
169
+
170
+ ### 5.6 Job 列表 — `bl jobs`(Group)
171
+
172
+ ```
173
+ bl jobs get -g GroupID... [--page N] [--page-size M] [--all]
174
+ [--template ...] [--status ...] [--instance-id ...]
175
+ bl jobs download -g GroupID... [-o DIR]
176
+ ```
177
+
178
+ - 文件:`{group_id}/job_list.json`
179
+
180
+ ### 5.7 Artifacts 产物 — `bl artifacts`(仅下载)
181
+
182
+ ```
183
+ bl artifacts download [-g GroupID...] [-j JobID...] [-o DIR]
184
+ [--include GLOB] [--exclude GLOB] [--list-only]
185
+ ```
186
+
187
+ - Job:下载该 Job 全部产物到 `{job_id}/` 目录。
188
+ - Group:下载组内所有 Job 产物到 `{group_id}/` 目录(接入 Lindorm)。
189
+ - `--list-only`:只列出产物清单不下载;`--include/--exclude` 按通配过滤。
190
+ - 后端返回 OSS 预签名 URL,CLI 负责并发下载与落盘。
191
+
192
+ **下载文件布局**
193
+
194
+ | 维度 | 路径 |
195
+ | ----- | ------------- |
196
+ | Job | `{job_id}/` |
197
+ | Group | `{group_id}/` |
198
+
199
+ ### 5.8(可选)一键打包 — `bl pull`
200
+
201
+ 便捷聚合命令:对给定 group/job 一次性拉取 metrics + trajectory + lists(+report/artifacts) 到上述布局。
202
+
203
+ ```
204
+ bl pull -g GroupID... [-j JobID...] [--with metrics,trajectory,report,artifacts,tasks,jobs] [-o DIR]
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 6. 输出文件布局总览(download 根目录下)
210
+
211
+ ```
212
+ <output-dir>/
213
+ ├── {group_id}/
214
+ │ ├── overall_metrics.json
215
+ │ ├── detail_metrics.json
216
+ │ ├── trajectory.json
217
+ │ ├── task_list.json
218
+ │ ├── job_list.json
219
+ │ └── <artifacts...> # group 产物
220
+ ├── {job_id}_run_metrics.json
221
+ ├── {job_id}_trajectory.json
222
+ ├── {job_id}_report.md
223
+ └── {job_id}/ # job 产物
224
+ └── <artifacts...>
225
+ ```
226
+
227
+ ---
228
+
229
+ ## 7. 后端 `/openapi` 接口对照(复用 vs 待补充)
230
+
231
+ > 鉴权统一为 `X-API-Key`(既有机制:`mcp_auth_tokens` → `work_no`)。
232
+
233
+ | CLI 命令 | 复用既有 `/openapi` | 需新增 `/openapi` |
234
+ | ------------------------------ | -------------------------------------------- | ---------------------------------------------- |
235
+ | `metrics get/download -j` | `GET /openapi/metrics/{jobId}` ✅ | — |
236
+ | `metrics ... -g --scope overall` | `GET /openapi/groups/{groupId}/eval_summary` ✅ 或 `GET /openapi/metrics?group_id=` | (二选一,确认 overall 字段口径) |
237
+ | `metrics ... -g --scope detail` | 可基于 `GET /openapi/jobs?group_id=` + 逐 job `metrics/{jobId}` | 建议新增 `GET /openapi/groups/{groupId}/metrics/detail` 直接聚合 |
238
+ | `trajectory ... -j` | — | **新增** `GET /openapi/jobs/{jobId}/trajectory` |
239
+ | `trajectory ... -g` | — | **新增** `GET /openapi/groups/{groupId}/trajectory`(或复用 `trajectory/download` 任务流) |
240
+ | `report ... -j` | — | **新增** `GET /openapi/jobs/{jobId}/report` |
241
+ | `report ... -g` | — | **新增** `GET /openapi/groups/{groupId}/report` |
242
+ | `overview get -g --scope summary` | `GET /openapi/groups/{groupId}/eval_summary` ✅ | 视字段补充 |
243
+ | `overview get -g --scope tasks` | `GET /openapi/groups/{groupId}/eval_tasks` ✅(聚合口径)| 可能新增统计汇总端点 |
244
+ | `overview get -j` | `GET /openapi/jobs/{jobId}` ✅ + `GET /openapi/jobs/stats` ✅ | — |
245
+ | `tasks get/download -g` | `GET /openapi/groups/{groupId}/eval_tasks` ✅ | — |
246
+ | `jobs get/download -g` | `GET /openapi/jobs?group_id=&skip=&limit=` ✅ | — |
247
+ | `artifacts download -j` | — | **新增** `GET /openapi/jobs/{jobId}/artifacts`(返回预签名 URL 列表) |
248
+ | `artifacts download -g` | — | **新增** `GET /openapi/groups/{groupId}/artifacts`(分页,Lindorm) |
249
+
250
+ **待后端补充实现清单(汇总)**
251
+
252
+ 1. `GET /openapi/jobs/{jobId}/trajectory`
253
+ 2. `GET /openapi/groups/{groupId}/trajectory`
254
+ 3. `GET /openapi/jobs/{jobId}/report`
255
+ 4. `GET /openapi/groups/{groupId}/report`
256
+ 5. `GET /openapi/jobs/{jobId}/artifacts`
257
+ 6. `GET /openapi/groups/{groupId}/artifacts`
258
+ 7. `GET /openapi/groups/{groupId}/metrics/detail`(detail 聚合,可选)
259
+
260
+ ---
261
+
262
+ ## 8. 行为约定
263
+
264
+ - **多 id**:使用内部固定并发数执行,结果数组合并;download 各自落盘。
265
+ - **返回数组**:`get` 始终输出数组;单条也包成单元素数组。
266
+ - **部分失败**:某 id 失败不阻断其它 id;汇总在结尾打印失败清单,退出码非 0。
267
+ - **退出码**:`0` 全部成功;`1` 部分失败;`2` 参数错误;`3` 鉴权失败(401);`4` 网络/超时。
268
+ - **stdout/stderr 分离**:数据走 stdout(可管道给 `jq`),日志/进度走 stderr。
269
+ - **幂等下载**:默认覆盖;`--skip-existing` 跳过已存在文件;`--list-only` 仅预览。
270
+
271
+ ---
272
+
273
+ ## 9. 打包与分发
274
+
275
+ - 模块:`aliyun.bmcli`,可执行入口 `bl` 与兼容别名 `bmcli`(`[project.scripts] bl = "aliyun.bmcli.__main__:main"`,`bmcli = "aliyun.bmcli.__main__:main"`)。
276
+ - 技术栈建议:Python 3.10+ + Typer/Click + httpx,`uv` + `hatchling` 打包(与现有 `bench_mcp` 工具链一致)。
277
+ - 安装:`uv tool install benchloop_client` 或 `pipx install benchloop_client`。
278
+
279
+ ---
280
+
281
+ ## 10. 用法示例
282
+
283
+ ```bash
284
+ # 配置一次
285
+ bl config set --api-key $KEY --host https://benchmark-analysis.alibaba-inc.com
286
+
287
+ # 查询单个 job 的 run_metrics(数组输出,可接 jq)
288
+ bl metrics get -j J123 | jq '.[0].score'
289
+
290
+ # 下载一个 group 的 overall+detail 指标
291
+ bl metrics download -g G1 --scope all -o ./out
292
+
293
+ # 多个 group 的 trajectory 下载
294
+ bl trajectory download -g G1,G2 -o ./out
295
+
296
+ # job 的预分析报告
297
+ bl report download -j J123 -o ./out
298
+
299
+ # group 报告及组内错误分布
300
+ bl report get -g G1
301
+ bl report download -g G1 -o ./out
302
+
303
+ # group 的 job 列表(全量)
304
+ bl jobs download -g G1 --all
305
+
306
+ # 下载 group 下所有 job 产物
307
+ bl artifacts download -g G1 -o ./out
308
+
309
+ # 一键拉取
310
+ bl pull -g G1 --with metrics,trajectory,jobs,artifacts -o ./out
311
+ ```
312
+
313
+ ---
314
+
315
+ ## 11. 其他问题
316
+
317
+ 1. `overall metrics` 是 Group 页面 Run_Metrics 下面显示的统计的 metrics 数据.
318
+ 2. `metrics detail` CLI 端循环按照 group_id 分页拉取
319
+ 3. `overview task`(Group Task Overview)统计口径与现有 `eval_tasks` 的差异。
320
+ 4. trajectory(尤其 group 级,数据量大)走「同步返回」还是「异步下载任务」模式。
321
+ 5. artifacts group 级量大时是否需要断点续传 / 限速。
322
+ 6. api_key 是否复用 `mcp_auth_tokens`,还是单独签发体系。