@guandata/guancli 1.0.57 → 1.0.59
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/CHANGELOG.md +15 -0
- package/README.md +13 -0
- package/binaries/guancli-darwin-arm64 +0 -0
- package/binaries/guancli-darwin-x64 +0 -0
- package/binaries/guancli-linux-arm64 +0 -0
- package/binaries/guancli-linux-x64 +0 -0
- package/binaries/guancli-win32-x64.exe +0 -0
- package/package.json +3 -3
- package/skills/guancli/SKILL.md +12 -6
- package/skills/guancli/evals/evals.json +35 -6
- package/skills/guancli/evals/fixtures/metric-consumption-columns.json +46 -0
- package/skills/guancli/evals/fixtures/metric-consumption-metadata.json +36 -0
- package/skills/guancli/evals/fixtures/metric-consumption-query.json +18 -0
- package/skills/guancli/references/auth-and-config.md +22 -22
- package/skills/guancli/references/examples/metric-query-rows.py +48 -4
- package/skills/guancli/references/metric-batch-query.md +52 -0
- package/skills/guancli/references/metric-commands.md +20 -2
- package/skills/guancli/references/metric-generic-query.md +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## @guandata/guancli 1.0.59 - 2026-09-15
|
|
4
|
+
|
|
5
|
+
- `--filter` 支持符号比较操作符 `=`、`!=`、`<>`、`<`、`<=`、`>`、`>=`,统一归一化为枚举操作符;`--filter-json`、`--filter-file` 和 `metric batch-query` 的 `operator` 同样支持。`BT` 也接受两个不含空格的边界用空格分隔。
|
|
6
|
+
- `metric batch-query` 新增 `--fail-on-error`:任一项失败时仍输出完整 JSON 但非零退出,可直接用 `&&` 衔接后续处理。
|
|
7
|
+
- `metric batch-query` 的 `valueFormat` 新增 `both`:一次取数同时返回原始 `rows` 和展示用 `formattedRows`,需要计算又需要展示时不再重复取数。
|
|
8
|
+
- `ds execute-sql` 新增 `-o/--output`,可直接把结果写入文件(默认 CSV),避免为保存结果重复改参执行。
|
|
9
|
+
- `app publish --overwrite-settings` 仅在 BI `>= 8.3.2` 时生效;低版本、版本查询失败或响应无法解析时默认保留线上 `settings.json`。
|
|
10
|
+
- 结构化筛选条件组误用 `children` 时会给出明确错误并提示改用 `conditions`。
|
|
11
|
+
|
|
12
|
+
## @guandata/guancli 1.0.58 - 2026-09-11
|
|
13
|
+
|
|
14
|
+
- 新增 `metric batch-query`:把同轮已确定、互不依赖的多个基础指标查询写成一份 JSON 一次提交,CLI 自动调度并发并按输入顺序逐项返回,输出 `schemaVersion: 1.0` 稳定机器契约,失败逐项归因,退出 0 不代表每项都成功。
|
|
15
|
+
- 批量查询支持维度、日期子粒度、排序、分页与 `valueFormat`(raw/formatted);格式化输出沿用指标格式配置,排序和分页始终基于原始值。同比、XTD、recent、占比和排名等高级计算仍使用单条 `metric query`。
|
|
16
|
+
- 指标结果消费补充动态列发现与精确选择规范,禁止在脚本中硬编码展示列名;登录方式顺序调整为 1 用户名密码、2 uIdToken、3 Personal Access Token、4 浏览器 OIDC,并移除推荐标记。
|
|
17
|
+
|
|
3
18
|
## @guandata/guancli 1.0.57 - 2026-09-09
|
|
4
19
|
|
|
5
20
|
- 统一指标查询的 JSON 输入与输出契约,补充日期维度子类型和日期筛选示例,脚本处理更稳定。
|
package/README.md
CHANGED
|
@@ -43,6 +43,19 @@ guancli chatbi query --theme-name "经营主题" --message "最近30天营业收
|
|
|
43
43
|
|
|
44
44
|
## 版本更新
|
|
45
45
|
|
|
46
|
+
### @guandata/guancli 1.0.59
|
|
47
|
+
|
|
48
|
+
- 指标筛选支持 `=`、`!=`、`<>`、`<`、`<=`、`>`、`>=` 符号写法,统一归一化为枚举操作符;`BT` 也支持两个不含空格的边界用空格分隔。
|
|
49
|
+
- `metric batch-query` 新增 `--fail-on-error`,并在 `valueFormat` 中新增 `both`,一次取数同时返回原始值和展示值。
|
|
50
|
+
- `ds execute-sql` 新增 `-o/--output`,可直接把结果写入文件(默认 CSV)。
|
|
51
|
+
- `app publish --overwrite-settings` 仅在 BI >= 8.3.2 时生效,低版本默认保留线上设置。
|
|
52
|
+
|
|
53
|
+
### @guandata/guancli 1.0.58
|
|
54
|
+
|
|
55
|
+
- 新增 `metric batch-query`:同轮已确定、互不依赖的多个基础指标查询可写成一份 JSON 一次提交,CLI 自动调度并发并按输入顺序逐项返回,失败逐项归因。
|
|
56
|
+
- 批量查询支持维度、日期子粒度、排序、分页和 `valueFormat`;格式化输出沿用指标格式配置,排序分页基于原始值。
|
|
57
|
+
- 指标结果消费补充动态列发现与精确选择规范,避免硬编码展示列名;登录方式顺序与提示同步更新。
|
|
58
|
+
|
|
46
59
|
### @guandata/guancli 1.0.57
|
|
47
60
|
|
|
48
61
|
- 统一指标查询 JSON 契约,补充日期维度与筛选示例,并支持按状态搜索指标。
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guandata/guancli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.59",
|
|
4
4
|
"description": "观远 BI 命令行工具 - 通过 API 操作 ETL、数据集、页面、表单等资源,并提供 ChatBI 问数/洞察能力",
|
|
5
5
|
"bin": {
|
|
6
6
|
"guancli": "bin/run.js"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"node": ">=14"
|
|
39
39
|
},
|
|
40
40
|
"publishConfig": {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
41
|
+
"access": "public",
|
|
42
|
+
"registry": "https://registry.npmjs.org/"
|
|
43
43
|
}
|
|
44
44
|
}
|
package/skills/guancli/SKILL.md
CHANGED
|
@@ -70,6 +70,10 @@ guancli 是 BI 资源的**查询分析入口**,并支持 Form 表单填报 CRU
|
|
|
70
70
|
|
|
71
71
|
## 常用查询入口
|
|
72
72
|
|
|
73
|
+
**同轮指标查询规则**:本轮已确定、彼此互不依赖,且参数能被 `batch-query` 完整表达的多个基础指标查询,必须写成一个结构化查询列表并执行一次 `guancli metric batch-query --input queries.json`。同比、XTD、recent、占比、排名等高级计算继续使用单条 `metric query`;同轮其余基础查询仍应单独组成 batch。不得生成 Shell `for` 循环逐项执行基础指标查询,也不自行设计 `&`、`xargs -P` 等并发脚本或调整并发参数。CLI 自动调度并逐项返回结果;需要全部成功后再处理结果时加 `--fail-on-error`,可直接用 `&&` 衔接;默认模式仍需用 `id` 对齐每项 `status`。后续查询依赖本轮结果时,读取本轮结果后再生成下一批。搜索并需要详情时使用 `metric search --with-detail`,避免逐项 get。批量输入、分页与支持边界见 [metric-batch-query.md](references/metric-batch-query.md)。复用已确认的输入契约,缺少信息或遇到参数错误时再读取该参考,不固定增加帮助查询。
|
|
74
|
+
|
|
75
|
+
**减少模型往返**:同一授权和查询轮次内,已确认的指标口径、字段与能力直接复用。将确定性的文件读取、状态检查、裁剪和计算合并成一次本地执行,返回需要判断的摘要;仅在结果引入新决策时再规划下一轮。只读查询可与结果保存、检查和摘要合并执行;确认查询成功后再消费,不为补齐运行轨迹拆分命令或重跑查询。
|
|
76
|
+
|
|
73
77
|
```bash
|
|
74
78
|
guancli etl tree --max-depth 2
|
|
75
79
|
guancli ds tree --max-depth 2
|
|
@@ -98,7 +102,7 @@ guancli url metric-dir <metric_dir_id> --project-id <metric_project_id>
|
|
|
98
102
|
# 数据集目录 Web URL 格式为 /data-center/data-sets/<dataset_dir_id>
|
|
99
103
|
guancli ds preview <ds_id> --limit 20
|
|
100
104
|
# 多行或含复杂引号的 SQL 优先写入文件并使用 --sql-file;需要管道输入时显式使用 --sql-file -。
|
|
101
|
-
guancli ds execute-sql -inputs <ds_id> --sql-file query.sql
|
|
105
|
+
guancli ds execute-sql -inputs <ds_id> --sql-file query.sql -f csv -o result.csv
|
|
102
106
|
guancli card get <cd_id>
|
|
103
107
|
guancli card preview <cd_id> --value-format raw -f csv
|
|
104
108
|
guancli card preview <cd_id> --with-default-filters
|
|
@@ -145,14 +149,16 @@ guancli 在这条链路上只出只读的那一环:`guancli page search` / `pa
|
|
|
145
149
|
|
|
146
150
|
- **先按下面的命令契约生成,不要猜 shell、jq 或筛选语法**:
|
|
147
151
|
- `metric search/get/tree/query -f json` 返回统一 envelope:先读取 `schemaVersion`、`resultMode` 和 `rowCount`;当前 canonical 契约版本为 `1.0`。`resultMode=inline` 时消费 `data`,`resultMode=file` 时读取 `path`。search/get 直接从后端字段构造稳定英文模型,核心字段包括 `id/name/status/type/description/dataset/dimensions/timeField/measureFields`,`status/type` 使用 `PUBLISHED/ATOMIC` 等机器枚举,不依赖中文展示 key;tree 使用 `id/name/type/children`。后端新增未知字段不会要求 CLI 同步修改,稳定必填字段缺失则明确失败。可选标量和对象的缺失或 `null` 统一省略;`dimensions/timeField/measureFields/customAttributes` 及 `accelerations[].priority` 区分缺失、`null`、空值或零值,`accelerations` 区分未查询与已知空数组,调用方不要把省略解释成已知为空。旧脚本按 `references/metric-json-migration.md` 迁移;envelope 版本由响应体中的 `schemaVersion` 演进,不新增 `json-v2` 一类输出格式。JSON envelope 不能输出到 stderr;`--raw` 单独返回后端原始协议。
|
|
148
|
-
-
|
|
149
|
-
- query 的业务列可以是中文,每个中文层级都用 `["字段名"]`:例如 `.data[]["组织"]["名称"]
|
|
150
|
-
- 必须解析的命令不得用 `2>/dev/null` 隐藏 stderr,也不得用 `2>&1` 将错误文本送入 JSON
|
|
152
|
+
- 比较筛选优先用带空格的符号写法,例如 `--filter '日期 >= 2026-01-01'`;支持 `=`、`!=`、`<>`、`<`、`<=`、`>`、`>=`,原有 `EQ/NE/LT/LE/GT/GE` 仍有效。CLI 统一归一为枚举操作符,结构化筛选和 batch-query 的 `operator` 同样支持符号。整个 `--filter` 参数必须用 shell 引号包住;集合、区间、空值与字符串匹配操作符见命令帮助。
|
|
153
|
+
- query 的业务列可以是中文,每个中文层级都用 `["字段名"]`:例如 `.data[] | .["组织"]["名称"]`,每一个中文层级都要引用,不能只改顶层。search/get 的 canonical 英文字段与 query 的业务列名要分开理解。文件模式的 `path` 指向行数组,行数组没有 `rowCount`;先按 `resultMode` 分支再消费,示例见 `references/metric-commands.md`。
|
|
154
|
+
- 必须解析的命令不得用 `2>/dev/null` 隐藏 stderr,也不得用 `2>&1` 将错误文本送入 JSON 解码器。不要用会让末端命令成功掩盖上游失败的管道;允许组合执行时用 `&&` 衔接“输出到文件 → 解析摘要”,不为读取文件另起一轮推理,必须使用管道时先启用 `set -o pipefail`。
|
|
151
155
|
- 同类语法错误只允许出现一次;第一次失败后先执行对应命令的 `--help` 或读取本 Skill 的参考文档,再按真实契约纠正,不连续尝试相近写法。
|
|
152
|
-
- 普通 `--filter`、可重复 `--filter-json`、单个 `--filter-file` 三选一,禁止混用。复杂筛选优先使用 `--filter-json`(可重复)或 `--filter-file`
|
|
156
|
+
- 普通 `--filter`、可重复 `--filter-json`、单个 `--filter-file` 三选一,禁止混用。复杂筛选优先使用 `--filter-json`(可重复)或 `--filter-file` 条件树。参数和口径明确时直接查询;需要检查计划或排查复杂参数时才用 `--dry-run -f json`。dry-run 只读取指标详情做查询维度、筛选字段和类型校验,不执行指标取数,也不支持普通文件或 stderr 输出目标。不支持的 `--dim` 返回 `METRIC_UNSUPPORTED_DIMENSION`。条件组使用 `combineType: AND|OR` 和 `conditions` 数组,叶子使用 `field/operator/value|values`;`IN` 至少一个值,`BT` 恰好两个值。当前指标取数接口不能无损表达多分支 OR,真实执行会在取数前返回 `FILTER_OR_EXECUTION_UNSUPPORTED`,不得拆成多次聚合查询后拼接。失败时按稳定错误码修正,不猜错误文本。
|
|
153
157
|
- 搜索并同时查看业务口径、数据集和适用维度等详情时,优先使用 `guancli metric search --fuzzy <keyword> --limit <N> --with-detail --brief -f json`,不要先 search 再逐个 get,也不要为终端阅读额外拼 jq。只查单个指标详情时优先使用 `guancli metric get <metric_id> --brief`;只裁剪指标查询结果列时使用 `metric query --columns`。可复制模板见 `references/metric-commands.md`。
|
|
154
158
|
- 业务词不能直接命中指标时,候选发现必须遵守单批预算:一次性生成“原词 + 最多 4 个必要同义词/等价表达”,按 trim、空白归一化和大小写不敏感语义去重,保留原词在首位,然后只执行一次 `metric search --fuzzy`。不得把同义词拆成多次查询,不得通过调换顺序、改写等价词或查询子集重复搜索;如果单批无候选,立即结束本轮候选发现并说明已尝试关键词、搜索范围、无结果原因和 `stop_reason=no_candidate_within_budget`。后端最多接受 10 个模糊关键词,但 Agent 候选发现预算默认最多 5 个;不要缓存或跨请求复用“未找到指标”的结论。完整协议见 `references/metric-commands.md`。
|
|
159
|
+
- 指标结果加工前,先读取成功 query envelope 的实际 `columns` 和行对象 keys,按业务含义选择列;禁止硬编码或猜测指标展示列名(包括高级计算后缀),也不能按列位置取值。使用 `python3 references/examples/metric-query-rows.py <envelope.json> --list-columns` 发现列,再用 `--column "<已确认的实际列名>"` 精确选择;候选缺失或多义时停止并返回实际列集合,不猜近似名称。该参数属于消费 recipe,不是 `guancli metric query` 的参数。
|
|
155
160
|
- 普通指标数据查询用 `guancli metric query <metric_id>`,可加 `--dim`、筛选、排序、列筛选、输出格式等。数值默认按指标配置的 `format` 输出(查询响应有更具体的列级格式时优先),没有有效格式时才按 `--precision` 回退;需要标准表格/JSON/CSV/Excel 中保留原始数值时传 `--value-format raw`,不要和直接返回后端响应的全局 `--raw` 混淆。使用 `-f json` 时,未指定 `-o/--output` 且结果超过 1000 行会自动写入 `metric_<metricId>_<timestamp>_<unique>.json`,stdout 返回 `resultMode=file` 和绝对 `path`,不得再从中文提示猜文件名。唯一后缀用于避免同秒并发或重试覆盖已有结果。默认文本、CSV/Excel 和 `--raw` 保持原行为。回答指标数据查询结果时,必须检查输出中的 `查询加速` summary 或 `_queryAccelerate` 列:命中时明确说明“本次查询命中查询加速”,并列出源指标 ID、加速指标 ID 和页面查询顺序;未命中时说明“未命中查询加速”;如果显示 `未知: 后端未返回`,说明当前后端未返回命中 metadata,不能推断是否命中。注意:输出中的 `优先级N` 来自后端 `acceleratePriority` 排序权重,数字越大越先尝试;不要把它直接解释成页面“查询顺序”。需要和页面对齐时,额外执行 `guancli metric accelerate list <metric_id>`,按 `acceleratePriority` 倒序排列后换算页面查询顺序(倒序第 1 个即页面查询顺序 1)。
|
|
161
|
+
- 同一批量查询既用于计算又用于展示时,使用 `valueFormat: "both"`;原始 `rows` 用于计算,`formattedRows` 用于展示,不按格式重复取数。仅需一种格式时使用 raw 或 formatted,避免额外输出。
|
|
156
162
|
- 指标查数必须区分**时间范围**和**分组粒度**。用户说“本月/上月/2026 年 8 月销售额”时只生成时间筛选,不自动增加月维度;用户说“按月/每月/月度趋势/逐月”时,先从指标详情的 `timeField.name` 取得真实时间维度名,再使用 `--dim "<时间维度> toMonth"`;“近 12 个月每月”同时生成月维度和时间范围筛选。季度、周、日、星期、小时、分钟、秒同理映射到 `toQuarter/toWeek/toDate/toDayOfWeek/toHour/toMinute/toSecond`。用户未表达分组粒度时不得擅自改变日期粒度,也不要猜时间字段名一定叫“日期”。多日期维度且用户明确点名其中一个时,用 `--dim "<该维度> toGranularity"` 消歧;未点名且无法从业务问题确定时先确认。日期粒度排序使用相同表达式,例如 `--sort-asc "订单日期 toMonth"`。执行前可用 `--dry-run -f json` 检查 `resolvedDimensions` 中最终选择的 `fdId/fdType/parentFdName/granularity`。
|
|
157
163
|
- 搜索指标支持两种方式:`guancli metric search <keyword>` 按指标名称模糊搜索;`guancli metric search --fuzzy <keyword>` 同时按指标名称、业务口径、自定义业务属性值做 OR 模糊搜索,可多次传参,命中优先级为 name=1、desc=2、bizAttr=3。`[keyword]` 和 `--fuzzy` 互斥。需要同时查看每个命中指标的 `metric get` 详情时加 `--with-detail`;默认文本包含血缘,加 `--brief` 可跳过血缘。`-f json` 不包含且不请求血缘。此模式不兼容 `--raw`、CSV 和 Excel 输出,结果很多时先用 search 的 `--limit` 收窄指标数量。指标取数仍单独使用 `metric query`。
|
|
158
164
|
- 回答指标搜索结果时,必须逐条说明“命中的指标”和“命中方式”:至少包含指标 ID、指标名称、命中条件/字段、命中优先级、命中关键词;不要把用户输入默认解释为指标名称精确匹配。如果结果中有“命中条件”“命中优先级”“命中关键词”列,必须原样纳入结论。
|
|
@@ -181,7 +187,7 @@ guancli app publish --path <project_dir> --app-id <appId> --overwrite-settings
|
|
|
181
187
|
```
|
|
182
188
|
|
|
183
189
|
- 更新已有 SuperApp 时,CLI 会在构建后检查实际 `dist/settings.json`。交互终端会询问:“是否覆盖线上 `settings.json`?”发布应用的授权不等于覆盖线上设置的授权。
|
|
184
|
-
- 只有用户明确回答要覆盖时才传 `--overwrite-settings`,或在 CLI 交互提示中回答 `y
|
|
190
|
+
- 只有用户明确回答要覆盖时才传 `--overwrite-settings`,或在 CLI 交互提示中回答 `y`。该覆盖能力仅在 BI `>= 8.3.2` 时生效;低版本、版本查询失败或响应无法解析时均默认保留线上设置。不要仅因为用户要求“发布应用”就自动追加该参数。
|
|
185
191
|
- 用户回答不明确、没有反馈、非交互任务无法取得确认或确认流程异常时,一律按“不覆盖”处理。CLI 在非交互环境默认从待上传 zip 排除根目录的 `dist/settings.json`,继续发布其他静态资源,并在结果的 `settingsAction` 中返回 `preserved`。
|
|
186
192
|
- 创建全新 SuperApp 时线上尚无 `settings.json`,无需询问覆盖;但通过 `--app-id` 更新,或 `--update-if-exists` 命中同名线上应用时,都必须执行上述确认。
|
|
187
193
|
- 如果运行的是不支持该保护的旧版 guancli,不要冒险发布包含 `settings.json` 的更新产物;应先升级 CLI,不能把缺少确认当作同意。
|
|
@@ -15,13 +15,15 @@
|
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"id": 2,
|
|
18
|
-
"prompt": "
|
|
19
|
-
"expected_output": "
|
|
20
|
-
"files": [
|
|
18
|
+
"prompt": "附件 metric-consumption-metadata.json 包含成功的 metric search/get -f json 返回。请用 jq 分别提取搜索结果每个指标的 ID、名称,以及单个指标详情的适用维度。先检查实际结构,不使用旧展示字段。",
|
|
19
|
+
"expected_output": "读取 schemaVersion/resultMode;search 访问 .search.data[] 的 id/name/dimensions,get 访问 .get.data.dimensions。canonical 元数据与中文业务列分开处理。",
|
|
20
|
+
"files": [
|
|
21
|
+
"fixtures/metric-consumption-metadata.json"
|
|
22
|
+
],
|
|
21
23
|
"expectations": [
|
|
22
|
-
"使用 .[
|
|
23
|
-
"
|
|
24
|
-
"
|
|
24
|
+
"search 使用 envelope.data[] 中的 id/name/dimensions;get 使用 envelope.data 中的 dimensions",
|
|
25
|
+
"不猜测指标ID、指标详情、适用维度等旧展示 JSON key",
|
|
26
|
+
"先确认 CLI 成功,错误时保留 stderr 并停止解析"
|
|
25
27
|
]
|
|
26
28
|
},
|
|
27
29
|
{
|
|
@@ -75,6 +77,33 @@
|
|
|
75
77
|
"原词复购成交贡献保留在首位,去重后总关键词不超过 5 个",
|
|
76
78
|
"不把上一请求的 stop_reason 当成本次请求的搜索结果"
|
|
77
79
|
]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": 7,
|
|
83
|
+
"prompt": "附件是成功的指标 query 返回,请检查结构后用 jq 提取区域和组织名称。给出可执行表达式。",
|
|
84
|
+
"expected_output": "使用 .data[] | {region: .[\"区域\"], organization: .[\"组织\"][\"名称\"]};每一个中文层级都安全引用。",
|
|
85
|
+
"files": [
|
|
86
|
+
"fixtures/metric-consumption-query.json"
|
|
87
|
+
],
|
|
88
|
+
"expectations": [
|
|
89
|
+
"先区分 envelope 和行数组",
|
|
90
|
+
"顶层区域和组织、嵌套名称都用括号加引号,不出现点号直连中文字段",
|
|
91
|
+
"canonical 英文字段说明不覆盖 query 中文字段规则"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": 8,
|
|
96
|
+
"prompt": "附件是本次销售额泛化查询的三个独立返回样本,请分别决定如何读取金额,展示你的检查和选择过程;不要重新请求 BI。",
|
|
97
|
+
"expected_output": "先检查各样本 columns/data keys;renamed 按业务意图确认后读取销售净额,missing 和 ambiguous 明确停止并报告实际列集合,不能猜旧展示列或近似名称。",
|
|
98
|
+
"files": [
|
|
99
|
+
"fixtures/metric-consumption-columns.json"
|
|
100
|
+
],
|
|
101
|
+
"expectations": [
|
|
102
|
+
"读取实际列集合后再编写选择表达式,不预设销售额_recent_7d等展示名",
|
|
103
|
+
"renamed 选择来自实际 columns 的销售净额",
|
|
104
|
+
"missing 没有金额列时停止;ambiguous 存在销售额和销售净额时停止并询问业务口径",
|
|
105
|
+
"不抛 KeyError,不用缺失字段默认零或第一列掩盖歧义"
|
|
106
|
+
]
|
|
78
107
|
}
|
|
79
108
|
]
|
|
80
109
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"renamed": {
|
|
3
|
+
"schemaVersion": "1.0",
|
|
4
|
+
"resultMode": "inline",
|
|
5
|
+
"rowCount": 1,
|
|
6
|
+
"command": "metric.query",
|
|
7
|
+
"columns": [
|
|
8
|
+
"销售净额"
|
|
9
|
+
],
|
|
10
|
+
"data": [
|
|
11
|
+
{
|
|
12
|
+
"销售净额": 12
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"missing": {
|
|
17
|
+
"schemaVersion": "1.0",
|
|
18
|
+
"resultMode": "inline",
|
|
19
|
+
"rowCount": 1,
|
|
20
|
+
"command": "metric.query",
|
|
21
|
+
"columns": [
|
|
22
|
+
"地区"
|
|
23
|
+
],
|
|
24
|
+
"data": [
|
|
25
|
+
{
|
|
26
|
+
"地区": "华东"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"ambiguous": {
|
|
31
|
+
"schemaVersion": "1.0",
|
|
32
|
+
"resultMode": "inline",
|
|
33
|
+
"rowCount": 1,
|
|
34
|
+
"command": "metric.query",
|
|
35
|
+
"columns": [
|
|
36
|
+
"销售额",
|
|
37
|
+
"销售净额"
|
|
38
|
+
],
|
|
39
|
+
"data": [
|
|
40
|
+
{
|
|
41
|
+
"销售额": 12,
|
|
42
|
+
"销售净额": 10
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"search": {
|
|
3
|
+
"schemaVersion": "1.0",
|
|
4
|
+
"resultMode": "inline",
|
|
5
|
+
"rowCount": 1,
|
|
6
|
+
"command": "metric.search",
|
|
7
|
+
"data": [
|
|
8
|
+
{
|
|
9
|
+
"id": "fixture-sales",
|
|
10
|
+
"name": "销售额",
|
|
11
|
+
"dimensions": [
|
|
12
|
+
{
|
|
13
|
+
"name": "地区",
|
|
14
|
+
"id": "region"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"get": {
|
|
21
|
+
"schemaVersion": "1.0",
|
|
22
|
+
"resultMode": "inline",
|
|
23
|
+
"rowCount": 1,
|
|
24
|
+
"command": "metric.get",
|
|
25
|
+
"data": {
|
|
26
|
+
"id": "fixture-sales",
|
|
27
|
+
"name": "销售额",
|
|
28
|
+
"dimensions": [
|
|
29
|
+
{
|
|
30
|
+
"name": "地区",
|
|
31
|
+
"id": "region"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -2,23 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## 首次配置(认证)
|
|
4
4
|
|
|
5
|
-
###
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
guancli auth login --url https://bi.example.com --oidc
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
CLI 自主执行浏览器 OIDC 登录前,必须先在 BI 管理后台注册 Confidential Client 应用,再把生成的 Client ID 和 Client Secret 输入 CLI(也可分别使用 `--client-id` / `GUANCLI_OIDC_CLIENT_ID` 与 `--client-secret` / `GUANCLI_OIDC_CLIENT_SECRET`)。当前仅支持 Confidential Client,不提供客户端类型选择。交互登录会显示当前回调地址,直接回车保持不变,也可输入新地址;非交互场景使用 `--redirect-uri`。回调地址当前仅支持 HTTP loopback,默认登记地址为 `http://127.0.0.1/auth/oidc/callback`;CLI 会保留登记地址的 host/path,并始终将端口替换成本次本地 listener 的随机端口。回调地址必须存在于 BI OIDC 应用的回调地址配置中,否则授权请求会被拒绝。Token 默认与 Client ID、Client Secret 一起写入权限为 `0600` 的配置文件;使用 `--token-store keyring` 时,Token、Client ID 和 Client Secret 会一起保存到 macOS Keychain、Windows Credential Manager 或 Linux Secret Service,配置文件只保留凭据引用和非敏感 OIDC 元数据。已有 profile 重新登录时会沿用原存储方式,只有显式传入 `--token-store` 才切换。
|
|
12
|
-
|
|
13
|
-
Access Token 到期后自动使用 Refresh Token 刷新。Refresh Token 不可用时,macOS 和 Windows 会自动输出新的登录 URL、尝试打开系统默认浏览器并等待回调;Linux 和尚未适配的平台不会让普通 CLI 请求突然进入浏览器交互,而是明确提示执行 `guancli auth login --profile <name> --oidc`。用户在 Linux 主动执行 `auth login --oidc` 时仍会尝试通过 `xdg-open` 打开浏览器,失败后可复制终端中的 URL。当前 callback listener 仅支持本机 loopback,不支持公开 HTTPS 回调或跨设备 callback relay。
|
|
14
|
-
|
|
15
|
-
OIDC Base URL 支持 HTTP 和 HTTPS。传入 BI Web 根地址时,若根路径没有返回有效 Discovery,CLI 会兼容尝试 `/backend/.well-known/openid-configuration`;传入带路径的 URL 时则严格使用该路径。HTTPS 环境的 Discovery 不允许把 authorization/token/JWKS 等端点降级到 HTTP;测试环境可以直接使用 HTTP Base URL。CLI 不提供忽略自签名 HTTPS 证书校验的开关。浏览器打开前,CLI 会用一个不会成功兑换 Token 的占位授权码向 token endpoint 预检 Confidential Client 凭据:`invalid_grant` 表示 client_id/client_secret 已通过认证并继续登录;错误 client_id 或 client_secret 返回的 `invalid_client` 会立即结束,不再打开浏览器等待 callback;其他未覆盖的 OAuth 错误原样返回。
|
|
16
|
-
|
|
17
|
-
如果 BI 对 Discovery 返回业务状态 `5001` 且提示 `No static resource .well-known/openid-configuration`,CLI 会明确提示“目标 BI 环境不支持 OIDC”,并建议管理员开启 OIDC 功能或升级 BI 版本,不再只暴露底层 HTTP 500。对于已部署 OIDC 但当前用户域或应用在功能层面禁用登录的环境,兼容版本服务端会通过 loopback callback 立即返回 `access_denied`;CLI 将该稳定错误转换为同一“不支持 OIDC”提示,不再等待 callback 超时。其他未覆盖的 OAuth 授权错误保留服务端返回的 `error` 和 `error_description`,不静默改写。
|
|
18
|
-
|
|
19
|
-
上游 Agent 平台只需通过 `GUANCLI_OIDC_BASE_URL` 和 `GUANCLI_OIDC_ACCESS_TOKEN` 注入目标 BI 环境和托管 Token。Base URL 与 Access Token 是不可拆分的一组配置,缺少任意一个都会明确报错,不会回退或混用本地 profile。检测到完整配置后,普通业务命令可直接使用这组环境变量,不要求本地预先存在 profile;执行 `auth login` 或 `auth login --oidc` 时也会直接创建 external OIDC profile,不再要求 client_id/client_secret,不打开浏览器,并以环境变量 Base URL 覆盖已有 profile URL。完整 external OIDC 配置与 `--token`、`--pat`、账密参数不能同时使用,CLI 会立即提示参数冲突,避免保存一个实际不会被当前请求使用的本地身份。未检测到 Access Token 时才进入正常浏览器认证流程。命中上游 Token 后 guancli 只消费 Access Token,不接收外部 RefreshToken、不保存任何 Token,Access Token 过期或收到 401 时也不会回退到本地身份或触发浏览器登录,只提示由上游更新 AccessToken 后重试。
|
|
20
|
-
|
|
21
|
-
### 方式二:用户名密码登录
|
|
5
|
+
### 方式一:用户名密码登录
|
|
22
6
|
|
|
23
7
|
```bash
|
|
24
8
|
guancli auth login
|
|
@@ -27,20 +11,20 @@ guancli auth login
|
|
|
27
11
|
交互式输入:
|
|
28
12
|
1. 环境名称(默认 `default`,可自定义如 `staging`、`prod`)
|
|
29
13
|
2. BI 系统 URL(如 `https://bi.example.com`)
|
|
30
|
-
3. 选择登录方式:`
|
|
14
|
+
3. 选择登录方式:`1` 用户名密码
|
|
31
15
|
4. Domain(如 `demo`)
|
|
32
16
|
5. 用户名(邮箱)
|
|
33
17
|
6. 密码
|
|
34
18
|
|
|
35
19
|
账号或密码错误时,交互式登录会保留已输入的环境、URL、Domain 和 Login ID,直接提示重新输入密码。登录成功后 Token 自动保存在系统标准配置目录下的 `guancli/config.json`,并自动切换到刚登录的环境;无需再执行 `auth use`。密码方式支持 Token 过期后自动刷新。
|
|
36
20
|
|
|
37
|
-
###
|
|
21
|
+
### 方式二:直接输入 uIdToken
|
|
38
22
|
|
|
39
23
|
```bash
|
|
40
24
|
guancli auth login
|
|
41
25
|
```
|
|
42
26
|
|
|
43
|
-
选择登录方式 `
|
|
27
|
+
选择登录方式 `2`,直接粘贴已有的 uIdToken。适用于已从 Web 界面或其他途径获取 uIdToken 的场景。
|
|
44
28
|
|
|
45
29
|
如需按登录 Domain 筛选这个 profile,可在非交互式登录时同时保存:
|
|
46
30
|
|
|
@@ -48,16 +32,32 @@ guancli auth login
|
|
|
48
32
|
guancli auth login --url https://bi.example.com --domain demo --token <uid-token>
|
|
49
33
|
```
|
|
50
34
|
|
|
51
|
-
###
|
|
35
|
+
### 方式三:Personal Access Token
|
|
52
36
|
|
|
53
37
|
```bash
|
|
54
38
|
guancli auth login --url https://bi.example.com --pat <pat>
|
|
55
39
|
```
|
|
56
40
|
|
|
57
|
-
交互式登录时选择登录方式 `
|
|
41
|
+
交互式登录时选择登录方式 `3`,直接粘贴 Personal Access Token。`--personal-token` 仍可作为长参数使用。PAT 请求会自动携带 `X-Personal-Token`,`X-Guandata-Client` 沿用请求来源(默认 `guancli`;高层 skill 经内部请求通道调用时保留其自身来源),`auth status` 会通过 `/api/pat/introspect` 做自检,且仅在响应明确返回 `usable: true`(兼容历史 `active: true`)时判定有效。
|
|
58
42
|
|
|
59
43
|
`chatbi` 子命令支持 uIdToken 或 OIDC Access Token;PAT 仍不支持。
|
|
60
44
|
|
|
45
|
+
### 方式四:浏览器 OIDC 登录
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
guancli auth login --url https://bi.example.com --oidc
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
CLI 自主执行浏览器 OIDC 登录前,必须先在 BI 管理后台注册 Confidential Client 应用,再把生成的 Client ID 和 Client Secret 输入 CLI(也可分别使用 `--client-id` / `GUANCLI_OIDC_CLIENT_ID` 与 `--client-secret` / `GUANCLI_OIDC_CLIENT_SECRET`)。当前仅支持 Confidential Client,不提供客户端类型选择。交互登录会显示当前回调地址,直接回车保持不变,也可输入新地址;非交互场景使用 `--redirect-uri`。回调地址当前仅支持 HTTP loopback,默认登记地址为 `http://127.0.0.1/auth/oidc/callback`;CLI 会保留登记地址的 host/path,并始终将端口替换成本次本地 listener 的随机端口。回调地址必须存在于 BI OIDC 应用的回调地址配置中,否则授权请求会被拒绝。Token 默认与 Client ID、Client Secret 一起写入权限为 `0600` 的配置文件;使用 `--token-store keyring` 时,Token、Client ID 和 Client Secret 会一起保存到 macOS Keychain、Windows Credential Manager 或 Linux Secret Service,配置文件只保留凭据引用和非敏感 OIDC 元数据。已有 profile 重新登录时会沿用原存储方式,只有显式传入 `--token-store` 才切换。
|
|
52
|
+
|
|
53
|
+
Access Token 到期后自动使用 Refresh Token 刷新。Refresh Token 不可用时,macOS 和 Windows 会自动输出新的登录 URL、尝试打开系统默认浏览器并等待回调;Linux 和尚未适配的平台不会让普通 CLI 请求突然进入浏览器交互,而是明确提示执行 `guancli auth login --profile <name> --oidc`。用户在 Linux 主动执行 `auth login --oidc` 时仍会尝试通过 `xdg-open` 打开浏览器,失败后可复制终端中的 URL。当前 callback listener 仅支持本机 loopback,不支持公开 HTTPS 回调或跨设备 callback relay。
|
|
54
|
+
|
|
55
|
+
OIDC Base URL 支持 HTTP 和 HTTPS。传入 BI Web 根地址时,若根路径没有返回有效 Discovery,CLI 会兼容尝试 `/backend/.well-known/openid-configuration`;传入带路径的 URL 时则严格使用该路径。HTTPS 环境的 Discovery 不允许把 authorization/token/JWKS 等端点降级到 HTTP;测试环境可以直接使用 HTTP Base URL。CLI 不提供忽略自签名 HTTPS 证书校验的开关。浏览器打开前,CLI 会用一个不会成功兑换 Token 的占位授权码向 token endpoint 预检 Confidential Client 凭据:`invalid_grant` 表示 client_id/client_secret 已通过认证并继续登录;错误 client_id 或 client_secret 返回的 `invalid_client` 会立即结束,不再打开浏览器等待 callback;其他未覆盖的 OAuth 错误原样返回。
|
|
56
|
+
|
|
57
|
+
如果 BI 对 Discovery 返回业务状态 `5001` 且提示 `No static resource .well-known/openid-configuration`,CLI 会明确提示“目标 BI 环境不支持 OIDC”,并建议管理员开启 OIDC 功能或升级 BI 版本,不再只暴露底层 HTTP 500。对于已部署 OIDC 但当前用户域或应用在功能层面禁用登录的环境,兼容版本服务端会通过 loopback callback 立即返回 `access_denied`;CLI 将该稳定错误转换为同一“不支持 OIDC”提示,不再等待 callback 超时。其他未覆盖的 OAuth 授权错误保留服务端返回的 `error` 和 `error_description`,不静默改写。
|
|
58
|
+
|
|
59
|
+
上游 Agent 平台只需通过 `GUANCLI_OIDC_BASE_URL` 和 `GUANCLI_OIDC_ACCESS_TOKEN` 注入目标 BI 环境和托管 Token。Base URL 与 Access Token 是不可拆分的一组配置,缺少任意一个都会明确报错,不会回退或混用本地 profile。检测到完整配置后,普通业务命令可直接使用这组环境变量,不要求本地预先存在 profile;执行 `auth login` 或 `auth login --oidc` 时也会直接创建 external OIDC profile,不再要求 client_id/client_secret,不打开浏览器,并以环境变量 Base URL 覆盖已有 profile URL。完整 external OIDC 配置与 `--token`、`--pat`、账密参数不能同时使用,CLI 会立即提示参数冲突,避免保存一个实际不会被当前请求使用的本地身份。未检测到 Access Token 时才进入正常浏览器认证流程。命中上游 Token 后 guancli 只消费 Access Token,不接收外部 RefreshToken、不保存任何 Token,Access Token 过期或收到 401 时也不会回退到本地身份或触发浏览器登录,只提示由上游更新 AccessToken 后重试。
|
|
60
|
+
|
|
61
61
|
### 多环境管理
|
|
62
62
|
|
|
63
63
|
```bash
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Read a successful metric.query envelope; emit its row array for processing."""
|
|
2
2
|
|
|
3
|
+
import argparse
|
|
3
4
|
import json
|
|
4
5
|
import sys
|
|
5
6
|
from pathlib import Path
|
|
@@ -32,8 +33,51 @@ def query_rows(envelope):
|
|
|
32
33
|
return rows
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
def query_columns(envelope):
|
|
37
|
+
columns = envelope["columns"]
|
|
38
|
+
if (any(not isinstance(column, str) or not column for column in columns)
|
|
39
|
+
or len(set(columns)) != len(columns)):
|
|
40
|
+
raise ValueError("invalid or ambiguous columns: " + json.dumps(columns, ensure_ascii=False))
|
|
41
|
+
return columns
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def select_column(columns, rows, candidates):
|
|
45
|
+
# Candidates must come from observed columns and confirmed business intent.
|
|
46
|
+
# Never infer meaning from a suffix, approximate spelling or column order.
|
|
47
|
+
matches = [column for column in columns if column in candidates]
|
|
48
|
+
available = json.dumps(columns, ensure_ascii=False)
|
|
49
|
+
if len(matches) != 1:
|
|
50
|
+
raise ValueError("expected exactly one matching column; actual columns: " + available)
|
|
51
|
+
column = matches[0]
|
|
52
|
+
for index, row in enumerate(rows):
|
|
53
|
+
if column not in row:
|
|
54
|
+
raise ValueError(f"column missing in row {index}; actual columns: {available}; "
|
|
55
|
+
"row keys: " + json.dumps(list(row), ensure_ascii=False))
|
|
56
|
+
return [{column: row[column]} for row in rows]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main():
|
|
60
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
61
|
+
parser.add_argument("envelope", help="stdout JSON from a successful metric query -f json")
|
|
62
|
+
selection = parser.add_mutually_exclusive_group()
|
|
63
|
+
selection.add_argument("--list-columns", action="store_true", help="inspect actual column names first")
|
|
64
|
+
selection.add_argument("--column", action="append", help="exact candidate; repeat only for confirmed alternatives")
|
|
65
|
+
args = parser.parse_args()
|
|
66
|
+
try:
|
|
67
|
+
with open(args.envelope, encoding="utf-8") as source:
|
|
68
|
+
envelope = json.load(source)
|
|
69
|
+
rows = query_rows(envelope)
|
|
70
|
+
result = rows
|
|
71
|
+
if args.list_columns or args.column:
|
|
72
|
+
columns = query_columns(envelope)
|
|
73
|
+
result = columns if args.list_columns else select_column(columns, rows, args.column)
|
|
74
|
+
except (ValueError, KeyError, TypeError, OSError) as error:
|
|
75
|
+
print(f"Cannot consume metric query: {error}", file=sys.stderr)
|
|
76
|
+
return 1
|
|
77
|
+
json.dump(result, sys.stdout, ensure_ascii=False)
|
|
39
78
|
print()
|
|
79
|
+
return 0
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if __name__ == "__main__":
|
|
83
|
+
sys.exit(main())
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# 同轮指标批量查询
|
|
2
|
+
|
|
3
|
+
`guancli metric batch-query --input queries.json`。完整原生 guancli 也可用 `--input -` 从 stdin 读取 JSON 数组;kit/lite 的 stdin 用于宿主协议,必须使用文件输入。
|
|
4
|
+
同一轮已经确定的独立查询一次提交,CLI 管理并发;读完结果才能确定的下一轮单独提交。
|
|
5
|
+
不要编写循环逐个 `metric query` 或自行安排 Shell 并发。
|
|
6
|
+
|
|
7
|
+
已确认输入契约时直接复用;缺少必要信息或遇到参数错误时再看 `guancli metric batch-query --help`;多条件筛选示例见 [metric-commands.md](metric-commands.md) 的“结构化条件树示例”。筛选组使用 `conditions` 数组,不使用资源 tree 的 `children`。只使用已确认的指标字段及取值;按错误指出的字段修正,不连续猜键名。
|
|
8
|
+
|
|
9
|
+
参数确定后将所有独立查询写入同一批次并直接执行;dry-run 仅用于检查计划或排查复杂参数,不作为每批取数的前置步骤。需要 dry-run 时,加 `--fail-on-error` 可让任一计划失败返回非零;全部通过后可用 `&&` 执行同一输入。默认模式仍需检查每项 `status=planned`。正式执行默认模式先检查各项状态;使用 `--fail-on-error` 且退出成功时可直接处理结果,无需重复逐项检查状态。只读查询允许与结果保存、检查和计算组合执行;无法生成结构化运行轨迹时接受降级,不为轨迹增加调用。
|
|
10
|
+
|
|
11
|
+
批量查询的“保存 + 成功后摘要”示例(queries.json 使用已确认参数):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
guancli metric batch-query --input queries.json --fail-on-error -f json > results.json &&
|
|
15
|
+
python3 - <<'PYTHON'
|
|
16
|
+
import json
|
|
17
|
+
with open("results.json") as source:
|
|
18
|
+
items = json.load(source)["results"]
|
|
19
|
+
print(json.dumps([{"id": item["id"], "columns": item["result"]["columns"],
|
|
20
|
+
"rowCount": item["result"]["rowCount"],
|
|
21
|
+
"sampleRows": item["result"]["rows"][:5]} for item in items], ensure_ascii=False))
|
|
22
|
+
PYTHON
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
摘要只展示样例;需要全量计算时在同一本地步骤中使用 results.json 的完整结果,并核对 limit 与完整性。
|
|
26
|
+
仅需直接阅读且输出已足够精简时直接消费 CLI 输出。已有结果的状态检查、完整性检查和计算也在一次本地执行中完成;字段缺失、多义或结果不完整时返回证据,不猜字段、不删筛选。不要为缩短往返扩大数据范围或省略业务校验。
|
|
27
|
+
|
|
28
|
+
每项必填唯一非空 `id` 和真实 `metricId`。时间范围通过 `filters` 表达,省略表示不额外筛选;支持现有结构化条件树和操作符,不支持需要拆分聚合的多分支 OR。基础查询与 `metric query` 一样,使用指标关联的趋势图卡片,缺失时回退指标值卡片;每项创建独立编辑会话。日期粒度筛选、日期子粒度分组和排序沿用 `metric query` 的能力。错误或不支持的条件显式失败,禁止删除条件后重试以伪装成功。
|
|
29
|
+
|
|
30
|
+
- `dimensions`:非空维度名称数组;省略时沿用关联卡片的默认分组,显式提供时覆盖该项独立编辑会话的分组。空数组会被拒绝;支持 `日期 toMonth` 等现有粒度语法。
|
|
31
|
+
- `sortAsc` / `sortDesc`:互斥;解析和执行语义与 `metric query` 一致。日期子粒度排序使用同一限定表达式,例如 `日期 toMonth`。
|
|
32
|
+
- `limit`:默认 50,必须为正数。`offset` 默认 0,非负;`offset + limit` 最多 10000。非零 offset 必须显式排序。后端无 offset,CLI 请求至 offset+limit 后截取,不代表全量遍历;排序相同值和跨请求数据变化可能使跨页不稳定,严格分页需选择能唯一定位顺序的分组。
|
|
33
|
+
- `valueFormat`:支持 `raw`(默认)、`formatted` 和 `both`。`raw` 保留 JSON 数字、null 和维度值;`formatted` 沿用 `metric query --value-format formatted` 的指标格式规则,把指标列输出为带精度、千分位、百分号或单位的字符串,维度列保持原值。排序和分页始终基于格式化前的原始值。需要计算并展示同一结果时使用 `both`,一次取数返回原始 `rows` 和位置完全对应的 `formattedRows`,不要为两种格式提交重复查询。
|
|
34
|
+
- `--dry-run`:读取指标详情后生成每项取数请求计划,不执行指标取数,不代表权限、执行或数据完整性已经通过。
|
|
35
|
+
|
|
36
|
+
完整 guancli 固定并发 10,不限制查询项数量,输入文件至多 1 MiB;超过 10 项的部分排队。batch 不设置整批超时,每个底层接口沿用 `metric query` 的 HTTP 单请求超时。结果逐项写入临时 spool,最终按输入顺序流式输出,内存占用随并发度而不是查询项总数增长;命令取消会传到底层 HTTP 并等待在途 worker 收口。无缓存、无跨批结果复用。每项使用后端生成的独立 UUID 编辑会话,不保存关联卡片;编辑会话生命周期沿用现有 `metric query` 和 BI 后端策略。kit/lite 入口还受宿主实际请求预算约束,超过预算时由 dispatcher 按真实请求数停止。
|
|
37
|
+
|
|
38
|
+
## 稳定 JSON 协议 v1
|
|
39
|
+
|
|
40
|
+
顶层 `schemaVersion: "1.0"`、`command: "metric.batch-query"`、`status`、`results`。全部完成成功为 `success`,存在失败为 `partial_failure`。默认有效批次输出完整汇总后退出 0,包括含失败项的批次。使用 `--fail-on-error` 时,任一项为 error 都在输出完整 JSON 后以非零退出,成功项仍保留;适用于正式查询和 dry-run,全部 success 或全部 planned 时退出 0。输入/认证初始化等批次级错误退出非零。
|
|
41
|
+
|
|
42
|
+
每项保留输入 `id`、`metricId`,按输入顺序返回。`status` 为 `success` / `error` / `planned`;成功时 `result` 包含 `resultMode: "inline"`、实际采用的 `valueFormat`、`columns: [{name,role}]`、`rows` 二维数组、`rowCount`、`offset`、`limit`。raw 模式的指标值保持 JSON 数字;formatted 模式的指标值为展示字符串。both 模式的 `rows` 与 raw 相同,并额外提供 `formattedRows`(包括空结果时的 `[]`),与 rows 共用列、排序和分页;计算读取 rows,展示读取 formattedRows。其它模式不输出 formattedRows。列名直接来自 BI,角色为 dimension/metric,位置与行值一一对应;不存在以本地化展示字段反推新协议的转换。错误为 `error: {code,message,httpStatus?,businessStatus?}`,已有 HTTP/业务状态直接透传,检查每项错误再分析其余成功结果;后端必需字段缺失、类型或行宽变化报 `METRIC_RESPONSE_INVALID`。
|
|
43
|
+
|
|
44
|
+
原生执行 `timingScope: "native"`,顶层提供 `durationMs`、`concurrencyLimit`、`requestCount`(逻辑 BI 调用数,包含详情、会话和取数,认证重试不计);每项基础查询通常 3 次调用,显式维度或排序时通常 5 次。每项提供 UTC `startedAt`、`finishedAt`、`durationMs`,可据此检查重叠。
|
|
45
|
+
|
|
46
|
+
lite/kit 执行会在 replay 轮汇集独立请求;只读请求可标为 parallel,编辑会话 modify 按现有 mutating 契约串行。实际执行并发/时间由宿主负责,`timingScope: "host"` 时不返回原生计时、请求数和并发字段,不能把 kit 重放耗时当成 BI 耗时。现有原生 lite 宿主最多 8 路,WASI 宿主为单路,WASI 不提供本次并发性能保证;完整 guancli 是本次性能验收入口。宿主的总时限沿用其现有策略。
|
|
47
|
+
|
|
48
|
+
## 服务端与权限边界
|
|
49
|
+
|
|
50
|
+
复用 `metric query` 的接口链:`GET /api/metric-platform/metrics/{metricId}`、`GET /api/card/{cardId}/edit/session`、`POST /api/card/{cardId}/edit/{sessionId}/data`;显式维度或排序时还会调用 `GET /api/card/{cardId}/edit` 和 `POST /api/oriput/card/{cardId}/edit/{sessionId}/modify`。代理还原后的 Spring 路由均已确认存在。指标详情要求 `METRIC_PLATFORM/read`(PAT pId 90/read);卡片会话、modify 和取数要求 `BASE/read`,读取编辑配置还要求 `PAGE/update`(PAT 仪表板 pId 1/update)。所以仅查询卡片保存配置时 pId 90/read 可用,显式 dimensions 或 sorting 时 PAT 还要包含仪表板 update;权限不足会逐项返回 403,不能扩大用户资源权限。
|
|
51
|
+
|
|
52
|
+
每项读取指标关联卡片并在独立编辑会话中取数,不拼接多个聚合结果。未显式提供 dimensions 时保留卡片默认分组;提供 dimensions 或 sorting 时只覆盖该项会话中的对应配置,filters 作为本次取数条件传入。指标详情、卡片配置与取数之间不保证快照;改名、发布或权限变化由服务端最终裁决。当前 batch 输入不包含同比、XTD、recent、占比和排名等高级计算;这些仍由单条 `metric query` 的 v2 分支处理,后续若加入 batch 必须沿用相同分流。
|
|
@@ -301,7 +301,9 @@ guancli metric query <metric_id> --profile default --dim "订单日期 toMonth"
|
|
|
301
301
|
| 空值 | `IS_NULL`、`NOT_NULL` |
|
|
302
302
|
| 字符串 | `CONTAINS`、`NOT_CONTAINS`、`STARTSWITH`、`NOT_STARTSWITH`、`ENDSWITH`、`NOT_ENDSWITH` |
|
|
303
303
|
|
|
304
|
-
`--filter`
|
|
304
|
+
`--filter` 支持 `=`、`!=`/`<>`、`<`、`<=`、`>`、`>=`,分别归一为 `EQ`、`NE`、`LT`、`LE`、`GT`、`GE`;原枚举写法继续有效。优先写 `--filter '日期 >= 2026-01-01'`,保留操作符两侧空格并引用整个参数。`--filter-json`、`--filter-file` 和 batch-query 的 `operator` 同样支持符号,规范化输出及 BI 请求仍使用枚举。
|
|
305
|
+
|
|
306
|
+
`BT` 接受逗号分隔的两个值,也接受两个不含空格的边界用空格分隔,例如 `--filter '日期 BT 20260101 20260131'`。边界本身含空格(如完整日期时间)时继续用逗号分隔;不推测三个或更多空格分段的边界。
|
|
305
307
|
|
|
306
308
|
示例:
|
|
307
309
|
|
|
@@ -335,7 +337,7 @@ guancli metric query <metric_id> --profile <profile> \
|
|
|
335
337
|
--limit 100
|
|
336
338
|
```
|
|
337
339
|
|
|
338
|
-
出现筛选语法错误后,先执行 `guancli metric query --help`
|
|
340
|
+
出现筛选语法错误后,先执行 `guancli metric query --help` 并按帮助纠正;不要猜测未支持的操作符(例如 `==`)。`--columns` 已能在 Go 端稳定裁剪结果列,不要为这一步额外拼 jq。
|
|
339
341
|
|
|
340
342
|
结构化条件树示例:
|
|
341
343
|
|
|
@@ -522,6 +524,19 @@ bash references/examples/metric-query.sh <metric_id> <profile> &&
|
|
|
522
524
|
|
|
523
525
|
`examples/metric-query-rows.py` 检查 schemaVersion、command、resultMode 和行数;file 模式只从 envelope 的绝对 `path` 读取,不无条件遍历 `data`。上例中文嵌套字段仅演示引用语法,实际字段以 `columns`/数据为准。每一个中文层级都使用 `["字段名"]`。
|
|
524
526
|
|
|
527
|
+
#### 先发现列,再选择
|
|
528
|
+
|
|
529
|
+
禁止在加工脚本中硬编码指标展示列名,或根据指标名称、高级计算后缀、列位置猜列。先检查 `columns` 和行对象 keys,并按当前业务意图确认候选;存在多个候选时不能自动选第一个。下面参数属于 Python recipe,不是 query 命令的新参数:
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
# 复用已成功查询的 envelope,不为发现列重复请求 BI。
|
|
533
|
+
python3 references/examples/metric-query-rows.py query-envelope.json --list-columns
|
|
534
|
+
# 阅读实际列集合并确认业务含义后,替换占位符;不要原样执行。
|
|
535
|
+
python3 references/examples/metric-query-rows.py query-envelope.json --column "<已确认的实际列名>"
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
`--column` 可重复传入经过业务确认的备选名称;与实际列精确匹配后必须恰好剩一列。零匹配、多匹配、重复列名或某行缺少该列都会非零退出,stderr 返回实际列集合,stdout 不输出部分结果;不做近似匹配、不触发 KeyError、不把缺失当 null。真正的 null 保留为 null。选择成功仍输出行对象数组;不传新增参数时保持原有整行输出。空结果可发现声明列,但不能据此宣称存在业务数据。
|
|
539
|
+
|
|
525
540
|
### 日期与 IN 使用同一种筛选输入
|
|
526
541
|
|
|
527
542
|
先通过 get 确认日期、城市存在且类型相符。完整条件树见 `examples/metric-date-in.json`:
|
|
@@ -535,3 +550,6 @@ guancli metric query <metric_id> --profile <profile> \
|
|
|
535
550
|
```
|
|
536
551
|
|
|
537
552
|
普通 `--filter`、可重复 `--filter-json`、单个 `--filter-file` 三选一。dry-run 成功只表示计划校验通过,实际执行仍由 BI 决定。
|
|
553
|
+
# 同轮独立查询
|
|
554
|
+
|
|
555
|
+
多项已确定、彼此独立且参数能被 batch 完整表达的基础指标查询,使用 `metric batch-query --input queries.json`,禁止 Shell 循环逐条取数。同比、XTD、recent、占比、排名等高级计算继续使用单条 `metric query`;同轮其余基础查询仍单独组成 batch。详见 [批量协议与示例](metric-batch-query.md)。依赖结果的后续查询在下一轮提交。
|
|
@@ -194,8 +194,16 @@ guancli metric query <metric_id> --profile default --dim 日期 --recent 7d --ra
|
|
|
194
194
|
|
|
195
195
|
```bash
|
|
196
196
|
guancli metric query <metric_id> --profile default --dim 省份 --compare yoy --filter "省份 EQ 河南省" --limit 5
|
|
197
|
-
guancli metric query <metric_id> --profile default --dim 日期 --recent 7d
|
|
197
|
+
guancli metric query <metric_id> --profile default --dim 日期 --recent 7d -f json --limit 10
|
|
198
198
|
guancli metric query <metric_id> --profile default --dim 城市 --rank-top 5 --rank-order desc --rank-dim 城市 -f json
|
|
199
199
|
```
|
|
200
200
|
|
|
201
201
|
机器输出使用 `-f json`,与普通 query 共享 envelope 契约;先确认 CLI 成功,再按 `resultMode` 读取 `data` 或 `path` 中的行数组。完整可执行消费示例见 [指标命令](metric-commands.md#查询结果消费)。
|
|
202
|
+
|
|
203
|
+
### 泛化结果列的发现与选择
|
|
204
|
+
|
|
205
|
+
`--recent/--xtd/--compare` 的窗口和展示列名不能互相推导。消费前先读实际 `columns` 和行对象 keys,禁止硬编码展示列名或拼接 `_recent_7d` 等后缀;仅按业务意图确认实际列,不按列顺序或近似名称猜测。列缺失或多个候选同时存在时停止,返回实际列集合。
|
|
206
|
+
|
|
207
|
+
复用 [查询结果消费 recipe](metric-commands.md#查询结果消费):成功取得 `-f json` envelope 后,用 `python3 references/examples/metric-query-rows.py query-envelope.json --list-columns` 发现列,再用 `--column "<已确认的实际列名>"` 精确选择。这些是 Python recipe 参数,不是 query 参数。inline/file 分支、失败时保留 stderr 和停止解析沿用同一 recipe。
|
|
208
|
+
|
|
209
|
+
每一个中文层级都使用括号加引号,例如 `.data[] | .["组织"]["名称"]`;canonical 英文元数据字段不能替代中文业务列的安全引用规则。示例只演示嵌套引用语法,使用前须在实际数据中确认字段。
|