@guandata/guancli 1.0.54 → 1.0.56

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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## @guandata/guancli 1.0.56 - 2026-09-03
4
+
5
+ - 指标查询默认按指标或查询列的格式配置展示数值,支持数值、货币、百分比、小数位、千分位、数量级和前后缀等格式。
6
+ - 新增 `--value-format raw`,可在表格、JSON、CSV 和 Excel 等标准输出中保留原始数值,不与直接返回后端响应的 `--raw` 混用。
7
+ - 登录和加载 Profile 时会校验 `base_url`,提前拦截 Windows 引号转义等问题造成的无效地址并给出明确错误。
8
+
9
+ ## @guandata/guancli 1.0.55 - 2026-09-01
10
+
11
+ - 新增 `analyze normalize/align/calculate/topn` 本地分析命令,支持 CSV/JSON 规范化、结果集对齐、安全四则运算、分组 TopN 与占比,并统一输出 `analysis/v1` 结构。
12
+ - 指标查询新增 `--json-envelope` 稳定机器契约,以及 `--filter-json`、`--filter-file` 和 dry-run 筛选校验,复杂条件的字段、类型与错误码更明确。
13
+ - 指标搜索候选发现采用单批关键词预算,避免同义词反复搜索造成额外请求和不稳定结果。
14
+ - 强化本地分析输出的精度、空值、重复键、除零与原子写入保护,失败时保留原输出文件并给出可定位错误。
15
+
3
16
  ## @guandata/guancli 1.0.54 - 2026-08-26
4
17
 
5
18
  - `app publish` 新增 `--skip-build`,可直接发布可信、已验证的 `dist`,避免服务端重复执行项目构建脚本。
package/README.md CHANGED
@@ -43,6 +43,18 @@ guancli chatbi query --theme-name "经营主题" --message "最近30天营业收
43
43
 
44
44
  ## 版本更新
45
45
 
46
+ ### @guandata/guancli 1.0.56
47
+
48
+ - 指标查询默认遵循指标或查询列的数值格式,覆盖货币、百分比、精度、千分位、数量级和前后缀。
49
+ - 新增 `--value-format raw`,可在标准表格、JSON、CSV 和 Excel 输出中保留原始数值。
50
+ - 登录和 Profile 加载会提前校验 BI 地址,减少 Windows 引号转义等配置问题造成的连接失败。
51
+
52
+ ### @guandata/guancli 1.0.55
53
+
54
+ - 新增本地 CSV/JSON 规范化、对齐、安全计算和分组 TopN 分析命令。
55
+ - 指标查询提供稳定 JSON envelope、结构化筛选文件和 dry-run 校验,复杂筛选更易自动化处理。
56
+ - 限制指标候选发现的搜索轮次,并强化精度、空值、重复键和输出文件保护。
57
+
46
58
  ### @guandata/guancli 1.0.54
47
59
 
48
60
  - SuperApp 发布支持复用可信、已验证的 `dist`,避免服务端因缺少项目本地构建工具而发布失败。
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.54",
3
+ "version": "1.0.56",
4
4
  "description": "观远 BI 命令行工具 - 通过 API 操作 ETL、数据集、页面、表单等资源,并提供 ChatBI 问数/洞察能力",
5
5
  "bin": {
6
6
  "guancli": "bin/run.js"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: guancli
3
- description: 当用户要分析观远 BI / Guandata 的 ETL、数据集、页面/仪表板、卡片、血缘、节点 SQL、资源树、目录、表单填报数据、指标 metric 查询、指标树归因 metric_attribution、指标泛化查询参数,或给出 ETL ID、dsId、page ID、card ID、metric ID、metric tree ID 想看现有内容/查询数据,或要为已有仪表板/智能洞察卡片生成智能洞察结果时,主动使用这个 skill。用户提到“创建超级应用”“创建 SuperApp”“新建 SuperApp 项目”“SuperApp 模板项目”“发布 SuperApp”“下载 SuperApp 整包”时,也要使用这个 skill,并引导使用 `guancli app create` / `guancli app publish` / `guancli app download`。用户要删除、重命名、移动页面时,本 skill 只负责把用户路由到 guanvis(`guanvis page delete/rename/move`),这些命令不在 guancli;被删页面没有任何命令行恢复入口,只能人工登录 BI 网页端还原。即使用户只说"看一下这个 page""贴一下这个 ETL 的 SQL""搜个叫 X 的数据集""这个数据集长啥样""页面卡片用了哪些 ds""帮我查这个指标""生成指标泛化查询命令""帮我创建一个超级应用""把这个页面挪到 XX 目录""删掉这个页面""刚删的页面能找回来吗",也要触发。它直接调用 BI HTTP API 拉数据并整理成 AI 友好的中文结论,定位是 BI 查询分析 + 表单填报 CRUD + 指标查询分析 + SuperApp 模板项目创建、发布与整包下载。创建/编辑/删除指标、指标主题、指标目录或公共维度走 guanmetric;修改 ETL 走 guanetl;页面**内容**(卡片、布局、筛选器)的新建与修改、以及页面**本身**的删除/改名/移动都走 guanvis;数据源/数据集 CRUD/增量/调度走 guands;页面 PNG 视觉验证走 guanvis screenshot。若用户希望直接分析 BI 项目而不是手工点页面,或希望直接通过 ChatBI 进行主题问数/洞察分析,也应优先使用这个 skill。
3
+ description: 当用户要分析观远 BI / Guandata 的 ETL、数据集、页面/仪表板、卡片、血缘、节点 SQL、资源树、目录、表单填报数据、指标 metric 查询、指标树归因 metric_attribution、指标泛化查询参数,或要对本地 CSV/JSON 做通用规范化、字段对齐、安全基础计算、分组 TopN/占比时,主动使用这个 skill。用户给出 ETL ID、dsId、page ID、card ID、metric ID、metric tree ID 想看现有内容/查询数据,或要为已有仪表板/智能洞察卡片生成智能洞察结果时也触发。用户提到“创建超级应用”“创建 SuperApp”“新建 SuperApp 项目”“SuperApp 模板项目”“发布 SuperApp”“下载 SuperApp 整包”时,也要使用这个 skill,并引导使用 `guancli app create` / `guancli app publish` / `guancli app download`。用户要删除、重命名、移动页面时,本 skill 只负责把用户路由到 guanvis(`guanvis page delete/rename/move`),这些命令不在 guancli;被删页面没有任何命令行恢复入口,只能人工登录 BI 网页端还原。创建/编辑/删除指标、指标主题、指标目录或公共维度走 guanmetric;修改 ETL 走 guanetl;页面**内容**(卡片、布局、筛选器)的新建与修改、以及页面**本身**的删除/改名/移动都走 guanvis;数据源/数据集 CRUD/增量/调度走 guands;页面 PNG 视觉验证走 guanvis screenshot。
4
4
  compatibility: Requires Node.js 14+. Install via npm install -g --foreground-scripts @guandata/guancli so the AI skill refresh result is visible.
5
5
  ---
6
6
 
@@ -21,6 +21,7 @@ guancli 是 BI 资源的查询分析入口,并支持 Form 表单填报 CRUD、
21
21
  - 用户要创建、发布或更新超级应用 / SuperApp,或要把平台上的 SuperApp 整包下载成本地 zip。
22
22
  - 用户要删除、重命名、移动页面(本 skill 只负责把用户路由到 `guanvis page`,命令不在 guancli)。
23
23
  - 用户要为已有仪表板或智能洞察卡片生成智能洞察结果。
24
+ - 用户已经取得本地 CSV/JSON,需要稳定处理 BOM/null/嵌套字段、对齐两个结果集、执行安全四则运算,或做通用分组 TopN/占比;不再临时生成 Python 拼接脚本。
24
25
 
25
26
  如果用户只想生成页面 PNG 截图成品,不要用本 skill,改用 `guanvis screenshot`。
26
27
 
@@ -65,6 +66,7 @@ guancli 是 BI 资源的**查询分析入口**,并支持 Form 表单填报 CRU
65
66
  | Form CRUD、子表、ChatBI 主题问数/洞察 | `references/form-chatbi.md` |
66
67
  | 指标与指标树全量命令 | `references/metric-commands.md` |
67
68
  | 指标泛化查询参数与示例 | `references/metric-generic-query.md` |
69
+ | 本地 CSV/JSON 规范化、对齐、基础计算、TopN | `references/analysis-primitives.md` |
68
70
 
69
71
  ## 常用查询入口
70
72
 
@@ -142,13 +144,15 @@ guancli 在这条链路上只出只读的那一环:`guancli page search` / `pa
142
144
  ## 指标关键规则
143
145
 
144
146
  - **先按下面的命令契约生成,不要猜 shell、jq 或筛选语法**:
145
- - jq 访问中文 JSON key 必须写成 `.["字段名"]`,嵌套字段逐级写成 `.["指标详情"]["适用维度"]`;禁止 `.字段名`。
147
+ - `metric search/get/tree/query --json-envelope` 返回统一 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` 区分未查询与已知空数组,调用方不要把省略解释成已知为空。原 `-f json` 保持旧版对象/数组结构,供已有调用方兼容;envelope 版本由响应体中的 `schemaVersion` 演进,不新增 `json-v2` 一类输出格式。该参数不能与 `--raw`、非 JSON `-f` 或 stderr 输出目标同时使用。
146
148
  - `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"`。
147
149
  - 必须解析的命令不得用 `2>/dev/null` 隐藏 stderr。不要用会让末端命令成功掩盖上游失败的管道;优先拆成“guancli 输出到文件 → 确认命令成功 → jq 读取文件”,必须使用管道时先启用 `set -o pipefail`。
148
150
  - 同类语法错误只允许出现一次;第一次失败后先执行对应命令的 `--help` 或读取本 Skill 的参考文档,再按真实契约纠正,不连续尝试相近写法。
151
+ - 复杂筛选优先使用 `--filter-json`(可重复)或 `--filter-file` 条件树,并先加 `--dry-run --json-envelope`;dry-run 只读取指标详情做查询维度、筛选字段和类型校验,不执行指标取数,也不支持普通文件或 stderr 输出目标。不支持的 `--dim` 返回 `METRIC_UNSUPPORTED_DIMENSION`。条件树节点使用 `combineType: AND|OR`,叶子使用 `field/operator/value|values`;`IN` 至少一个值,`BT` 恰好两个值。当前指标取数接口不能无损表达多分支 OR,真实执行会在取数前返回 `FILTER_OR_EXECUTION_UNSUPPORTED`,不得拆成多次聚合查询后拼接。失败时按稳定错误码修正,不猜错误文本。
149
152
  - 搜索并同时查看业务口径、数据集和适用维度等详情时,优先使用 `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`。
150
- - 普通指标数据查询用 `guancli metric query <metric_id>`,可加 `--dim`、`--filter`、排序、列筛选、输出格式等;未指定 `-o/--output` 且结果超过 1000 行时会自动写入 `metric_<metricId>_<timestamp>.<ext>`。回答指标数据查询结果时,必须检查输出中的 `查询加速` summary 或 `_queryAccelerate` 列:命中时明确说明“本次查询命中查询加速”,并列出源指标 ID、加速指标 ID 和页面查询顺序;未命中时说明“未命中查询加速”;如果显示 `未知: 后端未返回`,说明当前后端未返回命中 metadata,不能推断是否命中。注意:输出中的 `优先级N` 来自后端 `acceleratePriority` 排序权重,数字越大越先尝试;不要把它直接解释成页面“查询顺序”。需要和页面对齐时,额外执行 `guancli metric accelerate list <metric_id>`,按 `acceleratePriority` 倒序排列后换算页面查询顺序(倒序第 1 个即页面查询顺序 1)。
151
- - 搜索指标支持两种方式:`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`。
153
+ - 业务词不能直接命中指标时,候选发现必须遵守单批预算:一次性生成“原词 + 最多 4 个必要同义词/等价表达”,按 trim、空白归一化和大小写不敏感语义去重,保留原词在首位,然后只执行一次 `metric search --fuzzy`。不得把同义词拆成多次查询,不得通过调换顺序、改写等价词或查询子集重复搜索;如果单批无候选,立即结束本轮候选发现并说明已尝试关键词、搜索范围、无结果原因和 `stop_reason=no_candidate_within_budget`。后端最多接受 10 个模糊关键词,但 Agent 候选发现预算默认最多 5 个;不要缓存或跨请求复用“未找到指标”的结论。完整协议见 `references/metric-commands.md`。
154
+ - 普通指标数据查询用 `guancli metric query <metric_id>`,可加 `--dim`、筛选、排序、列筛选、输出格式等。数值默认按指标配置的 `format` 输出(查询响应有更具体的列级格式时优先),没有有效格式时才按 `--precision` 回退;需要标准表格/JSON/CSV/Excel 中保留原始数值时传 `--value-format raw`,不要和直接返回后端响应的全局 `--raw` 混淆。使用 `--json-envelope` 时,未指定 `-o/--output` 且结果超过 1000 行会自动写入 `metric_<metricId>_<timestamp>_<unique>.json`,stdout 返回 `resultMode=file` 和绝对 `path`,不得再从中文提示猜文件名。唯一后缀用于避免同秒并发或重试覆盖已有结果。未启用该参数的默认和 `-f json` 输出保持兼容。回答指标数据查询结果时,必须检查输出中的 `查询加速` summary 或 `_queryAccelerate` 列:命中时明确说明“本次查询命中查询加速”,并列出源指标 ID、加速指标 ID 和页面查询顺序;未命中时说明“未命中查询加速”;如果显示 `未知: 后端未返回`,说明当前后端未返回命中 metadata,不能推断是否命中。注意:输出中的 `优先级N` 来自后端 `acceleratePriority` 排序权重,数字越大越先尝试;不要把它直接解释成页面“查询顺序”。需要和页面对齐时,额外执行 `guancli metric accelerate list <metric_id>`,按 `acceleratePriority` 倒序排列后换算页面查询顺序(倒序第 1 个即页面查询顺序 1)。
155
+ - 搜索指标支持两种方式:`guancli metric search <keyword>` 按指标名称模糊搜索;`guancli metric search --fuzzy <keyword>` 同时按指标名称、业务口径、自定义业务属性值做 OR 模糊搜索,可多次传参,命中优先级为 name=1、desc=2、bizAttr=3。`[keyword]` 和 `--fuzzy` 互斥。需要同时查看每个命中指标的 `metric get` 详情时加 `--with-detail`;旧格式默认包含血缘,加 `--brief` 可跳过血缘。`--json-envelope` 不包含且不请求血缘,需要血缘时使用旧 `-f json`。此模式不兼容 `--raw`、CSV 和 Excel 输出,结果很多时先用 search 的 `--limit` 收窄指标数量。指标取数仍单独使用 `metric query`。
152
156
  - 回答指标搜索结果时,必须逐条说明“命中的指标”和“命中方式”:至少包含指标 ID、指标名称、命中条件/字段、命中优先级、命中关键词;不要把用户输入默认解释为指标名称精确匹配。如果结果中有“命中条件”“命中优先级”“命中关键词”列,必须原样纳入结论。
153
157
  - 按数据集反查指标用 `guancli metric by-dataset <ds_id>`;如果已知指标主题,可加 `-d <metric_topic_id>` 缩小范围;需要结构化结果时用 `-f json`。
154
158
  - 只要传入 `--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>`。
@@ -197,6 +201,18 @@ GUANCLI_DOWNLOAD_TIMEOUT=1200 guancli app download <appId> # 大包/慢网络
197
201
  - 已知 caveat:`settings.json` 在远端是独立对象,如果经 app settings 接口改过,zip 里的那份可能仍是旧版本。
198
202
  - `-f` 只支持 `auto`(默认)和 `json`。
199
203
 
204
+ ## 请求转发路由
205
+
206
+ 请求转发能力通过 `gateway invoke` 调用 BI 网关,CLI 不会直接访问配置中的目标服务地址。当前 PAT 仅开放已配置路由的转发调用,路由管理和调试接口未开放,因此不提供 `route`、`debug` 等管理类子命令;路由需预先在 BI 中配置:
207
+
208
+ ```bash
209
+ guancli gateway invoke orders --method GET --path 2026/detail --query tenant=cn
210
+ ```
211
+
212
+ `invoke` 支持重复 `--query key=value`、`--header key=value`,以及互斥的 `--body` / `--body-file`。默认直接输出解析后的响应 JSON body;排查请求时增加 `--verbose`,可额外查看 `statusCode` 和脱敏后的 `headers`。`--raw` 只输出原始响应体。
213
+
214
+ 为避免覆盖 CLI 到 BI 的认证上下文,`Cookie`、`Authorization`、`token`、`X-Auth-Token`、`X-Personal-Token`、`x-dom-id` 和 `user-id` 等保留 Header 不能通过 `--header` 传入;目标服务鉴权应配置在路由模板或 Secret 中。
215
+
200
216
  ## 仪表板、卡片智能洞察
201
217
 
202
218
  ```bash
@@ -46,6 +46,35 @@
46
46
  "若使用管道,先启用 set -o pipefail",
47
47
  "不会因 jq 或管道末端成功而宣称上游 guancli 成功"
48
48
  ]
49
+ },
50
+ {
51
+ "id": 5,
52
+ "prompt": "帮我找‘复购成交贡献’相关指标。附件给出了本轮可重复的指标搜索返回,请展示你会执行的候选发现命令和最终答复。",
53
+ "expected_output": "代理应一次性生成原词和少量必要同义词,去重后放进同一次 metric search --fuzzy;消费附件中的确定性空结果后,报告尝试关键词、搜索范围、无结果原因和固定 stop_reason,并结束本轮发现。",
54
+ "files": [
55
+ "fixtures/metric-candidate-empty-search.json"
56
+ ],
57
+ "expectations": [
58
+ "原词保留在首位,原词加扩展词总数不超过 5 个",
59
+ "输出的调用序列中恰好出现一次 metric search --fuzzy,所有关键词都在这一次调用中",
60
+ "消费空结果后,调用序列中不再出现调换顺序、等价改写或查询子集的第二次 search",
61
+ "无结果说明包含 attempted_keywords、search_scope 和 stop_reason=no_candidate_within_budget",
62
+ "不把附件中的直接名称搜索计入候选发现 fuzzy 轮次"
63
+ ]
64
+ },
65
+ {
66
+ "id": 6,
67
+ "prompt": "上一请求曾按附件记录搜索‘复购成交贡献’且没有候选。现在这是一个新的用户请求:再帮我找一次‘复购成交贡献’相关指标。请给出本次请求的下一条候选发现命令;不要沿用附件发生时的指标可见性。",
68
+ "expected_output": "代理不能复用上一请求的无结果结论,必须基于当前可见指标重新执行一次单批 metric search --fuzzy;关键词仍以原词为首并遵守 5 词预算。",
69
+ "files": [
70
+ "fixtures/metric-candidate-prior-request.json"
71
+ ],
72
+ "expectations": [
73
+ "即使附件记录上一请求无结果,本次仍生成一条新的 metric search --fuzzy 命令",
74
+ "本次调用序列中恰好出现一次 metric search --fuzzy",
75
+ "原词复购成交贡献保留在首位,去重后总关键词不超过 5 个",
76
+ "不把上一请求的 stop_reason 当成本次请求的搜索结果"
77
+ ]
49
78
  }
50
79
  ]
51
80
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "scenario": "current-request-empty-candidate-search",
3
+ "searchScope": "当前用户可见的全部指标主题",
4
+ "directNameSearch": {
5
+ "keyword": "复购成交贡献",
6
+ "count": 0,
7
+ "contents": []
8
+ },
9
+ "fuzzySearchFixture": {
10
+ "count": 0,
11
+ "contents": []
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "scenario": "prior-request-negative-result-must-not-be-reused",
3
+ "requestId": "prior-request",
4
+ "searchedAt": "2026-08-27T17:51:18+08:00",
5
+ "attemptedKeywords": [
6
+ "复购成交贡献",
7
+ "重复购买贡献",
8
+ "回购贡献"
9
+ ],
10
+ "searchScope": "当时用户可见的全部指标主题",
11
+ "candidateCount": 0,
12
+ "stopReason": "no_candidate_within_budget"
13
+ }
@@ -0,0 +1,95 @@
1
+ # 本地分析原语
2
+
3
+ `guancli analyze` 是无网络、无业务语义的本地表格处理入口。输入必须是明确的 CSV/JSON 文件,输出统一为 `analysis/v1` JSON envelope:
4
+
5
+ ```json
6
+ {
7
+ "schemaVersion": "analysis/v1",
8
+ "operation": "normalize",
9
+ "columns": ["区域", "金额"],
10
+ "rowCount": 1,
11
+ "rows": [{"区域": "华东", "金额": "10"}],
12
+ "metadata": {"input": "raw.csv"}
13
+ }
14
+ ```
15
+
16
+ ## 适用边界
17
+
18
+ - CLI 只提供 loader、字段对齐、安全四则运算、分组排序、TopN 和占比。
19
+ - “本期/同期/预算”“同比/达成率”“毛利贡献”“价格/成本效应”等属于上层分析 recipe。调用方应显式选择字段并组合通用原语,禁止假设 CLI 内置这些业务口径。
20
+ - 每一步都写到明确文件再进入下一步。命令失败后读取错误并修正字段或策略,不用临时 Python 脚本绕过契约。
21
+
22
+ ## 规范化
23
+
24
+ ```bash
25
+ guancli analyze normalize raw.csv -o normalized.json
26
+ guancli analyze normalize raw.json --input-format json -o normalized.json
27
+ ```
28
+
29
+ - 自动识别 CSV/JSON,也可以用 `--input-format` 明确指定。
30
+ - 去除 UTF-8 BOM;JSON 嵌套对象扁平化为 `父字段.子字段`。
31
+ - CSV 按记录读取,JSON 对象数组以及 `rows`/`data` 数组按元素读取;最终规范化表仍会保留在内存中,超大结果应在上游先过滤。
32
+ - JSON 数字按原始十进制文本解析并原样写回,超过 JavaScript 安全整数范围的 ID 不会先转成浮点数而丢失精度。
33
+ - CSV/JSON 字符串中的空字符串、`null`、`None`、`<nil>` 默认转成 JSON `null`。需要其他契约时可重复传 `--null-value`;一旦显式传入,就只使用调用方给出的集合。
34
+ - JSON 顶层支持对象数组、单个对象、`rows` 数组或 `data` 数组。
35
+ - 使用 `-o` 时先写同目录临时文件并同步,成功后再原子替换目标;写入、同步或关闭失败时保留原输出文件。
36
+
37
+ ## 对齐
38
+
39
+ ```bash
40
+ guancli analyze align \
41
+ --left current.json \
42
+ --right reference.json \
43
+ --key 区域 --key 产品 \
44
+ --join full \
45
+ --left-prefix current \
46
+ --right-prefix reference \
47
+ -o aligned.json
48
+ ```
49
+
50
+ - `--join` 支持 `full`、`inner`、`left`、`right`。
51
+ - 键字段只输出一份,非键字段统一加左右前缀;缺失的一侧显式输出 `null`。
52
+ - 任一输入出现重复组合键时直接失败。CLI 不猜测聚合方式,也不静默执行多对多连接;调用方必须先按明确口径聚合。
53
+
54
+ ## 安全基础计算
55
+
56
+ ```bash
57
+ guancli analyze calculate aligned.json \
58
+ --operator subtract \
59
+ --left-field current.金额 \
60
+ --right-field reference.金额 \
61
+ --output-field difference \
62
+ --null-policy propagate \
63
+ -o calculated.json
64
+
65
+ guancli analyze calculate aligned.json \
66
+ --operator divide \
67
+ --left-field current.金额 \
68
+ --right-field reference.金额 \
69
+ --output-field ratio \
70
+ --zero-divisor null \
71
+ -o ratio.json
72
+ ```
73
+
74
+ - `--operator` 支持 `add`、`subtract`、`multiply`、`divide`。
75
+ - `--null-policy propagate` 保留空值;只有调用方明确要求时才使用 `zero`。
76
+ - 除数为 0 默认输出 `null`;需要严格失败时使用 `--zero-divisor error`。
77
+ - 非空但不可解析为有限数值的字段(包括 `NaN`/`Inf`)直接报错并定位行号,不使用默认值吞错。
78
+
79
+ ## 分组 TopN 与占比
80
+
81
+ ```bash
82
+ guancli analyze topn calculated.json \
83
+ --group-by 区域 \
84
+ --value-field difference \
85
+ --limit 10 \
86
+ --order desc \
87
+ --rank-field rank \
88
+ --share-field share \
89
+ -o topn.json
90
+ ```
91
+
92
+ - `--group-by` 是分区字段,不指定时对全表排序。
93
+ - 占比分母是该分区全部非空行的数值之和,不是 TopN 截断后的合计。
94
+ - 空值排在有效数值之后,占比为 `null`;分区合计为 0 时占比同样为 `null`。
95
+ - `topn` 不做隐式聚合。存在重复粒度时,先使用具备明确聚合口径的上游查询或工具处理。
@@ -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` 详情;默认包含血缘,加 `--brief` 跳过血缘 |
75
+ | `--with-detail` | 同时返回每个命中指标的 `metric get` 详情;旧格式默认包含血缘,`--brief` 或 `--json-envelope` 不请求血缘 |
76
76
 
77
77
  `--fuzzy` 语义:
78
78
 
@@ -82,11 +82,22 @@ guancli metric search [keyword] [flags]
82
82
  - 结果会在原有指标字段基础上增加命中条件、命中优先级和命中关键词。
83
83
  - 非 `--raw` 输出会额外查询并返回每个指标关联的查询加速摘要,包括查询加速数量和加速指标 ID/优先级/字段摘要。
84
84
  - `--with-detail` 会为当前搜索结果中的每个指标补充与 `metric get <metric_id>` 相同的标准化详情;默认终端输出按指标追加详情,`-f json` 则在每条搜索结果的 `指标详情` 中嵌套返回。
85
- - 默认详情包含血缘;批量搜索只需业务口径、数据集、字段、权限、统计、自定义属性和查询加速等信息时,加 `--brief` 跳过血缘。结果较多时先用 `--limit` 收窄指标数量。
85
+ - 旧格式默认详情包含血缘;批量搜索只需业务口径、数据集、字段、权限、统计、自定义属性和查询加速等信息时,加 `--brief` 跳过血缘。`--json-envelope` 不包含且不请求血缘,需要血缘时使用旧 `-f json`。结果较多时先用 `--limit` 收窄指标数量。
86
86
  - `--with-detail` 只补指标详情,不查询指标数据;指标取数仍使用 `metric query`。
87
87
  - `--with-detail` 需要组合多个接口的结果,因此不兼容 `--raw`、`-f csv` 和 `-f excel`。
88
88
  - `[keyword]` 走旧指标名称搜索接口;`--fuzzy` 走新的统一模糊搜索接口,二者不能同时使用。
89
89
 
90
+ 候选发现预算与停止条件:
91
+
92
+ - 用户业务词不能直接命中指标时,一次性准备“原词 + 最多 4 个必要同义词/等价表达”。先 trim、合并连续空白,并按大小写不敏感语义去重;原词必须保留在首位。
93
+ - 把整组关键词放进同一次 `metric search --fuzzy`,例如 `--fuzzy "复购金额,重复购买金额,回购金额"`。不要逐词调用 search,也不要在无结果后通过调换顺序、轻微改写或查询子集重复执行等价搜索。
94
+ - Agent 候选发现预算默认最多 5 个关键词、1 个批量搜索轮次。后端硬上限是 10 个关键词,每个关键词最长 100 个字符;硬上限是接口保护,不是鼓励 Agent 扩大探索范围。
95
+ - 如果单批搜索返回候选,按返回顺序和命中信息列出全部候选,不再发起另一轮同义词搜索;后续是否查询指标数据取决于候选是否唯一以及用户选择。
96
+ - 如果单批搜索无候选,立即结束本轮候选发现。回答必须包含:`attempted_keywords`、`search_scope`、无结果原因“当前可见指标的名称、业务口径和可搜索业务属性均未命中”,以及 `stop_reason=no_candidate_within_budget`。
97
+ - 只有请求本身因可识别的认证、网络或服务错误失败时,才按对应错误恢复流程处理;业务无命中不是重试理由。
98
+ - 不缓存、不持久化、也不跨请求复用“未找到指标”的结论。每个新请求都必须基于当时的指标可见性、权限和指标内容重新判断。
99
+ - 已知指标主题 ID 时用 `-d <metric_topic_id>` 缩小 `search_scope`;未知主题时要说明搜索覆盖当前用户可见的全部指标主题。一次 CLI 调用在未知主题时可能内部扫描多个主题,不能把它表述成一次 HTTP 请求。
100
+
90
101
  回答要求:
91
102
 
92
103
  - 必须逐条返回命中的指标,至少包含指标 ID、指标名称、状态、类型。
@@ -119,8 +130,8 @@ guancli metric search --fuzzy <关键词> --profile <profile> --limit 5 --with-d
119
130
  确实需要机器处理 JSON 时,先保存成功输出再单独执行 jq,避免管道末端成功掩盖 guancli 失败:
120
131
 
121
132
  ```bash
122
- guancli metric search --fuzzy <关键词> --profile <profile> --limit 5 --with-detail --brief -f json > metric_search.json &&
123
- jq '.[] | {"指标ID": .["指标ID"], "名称": .["名称"], "适用维度": .["指标详情"]["适用维度"]}' metric_search.json
133
+ guancli metric search --fuzzy <关键词> --profile <profile> --limit 5 --with-detail --brief --json-envelope > metric_search.json &&
134
+ jq '.data[] | {id, name, dimensions, timeField}' metric_search.json
124
135
  ```
125
136
 
126
137
  中文 key 必须使用 `.["字段名"]`,嵌套 key 必须逐级引用;不要写 `.指标详情.适用维度`。必要解析不要添加 `2>/dev/null`。如果命令失败,先保留 stderr 和非零退出码并查看 `guancli metric search --help`,不要继续猜参数。
@@ -155,8 +166,8 @@ guancli metric get <metric_id> --profile <profile> --brief
155
166
  需要结构化提取时拆成两步:
156
167
 
157
168
  ```bash
158
- guancli metric get <metric_id> --profile <profile> --brief -f json > metric_detail.json &&
159
- jq '.["适用维度"] | map({"名称": .["名称"], "字段ID": .["字段ID"], "字段类型": .["字段类型"]})' metric_detail.json
169
+ guancli metric get <metric_id> --profile <profile> --brief --json-envelope > metric_detail.json &&
170
+ jq '.data.dimensions' metric_detail.json
160
171
  ```
161
172
 
162
173
  ### metric accelerate
@@ -204,7 +215,9 @@ guancli metric by-dataset <ds_id> --profile default --raw
204
215
 
205
216
  ### metric query
206
217
 
207
- 查询指标数据,支持维度、筛选、排序、列筛选和行数限制。泛化查询参数见 `metric-generic-query.md`。
218
+ 查询指标数据,支持维度、筛选、排序、列筛选和行数限制。默认按指标配置的 `format` 输出数值;查询响应携带更具体的列级格式时优先使用列级格式。泛化查询参数见 `metric-generic-query.md`。
219
+
220
+ 格式化覆盖数值、货币、百分比、高级格式,以及小数位、千分位、数量级单位、前后缀等配置。没有有效指标格式时才使用 `--precision` 回退。需要保留原始数值时使用 `--value-format raw`;它与全局 `--raw` 不同:前者仍输出标准表格/JSON/CSV/Excel,只是不应用数值展示格式,后者直接返回后端原始响应。
208
221
 
209
222
  非 `--raw` 输出会展示本次查询是否命中查询加速:summary 中有 `查询加速`,数据行中有 `_queryAccelerate`。命中时展示源指标 ID、加速指标 ID 和后端排序权重,例如 `metric_xxx->acc_xxx(优先级4)`;未命中时显示 `否`。若后端版本尚未返回查询加速 metadata,则显示 `未知: 后端未返回`。
210
223
 
@@ -228,14 +241,21 @@ guancli metric query <metric_id> [flags]
228
241
  | `--limit int` | `50` | 数据行数限制 |
229
242
  | `--dim strings` | 无 | 维度名称,可多次指定,也支持逗号、中文逗号、顿号分隔 |
230
243
  | `--filter stringArray` | 无 | 筛选条件,格式:`"列名 操作符 值"`,可多次指定 |
244
+ | `--filter-json stringArray` | 无 | 结构化筛选 JSON,可重复;支持嵌套 AND/OR 条件树 |
245
+ | `--filter-file string` | 无 | 从 JSON 文件读取一棵结构化条件树;与 `--filter`、`--filter-json` 互斥 |
231
246
  | `--combine-type string` | `AND` | 多条件组合方式:`AND` 或 `OR` |
247
+ | `--dry-run` | `false` | 只返回规范化查询计划、字段类型和稳定错误码,不执行指标取数;必须同时使用 `--json-envelope`,且不支持普通文件或 stderr 输出目标 |
248
+ | `--json-envelope` | `false` | 输出带 `schemaVersion` 的稳定 JSON envelope;`--dry-run` 必须启用此参数,且不能与 `--raw`、非 JSON `-f` 或 stderr 输出目标同时使用 |
232
249
  | `--sort-asc string` | 无 | 按列升序排序,与 `--sort-desc` 互斥 |
233
250
  | `--sort-desc string` | 无 | 按列降序排序,与 `--sort-asc` 互斥 |
234
251
  | `--columns strings` | 无 | 只显示指定列,逗号分隔,在 CLI 端执行 |
235
- | `--precision int` | `6` | 数值最大小数位数;传 `-1` 保留原始精度 |
252
+ | `--precision int` | `6` | 没有有效指标格式时的数值最大小数位数;传 `-1` 保留原始精度 |
253
+ | `--value-format string` | `formatted` | `formatted` 按指标格式输出;`raw` 保留原始数值 |
236
254
  | `-o, --output string` | 无 | 将查询结果写入文件;未指定且结果超过 1000 行时自动写入文件 |
237
255
 
238
- 未指定 `-o/--output` 且查询结果超过 1000 行时,默认写入 `metric_<metricId>_<timestamp>.<ext>` 文件,避免把大结果直接塞入上下文。默认 `-f auto` 在写文件时会切换为 CSV;显式指定 `-f json/csv/table/expanded/excel` 时按指定格式写入。
256
+ `metric search/get/tree/query --json-envelope` 都返回带版本号的稳定 JSON envelope,当前 canonical 契约版本为 `1.0`,公共字段为 `schemaVersion`、`command`、`resultMode`、`rowCount`。内联结果在 `data`,文件结果在绝对 `path`;query 还返回 `columns`。版本演进读取响应体中的 `schemaVersion`,不会增加 `json-v2` 一类输出格式。原 `-f json` 保持旧版对象/数组结构,避免破坏 Decidex 等既有调用方。未指定 `-o/--output` 且查询结果超过 1000 行时,默认模式仍自动写 CSV 并输出原中文提示;启用 `--json-envelope` 时写 JSON 文件,stdout 返回 `resultMode=file` envelope。自动文件名带唯一后缀,避免同秒并发或重试覆盖已有结果。显式非 JSON `-f` 与 `--json-envelope` 不兼容。
257
+
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` 只省略计数和权限,不省略节点身份。中文展示字段只属于默认输出和旧 `-f json`,不属于 envelope 契约。canonical 模型不包含血缘,因此 `--with-detail --json-envelope` 不请求血缘;确实需要血缘时使用原 `-f json`。query dry-run 不查询加速配置,此时省略 `metric.accelerations`,不能把省略解释成无加速配置。
239
259
 
240
260
  筛选操作符:
241
261
 
@@ -256,14 +276,19 @@ guancli metric query <metric_id> --profile default
256
276
  guancli metric query <metric_id> --profile default --dim 省份 --limit 10
257
277
  guancli metric query <metric_id> --profile default --dim "省份、城市" --limit 20
258
278
  guancli metric query <metric_id> --profile default --dim 省份 --filter "省份 EQ 河南省"
259
- guancli metric query <metric_id> --profile default --dim 省份 --filter "省份 EQ 河南省" --filter "省份 EQ 青海省" --combine-type OR
279
+ guancli metric query <metric_id> --profile default --dim 省份 --filter "省份 EQ 河南省" --filter "省份 EQ 青海省" --combine-type OR --dry-run --json-envelope
280
+ guancli metric query <metric_id> --profile default --filter-json '{"field":"省份","operator":"IN","values":["河南省","青海省"]}' --dry-run --json-envelope
281
+ guancli metric query <metric_id> --profile default --filter-file filters.json --dry-run --json-envelope
260
282
  guancli metric query <metric_id> --profile default --dim 省份 --sort-desc 订购数量
261
283
  guancli metric query <metric_id> --profile default --dim 省份 --columns "省份,订购数量"
262
284
  guancli metric query <metric_id> --profile default --dim 省份 -f csv
285
+ guancli metric query <metric_id> --profile default --value-format raw -f json
263
286
  guancli metric query <metric_id> --profile default --dim 省份 --limit 10000 -f csv -o metric.csv
264
287
  guancli metric query <metric_id> --profile default --dim 省份 --raw
265
288
  ```
266
289
 
290
+ 多分支 OR 的 dry-run 会返回 `valid=true`、`executable=false`、`requestCount=0` 和错误码 `FILTER_OR_EXECUTION_UNSUPPORTED`。当前指标取数接口不能在单次请求中无损表达这类 OR,真实执行会在取数前拒绝,不会拆成多次聚合查询后拼接。
291
+
267
292
  #### 可复制模板:筛选并裁剪查询结果
268
293
 
269
294
  ```bash
@@ -277,6 +302,26 @@ guancli metric query <metric_id> --profile <profile> \
277
302
 
278
303
  出现筛选语法错误后,先执行 `guancli metric query --help` 并按帮助纠正;不要连续尝试 `=`、`==`、`>=` 等相近符号写法。`--columns` 已能在 Go 端稳定裁剪结果列,不要为这一步额外拼 jq。
279
304
 
305
+ 结构化条件树示例:
306
+
307
+ ```json
308
+ {
309
+ "combineType": "AND",
310
+ "conditions": [
311
+ {"field": "省份", "operator": "IN", "values": ["浙江省", "江苏省"]},
312
+ {
313
+ "combineType": "OR",
314
+ "conditions": [
315
+ {"field": "销售额", "operator": "GE", "value": 100},
316
+ {"field": "销售额", "operator": "BT", "values": [200, 300]}
317
+ ]
318
+ }
319
+ ]
320
+ }
321
+ ```
322
+
323
+ CLI 会把条件树确定性展开为“组内 AND、组间 OR”的查询计划,并在 dry-run 的 `requestCount` 和 `normalizedQueries` 中展示。为避免组合爆炸,最多展开 64 个查询组;超过时返回 `FILTER_TOO_MANY_QUERY_GROUPS`。其他结构化校验错误同样使用稳定的 `FILTER_*` code。
324
+
280
325
  ### metric tree
281
326
 
282
327
  获取指标目录树。默认输出树形结构,最外层展示指标主题。