@guandata/guancli 1.0.56 → 1.0.58
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 +12 -0
- package/README.md +11 -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 +1 -1
- package/skills/guancli/SKILL.md +11 -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-date-in.json +7 -0
- package/skills/guancli/references/examples/metric-query-rows.py +83 -0
- package/skills/guancli/references/examples/metric-query.sh +6 -0
- package/skills/guancli/references/metric-batch-query.md +38 -0
- package/skills/guancli/references/metric-commands.md +95 -16
- package/skills/guancli/references/metric-generic-query.md +12 -2
- package/skills/guancli/references/metric-json-migration.md +18 -0
- package/skills/guancli/references/preview-and-output.md +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## @guandata/guancli 1.0.58 - 2026-09-11
|
|
4
|
+
|
|
5
|
+
- 新增 `metric batch-query`:把同轮已确定、互不依赖的多个基础指标查询写成一份 JSON 一次提交,CLI 自动调度并发并按输入顺序逐项返回,输出 `schemaVersion: 1.0` 稳定机器契约,失败逐项归因,退出 0 不代表每项都成功。
|
|
6
|
+
- 批量查询支持维度、日期子粒度、排序、分页与 `valueFormat`(raw/formatted);格式化输出沿用指标格式配置,排序和分页始终基于原始值。同比、XTD、recent、占比和排名等高级计算仍使用单条 `metric query`。
|
|
7
|
+
- 指标结果消费补充动态列发现与精确选择规范,禁止在脚本中硬编码展示列名;登录方式顺序调整为 1 用户名密码、2 uIdToken、3 Personal Access Token、4 浏览器 OIDC,并移除推荐标记。
|
|
8
|
+
|
|
9
|
+
## @guandata/guancli 1.0.57 - 2026-09-09
|
|
10
|
+
|
|
11
|
+
- 统一指标查询的 JSON 输入与输出契约,补充日期维度子类型和日期筛选示例,脚本处理更稳定。
|
|
12
|
+
- `metric search` 支持按指标状态筛选。
|
|
13
|
+
- 卡片预览会标注本次生效的筛选条件及来源,并支持 `FIRST_PICK`、`MAX` 运行态默认值和级联选择器。
|
|
14
|
+
|
|
3
15
|
## @guandata/guancli 1.0.56 - 2026-09-03
|
|
4
16
|
|
|
5
17
|
- 指标查询默认按指标或查询列的格式配置展示数值,支持数值、货币、百分比、小数位、千分位、数量级和前后缀等格式。
|
package/README.md
CHANGED
|
@@ -43,6 +43,17 @@ guancli chatbi query --theme-name "经营主题" --message "最近30天营业收
|
|
|
43
43
|
|
|
44
44
|
## 版本更新
|
|
45
45
|
|
|
46
|
+
### @guandata/guancli 1.0.58
|
|
47
|
+
|
|
48
|
+
- 新增 `metric batch-query`:同轮已确定、互不依赖的多个基础指标查询可写成一份 JSON 一次提交,CLI 自动调度并发并按输入顺序逐项返回,失败逐项归因。
|
|
49
|
+
- 批量查询支持维度、日期子粒度、排序、分页和 `valueFormat`;格式化输出沿用指标格式配置,排序分页基于原始值。
|
|
50
|
+
- 指标结果消费补充动态列发现与精确选择规范,避免硬编码展示列名;登录方式顺序与提示同步更新。
|
|
51
|
+
|
|
52
|
+
### @guandata/guancli 1.0.57
|
|
53
|
+
|
|
54
|
+
- 统一指标查询 JSON 契约,补充日期维度与筛选示例,并支持按状态搜索指标。
|
|
55
|
+
- 卡片预览会标注生效筛选及来源,支持运行态默认值和级联选择器。
|
|
56
|
+
|
|
46
57
|
### @guandata/guancli 1.0.56
|
|
47
58
|
|
|
48
59
|
- 指标查询默认遵循指标或查询列的数值格式,覆盖货币、百分比、精度、千分位、数量级和前后缀。
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/skills/guancli/SKILL.md
CHANGED
|
@@ -54,7 +54,7 @@ guancli 是 BI 资源的**查询分析入口**,并支持 Form 表单填报 CRU
|
|
|
54
54
|
6. 先判断资源类型:ETL 用 `etl`,数据集用 `ds`,页面/仪表板用 `page`,卡片用 `card`,表单填报用 `form`。
|
|
55
55
|
7. 信息不全时先 `tree` 或 `search`,拿到 ID 后再 `get`;目录名能出现在 `ds tree`,不代表同词一定能命中 `ds search`。三棵 `tree` 都支持 `--max-depth N` / `--keyword 词`(客户环境目录树可达数千节点,全量输出会被截断,默认先 `--max-depth 2` 再按需加深)。
|
|
56
56
|
8. 用户给的是业务目录名而不是数据集名时,先 `ds tree` 定位目录,再在目录内按真实表名搜索,或从已有 `page/card` 反查 `dsId`。
|
|
57
|
-
9.
|
|
57
|
+
9. 用户要查看/分析某个页面(仪表板)上的卡片数据时,默认所见即所得:用 `card preview <cd_id> --with-default-filters` 应用页面筛选器默认值(含 FIRST_PICK / 日历 MAX 的运行态求值和级联),并把结果页脚 `筛选:` 行(stderr 也有同样说明)里的生效条件原样带进结论,标明数据是筛选后的而非全量;`筛选: 无(未应用页面筛选器默认值…)` 表示裸取数。用户明确不要页面筛选、或已自行给出筛选条件时才裸取数;报错“暂不支持”时如实告知该筛选器未生效,不要静默改成裸取数。卡片属于多个页面时,根据报错列出的候选页面请用户确认,再传 `--page-id <pg_id>`。
|
|
58
58
|
|
|
59
59
|
## 按需读取资料
|
|
60
60
|
|
|
@@ -70,6 +70,8 @@ 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 自动调度并逐项返回结果;用 `id` 对齐每项 `status`,不能把进程退出 0 当成所有查询成功。后续查询依赖本轮结果时,读取本轮结果后再生成下一批。搜索并需要详情时使用 `metric search --with-detail`,避免逐项 get。批量输入、分页与支持边界见 [metric-batch-query.md](references/metric-batch-query.md)。
|
|
74
|
+
|
|
73
75
|
```bash
|
|
74
76
|
guancli etl tree --max-depth 2
|
|
75
77
|
guancli ds tree --max-depth 2
|
|
@@ -144,15 +146,18 @@ guancli 在这条链路上只出只读的那一环:`guancli page search` / `pa
|
|
|
144
146
|
## 指标关键规则
|
|
145
147
|
|
|
146
148
|
- **先按下面的命令契约生成,不要猜 shell、jq 或筛选语法**:
|
|
147
|
-
- `metric search/get/tree/query
|
|
149
|
+
- `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
150
|
- `metric query --filter` 只接受 `EQ`、`NE`、`LT`、`LE`、`GT`、`GE`、`BT`、`IN`、`IS_NULL`、`NOT_NULL`、`CONTAINS`、`NOT_CONTAINS`、`STARTSWITH`、`NOT_STARTSWITH`、`ENDSWITH`、`NOT_ENDSWITH`,禁止使用 `=`、`>=`、`<=`。例如日期下界写 `--filter "日期 GE 2026-01-01"`。
|
|
149
|
-
-
|
|
151
|
+
- query 的业务列可以是中文,每个中文层级都用 `["字段名"]`:例如 `.data[] | .["组织"]["名称"]`,每一个中文层级都要引用,不能只改顶层。search/get 的 canonical 英文字段与 query 的业务列名要分开理解。文件模式的 `path` 指向行数组,行数组没有 `rowCount`;先按 `resultMode` 分支再消费,示例见 `references/metric-commands.md`。
|
|
152
|
+
- 必须解析的命令不得用 `2>/dev/null` 隐藏 stderr,也不得用 `2>&1` 将错误文本送入 JSON 解码器。不要用会让末端命令成功掩盖上游失败的管道;优先拆成“guancli 输出到文件 → 确认命令成功 → jq 读取文件”,必须使用管道时先启用 `set -o pipefail`。
|
|
150
153
|
- 同类语法错误只允许出现一次;第一次失败后先执行对应命令的 `--help` 或读取本 Skill 的参考文档,再按真实契约纠正,不连续尝试相近写法。
|
|
151
|
-
-
|
|
154
|
+
- 普通 `--filter`、可重复 `--filter-json`、单个 `--filter-file` 三选一,禁止混用。复杂筛选优先使用 `--filter-json`(可重复)或 `--filter-file` 条件树,并先加 `--dry-run -f json`;dry-run 只读取指标详情做查询维度、筛选字段和类型校验,不执行指标取数,也不支持普通文件或 stderr 输出目标。不支持的 `--dim` 返回 `METRIC_UNSUPPORTED_DIMENSION`。条件树节点使用 `combineType: AND|OR`,叶子使用 `field/operator/value|values`;`IN` 至少一个值,`BT` 恰好两个值。当前指标取数接口不能无损表达多分支 OR,真实执行会在取数前返回 `FILTER_OR_EXECUTION_UNSUPPORTED`,不得拆成多次聚合查询后拼接。失败时按稳定错误码修正,不猜错误文本。
|
|
152
155
|
- 搜索并同时查看业务口径、数据集和适用维度等详情时,优先使用 `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`。
|
|
153
156
|
- 业务词不能直接命中指标时,候选发现必须遵守单批预算:一次性生成“原词 + 最多 4 个必要同义词/等价表达”,按 trim、空白归一化和大小写不敏感语义去重,保留原词在首位,然后只执行一次 `metric search --fuzzy`。不得把同义词拆成多次查询,不得通过调换顺序、改写等价词或查询子集重复搜索;如果单批无候选,立即结束本轮候选发现并说明已尝试关键词、搜索范围、无结果原因和 `stop_reason=no_candidate_within_budget`。后端最多接受 10 个模糊关键词,但 Agent 候选发现预算默认最多 5 个;不要缓存或跨请求复用“未找到指标”的结论。完整协议见 `references/metric-commands.md`。
|
|
154
|
-
-
|
|
155
|
-
-
|
|
157
|
+
- 指标结果加工前,先读取成功 query envelope 的实际 `columns` 和行对象 keys,按业务含义选择列;禁止硬编码或猜测指标展示列名(包括高级计算后缀),也不能按列位置取值。使用 `python3 references/examples/metric-query-rows.py <envelope.json> --list-columns` 发现列,再用 `--column "<已确认的实际列名>"` 精确选择;候选缺失或多义时停止并返回实际列集合,不猜近似名称。该参数属于消费 recipe,不是 `guancli metric query` 的参数。
|
|
158
|
+
- 普通指标数据查询用 `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)。
|
|
159
|
+
- 指标查数必须区分**时间范围**和**分组粒度**。用户说“本月/上月/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`。
|
|
160
|
+
- 搜索指标支持两种方式:`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`。
|
|
156
161
|
- 回答指标搜索结果时,必须逐条说明“命中的指标”和“命中方式”:至少包含指标 ID、指标名称、命中条件/字段、命中优先级、命中关键词;不要把用户输入默认解释为指标名称精确匹配。如果结果中有“命中条件”“命中优先级”“命中关键词”列,必须原样纳入结论。
|
|
157
162
|
- 按数据集反查指标用 `guancli metric by-dataset <ds_id>`;如果已知指标主题,可加 `-d <metric_topic_id>` 缩小范围;需要结构化结果时用 `-f json`。
|
|
158
163
|
- 只要传入 `--compare`、`--compare-value`、`--xtd`、`--last`、`--recent`、`--recent-base`、`--percentage`、`--percentage-dim`、`--rank-top`、`--rank-order`、`--rank-dim`、`--adv-calc-json` 任一参数,就进入指标泛化查询模式。泛化查询要求 BI 版本 `>= 8.2.1`;如需确认环境版本,先执行 `guancli server-version --profile <profile>`。
|
|
@@ -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
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Read a successful metric.query envelope; emit its row array for processing."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def query_rows(envelope):
|
|
10
|
+
if not isinstance(envelope, dict) or envelope.get("schemaVersion") != "1.0":
|
|
11
|
+
raise ValueError("expected metric envelope schemaVersion 1.0")
|
|
12
|
+
if envelope.get("command") != "metric.query":
|
|
13
|
+
raise ValueError("expected metric.query, not metadata or a dry-run plan")
|
|
14
|
+
count = envelope.get("rowCount")
|
|
15
|
+
if type(count) is not int or count < 0:
|
|
16
|
+
raise ValueError("invalid rowCount")
|
|
17
|
+
if not isinstance(envelope.get("columns"), list):
|
|
18
|
+
raise ValueError("missing query columns")
|
|
19
|
+
if envelope.get("resultMode") == "inline":
|
|
20
|
+
rows = envelope["data"]
|
|
21
|
+
elif envelope.get("resultMode") == "file":
|
|
22
|
+
path = Path(envelope["path"])
|
|
23
|
+
if not path.is_absolute():
|
|
24
|
+
raise ValueError("expected absolute output path")
|
|
25
|
+
with path.open(encoding="utf-8") as source:
|
|
26
|
+
rows = json.load(source)
|
|
27
|
+
else:
|
|
28
|
+
raise ValueError("unsupported resultMode")
|
|
29
|
+
if not isinstance(rows, list) or len(rows) != count:
|
|
30
|
+
raise ValueError("row payload does not match envelope rowCount")
|
|
31
|
+
if any(not isinstance(row, dict) for row in rows):
|
|
32
|
+
raise ValueError("expected row objects")
|
|
33
|
+
return rows
|
|
34
|
+
|
|
35
|
+
|
|
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)
|
|
78
|
+
print()
|
|
79
|
+
return 0
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if __name__ == "__main__":
|
|
83
|
+
sys.exit(main())
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Usage: bash metric-query.sh METRIC_ID PROFILE
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
guancli metric query "$1" --profile "$2" -f json > query-envelope.json 2> query-error.log
|
|
6
|
+
python3 "$script_dir/metric-query-rows.py" query-envelope.json > query-rows.json
|
|
@@ -0,0 +1,38 @@
|
|
|
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
|
+
```json
|
|
8
|
+
[
|
|
9
|
+
{"id":"sales-2023","metricId":"实际指标ID","dimensions":["大区"],"filters":{"field":"日期","operator":"BT","values":["2023-01-01","2023-12-31"]},"sortDesc":"销售金额","offset":0,"limit":10,"valueFormat":"formatted"},
|
|
10
|
+
{"id":"sales-month","metricId":"实际指标ID","dimensions":["日期 toMonth"],"limit":12}
|
|
11
|
+
]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
每项必填唯一非空 `id` 和真实 `metricId`。时间范围通过 `filters` 表达,省略表示不额外筛选;支持现有结构化条件树和操作符,不支持需要拆分聚合的多分支 OR。基础查询与 `metric query` 一样,使用指标关联的趋势图卡片,缺失时回退指标值卡片;每项创建独立编辑会话。日期粒度筛选、日期子粒度分组和排序沿用 `metric query` 的能力。错误或不支持的条件显式失败,禁止删除条件后重试以伪装成功。
|
|
15
|
+
|
|
16
|
+
- `dimensions`:非空维度名称数组;省略时沿用关联卡片的默认分组,显式提供时覆盖该项独立编辑会话的分组。空数组会被拒绝;支持 `日期 toMonth` 等现有粒度语法。
|
|
17
|
+
- `sortAsc` / `sortDesc`:互斥;解析和执行语义与 `metric query` 一致。日期子粒度排序使用同一限定表达式,例如 `日期 toMonth`。
|
|
18
|
+
- `limit`:默认 50,必须为正数。`offset` 默认 0,非负;`offset + limit` 最多 10000。非零 offset 必须显式排序。后端无 offset,CLI 请求至 offset+limit 后截取,不代表全量遍历;排序相同值和跨请求数据变化可能使跨页不稳定,严格分页需选择能唯一定位顺序的分组。
|
|
19
|
+
- `valueFormat`:支持 `raw`(默认)和 `formatted`。`raw` 保留 JSON 数字、null 和维度值;`formatted` 沿用 `metric query --value-format formatted` 的指标格式规则,把指标列输出为带精度、千分位、百分号或单位的字符串,维度列保持原值。排序和分页始终基于格式化前的原始值。
|
|
20
|
+
- `--dry-run`:读取指标详情后生成每项取数请求计划,不执行指标取数,不代表权限、执行或数据完整性已经通过。
|
|
21
|
+
|
|
22
|
+
完整 guancli 固定并发 10,不限制查询项数量,输入文件至多 1 MiB;超过 10 项的部分排队。batch 不设置整批超时,每个底层接口沿用 `metric query` 的 HTTP 单请求超时。结果逐项写入临时 spool,最终按输入顺序流式输出,内存占用随并发度而不是查询项总数增长;命令取消会传到底层 HTTP 并等待在途 worker 收口。无缓存、无跨批结果复用。每项使用后端生成的独立 UUID 编辑会话,不保存关联卡片;编辑会话生命周期沿用现有 `metric query` 和 BI 后端策略。kit/lite 入口还受宿主实际请求预算约束,超过预算时由 dispatcher 按真实请求数停止。
|
|
23
|
+
|
|
24
|
+
## 稳定 JSON 协议 v1
|
|
25
|
+
|
|
26
|
+
顶层 `schemaVersion: "1.0"`、`command: "metric.batch-query"`、`status`、`results`。全部完成成功为 `success`,存在失败为 `partial_failure`。有效批次输出完整汇总后退出 0,包括含失败项的批次;输入/认证初始化等批次级错误退出非零。
|
|
27
|
+
|
|
28
|
+
每项保留输入 `id`、`metricId`,按输入顺序返回。`status` 为 `success` / `error` / `planned`;成功时 `result` 包含 `resultMode: "inline"`、实际采用的 `valueFormat`、`columns: [{name,role}]`、`rows` 二维数组、`rowCount`、`offset`、`limit`。raw 模式的指标值保持 JSON 数字;formatted 模式的指标值为展示字符串。列名直接来自 BI,角色为 dimension/metric,位置与行值一一对应;不存在以本地化展示字段反推新协议的转换。错误为 `error: {code,message,httpStatus?,businessStatus?}`,已有 HTTP/业务状态直接透传,检查每项错误再分析其余成功结果;后端必需字段缺失、类型或行宽变化报 `METRIC_RESPONSE_INVALID`。
|
|
29
|
+
|
|
30
|
+
原生执行 `timingScope: "native"`,顶层提供 `durationMs`、`concurrencyLimit`、`requestCount`(逻辑 BI 调用数,包含详情、会话和取数,认证重试不计);每项基础查询通常 3 次调用,显式维度或排序时通常 5 次。每项提供 UTC `startedAt`、`finishedAt`、`durationMs`,可据此检查重叠。
|
|
31
|
+
|
|
32
|
+
lite/kit 执行会在 replay 轮汇集独立请求;只读请求可标为 parallel,编辑会话 modify 按现有 mutating 契约串行。实际执行并发/时间由宿主负责,`timingScope: "host"` 时不返回原生计时、请求数和并发字段,不能把 kit 重放耗时当成 BI 耗时。现有原生 lite 宿主最多 8 路,WASI 宿主为单路,WASI 不提供本次并发性能保证;完整 guancli 是本次性能验收入口。宿主的总时限沿用其现有策略。
|
|
33
|
+
|
|
34
|
+
## 服务端与权限边界
|
|
35
|
+
|
|
36
|
+
复用 `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,不能扩大用户资源权限。
|
|
37
|
+
|
|
38
|
+
每项读取指标关联卡片并在独立编辑会话中取数,不拼接多个聚合结果。未显式提供 dimensions 时保留卡片默认分组;提供 dimensions 或 sorting 时只覆盖该项会话中的对应配置,filters 作为本次取数条件传入。指标详情、卡片配置与取数之间不保证快照;改名、发布或权限变化由服务端最终裁决。当前 batch 输入不包含同比、XTD、recent、占比和排名等高级计算;这些仍由单条 `metric query` 的 v2 分支处理,后续若加入 batch 必须沿用相同分流。
|
|
@@ -72,7 +72,7 @@ guancli metric search [keyword] [flags]
|
|
|
72
72
|
| `--fuzzy strings` | 名称、业务口径、自定义业务属性统一模糊搜索关键词,可多次指定,也支持逗号、中文逗号、顿号分隔;和 `[keyword]` 互斥 |
|
|
73
73
|
| `--offset int` | 搜索结果分页偏移量,默认 `0` |
|
|
74
74
|
| `--limit int` | 搜索结果数量,默认 `0` 表示全部 |
|
|
75
|
-
| `--with-detail` | 同时返回每个命中指标的 `metric get`
|
|
75
|
+
| `--with-detail` | 同时返回每个命中指标的 `metric get` 详情;默认文本包含血缘,`--brief` 或 `-f json` 不请求血缘 |
|
|
76
76
|
|
|
77
77
|
`--fuzzy` 语义:
|
|
78
78
|
|
|
@@ -81,8 +81,8 @@ guancli metric search [keyword] [flags]
|
|
|
81
81
|
- 自定义业务属性值统一模糊匹配;后端只匹配启用且可搜索的业务属性。
|
|
82
82
|
- 结果会在原有指标字段基础上增加命中条件、命中优先级和命中关键词。
|
|
83
83
|
- 非 `--raw` 输出会额外查询并返回每个指标关联的查询加速摘要,包括查询加速数量和加速指标 ID/优先级/字段摘要。
|
|
84
|
-
- `--with-detail` 会为当前搜索结果中的每个指标补充与 `metric get <metric_id>` 相同的标准化详情;默认终端输出按指标追加详情,`-f json`
|
|
85
|
-
-
|
|
84
|
+
- `--with-detail` 会为当前搜索结果中的每个指标补充与 `metric get <metric_id>` 相同的标准化详情;默认终端输出按指标追加详情,`-f json` 在 envelope 的 `data[]` 中直接返回 canonical 详情字段,不再嵌套中文 `指标详情`。
|
|
85
|
+
- 默认文本详情包含血缘;批量搜索只需业务口径、数据集、字段、权限、统计、自定义属性和查询加速等信息时,加 `--brief` 跳过血缘。`-f json` 不包含且不请求血缘。结果较多时先用 `--limit` 收窄指标数量。
|
|
86
86
|
- `--with-detail` 只补指标详情,不查询指标数据;指标取数仍使用 `metric query`。
|
|
87
87
|
- `--with-detail` 需要组合多个接口的结果,因此不兼容 `--raw`、`-f csv` 和 `-f excel`。
|
|
88
88
|
- `[keyword]` 走旧指标名称搜索接口;`--fuzzy` 走新的统一模糊搜索接口,二者不能同时使用。
|
|
@@ -130,7 +130,7 @@ guancli metric search --fuzzy <关键词> --profile <profile> --limit 5 --with-d
|
|
|
130
130
|
确实需要机器处理 JSON 时,先保存成功输出再单独执行 jq,避免管道末端成功掩盖 guancli 失败:
|
|
131
131
|
|
|
132
132
|
```bash
|
|
133
|
-
guancli metric search --fuzzy <关键词> --profile <profile> --limit 5 --with-detail --brief
|
|
133
|
+
guancli metric search --fuzzy <关键词> --profile <profile> --limit 5 --with-detail --brief -f json > metric_search.json &&
|
|
134
134
|
jq '.data[] | {id, name, dimensions, timeField}' metric_search.json
|
|
135
135
|
```
|
|
136
136
|
|
|
@@ -166,7 +166,7 @@ guancli metric get <metric_id> --profile <profile> --brief
|
|
|
166
166
|
需要结构化提取时拆成两步:
|
|
167
167
|
|
|
168
168
|
```bash
|
|
169
|
-
guancli metric get <metric_id> --profile <profile> --brief
|
|
169
|
+
guancli metric get <metric_id> --profile <profile> --brief -f json > metric_detail.json &&
|
|
170
170
|
jq '.data.dimensions' metric_detail.json
|
|
171
171
|
```
|
|
172
172
|
|
|
@@ -239,23 +239,57 @@ guancli metric query <metric_id> [flags]
|
|
|
239
239
|
| 参数 | 默认值 | 说明 |
|
|
240
240
|
| --- | --- | --- |
|
|
241
241
|
| `--limit int` | `50` | 数据行数限制 |
|
|
242
|
-
| `--dim strings` | 无 |
|
|
242
|
+
| `--dim strings` | 无 | 维度名称,可多次指定,也支持逗号、中文逗号、顿号分隔;日期子类型写作 `"订单日期 toMonth"` |
|
|
243
243
|
| `--filter stringArray` | 无 | 筛选条件,格式:`"列名 操作符 值"`,可多次指定 |
|
|
244
|
-
| `--filter-json stringArray` | 无 | 结构化筛选 JSON
|
|
244
|
+
| `--filter-json stringArray` | 无 | 结构化筛选 JSON,可重复;与 --filter/--filter-file 互斥;支持嵌套 AND/OR 条件树 |
|
|
245
245
|
| `--filter-file string` | 无 | 从 JSON 文件读取一棵结构化条件树;与 `--filter`、`--filter-json` 互斥 |
|
|
246
246
|
| `--combine-type string` | `AND` | 多条件组合方式:`AND` 或 `OR` |
|
|
247
|
-
| `--dry-run` | `false` | 只返回规范化查询计划、字段类型和稳定错误码,不执行指标取数;必须同时使用
|
|
248
|
-
| `--
|
|
249
|
-
| `--sort-
|
|
250
|
-
| `--sort-desc string` | 无 | 按列降序排序,与 `--sort-asc` 互斥 |
|
|
247
|
+
| `--dry-run` | `false` | 只返回规范化查询计划、字段类型和稳定错误码,不执行指标取数;必须同时使用 `-f json`,且不支持普通文件或 stderr 输出目标 |
|
|
248
|
+
| `--sort-asc string` | 无 | 按列升序排序;日期子类型使用与 `--dim` 相同的粒度表达式;与 `--sort-desc` 互斥 |
|
|
249
|
+
| `--sort-desc string` | 无 | 按列降序排序;日期子类型使用与 `--dim` 相同的粒度表达式;与 `--sort-asc` 互斥 |
|
|
251
250
|
| `--columns strings` | 无 | 只显示指定列,逗号分隔,在 CLI 端执行 |
|
|
252
251
|
| `--precision int` | `6` | 没有有效指标格式时的数值最大小数位数;传 `-1` 保留原始精度 |
|
|
253
252
|
| `--value-format string` | `formatted` | `formatted` 按指标格式输出;`raw` 保留原始数值 |
|
|
254
253
|
| `-o, --output string` | 无 | 将查询结果写入文件;未指定且结果超过 1000 行时自动写入文件 |
|
|
255
254
|
|
|
256
|
-
`metric search/get/tree/query
|
|
255
|
+
`metric search/get/tree/query -f json` 都返回带版本号的稳定 JSON envelope,当前 canonical 契约版本为 `1.0`,公共字段为 `schemaVersion`、`command`、`resultMode`、`rowCount`。内联结果在 `data`,文件结果在绝对 `path`;query 还返回 `columns`。版本演进读取响应体中的 `schemaVersion`,不会增加 `json-v2` 一类输出格式。旧对象/数组入口已移除,这是输出契约迁移,旧脚本必须同步适配,详见 [迁移清单](metric-json-migration.md)。未指定 `-o/--output` 且查询结果超过 1000 行时,默认模式仍自动写 CSV 并输出原中文提示;使用 `-f json` 时写 JSON 文件,stdout 返回 `resultMode=file` envelope。自动文件名带唯一后缀,避免同秒并发或重试覆盖已有结果。
|
|
257
256
|
|
|
258
|
-
search/get 的 `data` 使用直接由后端字段构造的 canonical 模型:`id/name/status/type/description/projectId/directoryId/dataset/dimensions/timeField/measureFields/match/accelerations/statistics/permissions/customAttributes/updatedAt`。`status/type` 保留 `PUBLISHED/ATOMIC` 等机器枚举,不使用“在线/原子指标”等中文展示标签;`match.priority` 保留后端 `name=1/desc=2/bizAttr=3`,精确/模糊由 `match.mode` 单独表达。未知后端字段被忽略,`id/name` 缺失时明确返回契约错误。可选标量和对象的缺失或 `null` 统一省略;`dimensions/timeField/measureFields/customAttributes` 及 `accelerations[].priority` 区分缺失、`null`、空值或零值,`accelerations` 区分未查询与已知空数组,调用方不要把省略解释成已知为空。tree 的节点固定使用 `id/name/type/children`,`--brief`
|
|
257
|
+
search/get 的 `data` 使用直接由后端字段构造的 canonical 模型:`id/name/status/type/description/projectId/directoryId/dataset/dimensions/timeField/measureFields/match/accelerations/statistics/permissions/customAttributes/updatedAt`。`status/type` 保留 `PUBLISHED/ATOMIC` 等机器枚举,不使用“在线/原子指标”等中文展示标签;`match.priority` 保留后端 `name=1/desc=2/bizAttr=3`,精确/模糊由 `match.mode` 单独表达。未知后端字段被忽略,`id/name` 缺失时明确返回契约错误。可选标量和对象的缺失或 `null` 统一省略;`dimensions/timeField/measureFields/customAttributes` 及 `accelerations[].priority` 区分缺失、`null`、空值或零值,`accelerations` 区分未查询与已知空数组,调用方不要把省略解释成已知为空。tree 的节点固定使用 `id/name/type/children`,`--brief` 只省略计数和权限,不省略节点身份。中文展示字段只属于默认输出,不属于 envelope 契约。canonical 模型不包含血缘,因此 `--with-detail -f json` 不请求血缘;文本详情可查看血缘。query dry-run 不查询加速配置,此时省略 `metric.accelerations`,不能把省略解释成无加速配置。
|
|
258
|
+
|
|
259
|
+
query dry-run 的 `dimensions` 保留用户输入的字符串数组,并额外返回 `resolvedDimensions`。后者是 CLI 最终发送给查询接口的维度对象,可用于确认日期子类型是否解析到了预期的 `fdId`、`fdType=SUB_DATE`、`parentFdName` 和 `granularity`。
|
|
260
|
+
|
|
261
|
+
### 日期子类型维度
|
|
262
|
+
|
|
263
|
+
日期维度可在字段名后增加粒度修饰符:
|
|
264
|
+
|
|
265
|
+
| 用户意图 | 修饰符 | 粒度 |
|
|
266
|
+
| --- | --- | --- |
|
|
267
|
+
| 按年 | `toYear` | `YEAR` |
|
|
268
|
+
| 按季度 | `toQuarter` | `QUARTER` |
|
|
269
|
+
| 按月 | `toMonth` | `MONTH` |
|
|
270
|
+
| 按周 | `toWeek` | `WEEK` |
|
|
271
|
+
| 按星期 | `toDayOfWeek` | `DAYOFWEEK` |
|
|
272
|
+
| 按日 | `toDate` / `toDay` | `DAY` |
|
|
273
|
+
| 按小时 | `toHour` | `HOUR` |
|
|
274
|
+
| 按分钟 | `toMinute` | `MINUTE` |
|
|
275
|
+
| 按秒 | `toSecond` | `SECOND` |
|
|
276
|
+
|
|
277
|
+
CLI 以指标详情返回的日期子字段为准;目标粒度不存在时返回 `METRIC_UNSUPPORTED_DATE_GRANULARITY`,不会伪造字段 ID。DATE 字段的 DAY 使用基础日期字段,TIMESTAMP 的 DAY 使用日期子字段。完整字段名精确匹配优先,因此不会破坏名称本身以 `toMonth` 等文本结尾的历史维度。
|
|
278
|
+
|
|
279
|
+
Agent 生成命令时必须区分时间范围与分组粒度:
|
|
280
|
+
|
|
281
|
+
- “本月/上月/某个月销售额”只表示筛选范围,不自动增加月维度。
|
|
282
|
+
- “按月/每月/月度趋势/逐月销售额”表示分组粒度,使用 `--dim "<时间维度> toMonth"`。
|
|
283
|
+
- “近 12 个月每月销售额”同时使用月维度和时间范围筛选。
|
|
284
|
+
- 时间字段名从指标详情的 `timeField.name` 获取,不要默认写成“日期”。
|
|
285
|
+
|
|
286
|
+
示例:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
guancli metric query <metric_id> --profile default --dim "订单日期 toMonth"
|
|
290
|
+
guancli metric query <metric_id> --profile default --dim "订单日期 toMonth" --sort-asc "订单日期 toMonth"
|
|
291
|
+
guancli metric query <metric_id> --profile default --dim "订单日期 toMonth" --dry-run -f json
|
|
292
|
+
```
|
|
259
293
|
|
|
260
294
|
筛选操作符:
|
|
261
295
|
|
|
@@ -275,10 +309,11 @@ search/get 的 `data` 使用直接由后端字段构造的 canonical 模型:`i
|
|
|
275
309
|
guancli metric query <metric_id> --profile default
|
|
276
310
|
guancli metric query <metric_id> --profile default --dim 省份 --limit 10
|
|
277
311
|
guancli metric query <metric_id> --profile default --dim "省份、城市" --limit 20
|
|
312
|
+
guancli metric query <metric_id> --profile default --dim "订单日期 toMonth" --sort-asc "订单日期 toMonth"
|
|
278
313
|
guancli metric query <metric_id> --profile default --dim 省份 --filter "省份 EQ 河南省"
|
|
279
|
-
guancli metric query <metric_id> --profile default --dim 省份 --filter "省份 EQ 河南省" --filter "省份 EQ 青海省" --combine-type OR --dry-run
|
|
280
|
-
guancli metric query <metric_id> --profile default --filter-json '{"field":"省份","operator":"IN","values":["河南省","青海省"]}' --dry-run
|
|
281
|
-
guancli metric query <metric_id> --profile default --filter-file filters.json --dry-run
|
|
314
|
+
guancli metric query <metric_id> --profile default --dim 省份 --filter "省份 EQ 河南省" --filter "省份 EQ 青海省" --combine-type OR --dry-run -f json
|
|
315
|
+
guancli metric query <metric_id> --profile default --filter-json '{"field":"省份","operator":"IN","values":["河南省","青海省"]}' --dry-run -f json
|
|
316
|
+
guancli metric query <metric_id> --profile default --filter-file filters.json --dry-run -f json
|
|
282
317
|
guancli metric query <metric_id> --profile default --dim 省份 --sort-desc 订购数量
|
|
283
318
|
guancli metric query <metric_id> --profile default --dim 省份 --columns "省份,订购数量"
|
|
284
319
|
guancli metric query <metric_id> --profile default --dim 省份 -f csv
|
|
@@ -472,3 +507,47 @@ guancli metric_attribution query <metric_tree_id> --profile test43 --target dim
|
|
|
472
507
|
guancli metric_attribution query <metric_tree_id> --profile test43 --target scan -f csv
|
|
473
508
|
guancli metric_attribution query <metric_tree_id> --profile test43 --target dim --dim 业务员 --raw
|
|
474
509
|
```
|
|
510
|
+
|
|
511
|
+
### 查询结果消费
|
|
512
|
+
|
|
513
|
+
机器查询统一用 `-f json`。`query` 的 `data` 和文件载荷都是行对象数组;search 的 `data` 是指标数组,get/tree 的 `data` 是单个对象。`rowCount` 属于 stdout envelope,不能从行数组读取。query 的 `columns` 保留真实业务列名,可以是中文;search/get 的 `id/name/dimensions` 是 canonical 英文字段。
|
|
514
|
+
|
|
515
|
+
下面示例在 Skill 目录执行;先确认 CLI 成功,再解析 stdout,stderr 单独保存:
|
|
516
|
+
|
|
517
|
+
```bash
|
|
518
|
+
# 成功后 query-rows.json 统一为行数组,不论原结果是 inline 还是 file。
|
|
519
|
+
bash references/examples/metric-query.sh <metric_id> <profile> &&
|
|
520
|
+
jq '.[] | .["组织"]["名称"]' query-rows.json
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
`examples/metric-query-rows.py` 检查 schemaVersion、command、resultMode 和行数;file 模式只从 envelope 的绝对 `path` 读取,不无条件遍历 `data`。上例中文嵌套字段仅演示引用语法,实际字段以 `columns`/数据为准。每一个中文层级都使用 `["字段名"]`。
|
|
524
|
+
|
|
525
|
+
#### 先发现列,再选择
|
|
526
|
+
|
|
527
|
+
禁止在加工脚本中硬编码指标展示列名,或根据指标名称、高级计算后缀、列位置猜列。先检查 `columns` 和行对象 keys,并按当前业务意图确认候选;存在多个候选时不能自动选第一个。下面参数属于 Python recipe,不是 query 命令的新参数:
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
# 复用已成功查询的 envelope,不为发现列重复请求 BI。
|
|
531
|
+
python3 references/examples/metric-query-rows.py query-envelope.json --list-columns
|
|
532
|
+
# 阅读实际列集合并确认业务含义后,替换占位符;不要原样执行。
|
|
533
|
+
python3 references/examples/metric-query-rows.py query-envelope.json --column "<已确认的实际列名>"
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
`--column` 可重复传入经过业务确认的备选名称;与实际列精确匹配后必须恰好剩一列。零匹配、多匹配、重复列名或某行缺少该列都会非零退出,stderr 返回实际列集合,stdout 不输出部分结果;不做近似匹配、不触发 KeyError、不把缺失当 null。真正的 null 保留为 null。选择成功仍输出行对象数组;不传新增参数时保持原有整行输出。空结果可发现声明列,但不能据此宣称存在业务数据。
|
|
537
|
+
|
|
538
|
+
### 日期与 IN 使用同一种筛选输入
|
|
539
|
+
|
|
540
|
+
先通过 get 确认日期、城市存在且类型相符。完整条件树见 `examples/metric-date-in.json`:
|
|
541
|
+
|
|
542
|
+
```bash
|
|
543
|
+
guancli metric query <metric_id> --profile <profile> --filter-file references/examples/metric-date-in.json --dry-run -f json
|
|
544
|
+
# 或把两个条件都放入可重复的 filter-json,不要再混入普通 --filter:
|
|
545
|
+
guancli metric query <metric_id> --profile <profile> \
|
|
546
|
+
--filter-json '{"field":"日期","operator":"BT","values":["2026-01-01","2026-01-31"]}' \
|
|
547
|
+
--filter-json '{"field":"城市","operator":"IN","values":["杭州","上海"]}' --dry-run -f json
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
普通 `--filter`、可重复 `--filter-json`、单个 `--filter-file` 三选一。dry-run 成功只表示计划校验通过,实际执行仍由 BI 决定。
|
|
551
|
+
# 同轮独立查询
|
|
552
|
+
|
|
553
|
+
多项已确定、彼此独立且参数能被 batch 完整表达的基础指标查询,使用 `metric batch-query --input queries.json`,禁止 Shell 循环逐条取数。同比、XTD、recent、占比、排名等高级计算继续使用单条 `metric query`;同轮其余基础查询仍单独组成 batch。详见 [批量协议与示例](metric-batch-query.md)。依赖结果的后续查询在下一轮提交。
|
|
@@ -117,7 +117,7 @@ guancli server-version --profile <profile>
|
|
|
117
117
|
|
|
118
118
|
```bash
|
|
119
119
|
guancli metric query <metric_id> --profile default --dim 日期 --compare yoy --limit 10
|
|
120
|
-
guancli metric query <metric_id> --profile default --dim 日期 --compare mom --limit 10
|
|
120
|
+
guancli metric query <metric_id> --profile default --dim "日期 toMonth" --compare mom --limit 10
|
|
121
121
|
guancli metric query <metric_id> --profile default --dim 日期 --compare yoy --compare-value rate --limit 10
|
|
122
122
|
guancli metric query <metric_id> --profile default --dim 省份 --compare yoy --filter "省份 EQ 河南省" --limit 10
|
|
123
123
|
```
|
|
@@ -194,6 +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
|
+
|
|
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 英文元数据字段不能替代中文业务列的安全引用规则。示例只演示嵌套引用语法,使用前须在实际数据中确认字段。
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# 指标 JSON 入口迁移(GALAXY-39561)
|
|
2
|
+
|
|
3
|
+
本次明确将 search/get/tree/query 的 `-f json` 改为已有 schemaVersion 1.0 envelope;旧数组/展示对象与它不兼容。原 `--json-envelope` 参数已移除,调用方统一使用 `-f json`。`--raw`(包括历史 `--raw -f json`)继续返回后端原始协议,不是 envelope。
|
|
4
|
+
|
|
5
|
+
| 消费者 | 清点与迁移 |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| guancli SKILL、metric-commands、metric-generic-query、help、设计示例 | 统一 -f json,data/path 分支消费;中文业务列逐层括号引用;可执行本地示例覆盖失败、文件和筛选 |
|
|
8
|
+
| guanmetric 指标树、原子/复合/衍生编辑参考 | 需要完整编辑详情的调用迁移到 --raw 后端 response;仅名称/ID 发现直接消费 envelope.data;formula/format 属于 --raw 后端字段 |
|
|
9
|
+
| guancli-kit / guancli-lite | kit 共用 cmdcore,lite 透传 kit 输出;kit 行为测试覆盖 envelope,文本输出保留血缘预算/探测测试 |
|
|
10
|
+
| Decidex guandata-live/metric-topic | 使用 --raw,协议保持原行为 |
|
|
11
|
+
| Decidex guancli-command-insight | 本次不修改,由用户另行适配:旧行数组行数提取需要同时接受 query envelope 的 inline/file,并保留历史输出读取;CLI 本地验证不代表 Decidex 已完成接入 |
|
|
12
|
+
| guancli project/by-dataset/accelerate、其他资源命令 | 不改变格式 |
|
|
13
|
+
|
|
14
|
+
不提供旧 JSON 兼容入口:`--json-envelope` 和 `--legacy-json` 均不支持。历史脚本重新执行时按新版帮助迁移参数及 data/path 消费逻辑。guanmetric 编辑消费者使用 --raw 读取完整后端详情。
|
|
15
|
+
|
|
16
|
+
## Domain and Contract
|
|
17
|
+
|
|
18
|
+
复用现有独立 canonical adapter 和 1.0 envelope,不新增后端接口/业务裁决/多接口合并。可选字段缺失/null 的原语义不变,稳定必填 id/name 缺失仍报错。query columns 保留业务列;file 载荷是行数组,stdout 才是 envelope。默认文本、CSV/Excel、原始协议、非指标命令和错误退出语义保持原行为。测试覆盖 CLI/kit 输出、移除参数的拒绝行为、空集合、缺失/null、文件与中文列,以及脚本退出码传播。
|
|
@@ -129,8 +129,9 @@ guancli card preview <cd_id> --with-default-filters --dynamic-param "结束日
|
|
|
129
129
|
|
|
130
130
|
- 卡片元信息只关联一个页面时自动使用该页面;关联多个页面时必须用 `--page-id` 明确上下文。
|
|
131
131
|
- 显式 `--filter` 或 `--dynamic-param` 会覆盖相同 `fdId` 或 `dpId` 的页面默认值,其他默认条件仍然保留。
|
|
132
|
-
-
|
|
133
|
-
-
|
|
132
|
+
- 支持普通固定值、多选、日期范围、后端已经解析出实际区间的时间宏,以及动态参数选择器。
|
|
133
|
+
- `FIRST_PICK`(取首个候选值)和日历 `MAX`(取最新日期)在页面详情里没有具体值,CLI 会与 BI 前端打开页面时一样调用 `POST /api/page/first-pick` 运行态求值;选择器级联时按上游→下游分层求值,同一层的选择器合并为一个请求(请求次数等于级联深度,无级联时 1 次),并把上游默认值作为候选值筛选条件传入;单次命令最多运行态求值 20 个选择器,循环级联直接报错。stderr 提示行的 `runtimeResolved=` 列出经运行态求值的选择器。\n- 每次 `card preview` 的表格页脚(写文件时为“已写入”后的一行)都有 `筛选:`,列出本次真正生效的条件及来源:`[--filter]`/`[--dynamic-param]` 为显式指定,`[页面默认·<选择器名>]` 为页面筛选器默认值,带 `·运行态求值` 表示 FIRST_PICK/MAX 求值结果;没有任何条件时写明是否应用了页面默认值(选择器等不支持该参数的卡片只显示“无”)。`-f json/csv/excel` 的 stdout 只含数据,条件说明只在 stderr。
|
|
134
|
+
- 树、组合、聚合/结果级映射、必填但无默认值,以及无法从页面元信息确定实际值或目标映射的默认条件均 fail closed:CLI 在查询卡片数据前明确报错,不会静默忽略后继续执行。`autoLink` 会先按同名字段推断目标字段,推断不到时才 fail closed。
|
|
134
135
|
- 多个选择器写入同一字段或动态参数、时间宏目标形态不明确、动态参数默认值包含逗号等可能产生歧义的情况同样会停止查询。
|
|
135
136
|
- 该参数仅适用于 CHART 图表卡片;复杂报表 Pro、选择器和其他卡片类型暂不支持。
|
|
136
137
|
|