@guandata/guancli 1.0.63 → 1.0.66
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 +19 -0
- package/README.md +18 -0
- package/bin/run.js +14 -1
- package/package.json +6 -6
- package/skills/guancli/SKILL.md +27 -4
- package/skills/guancli/evals/evals.json +8 -9
- package/skills/guancli/references/analysis-primitives.md +114 -4
- package/skills/guancli/references/form-chatbi.md +1 -0
- package/skills/guancli/references/gateway.md +148 -0
- package/skills/guancli/references/metric-batch-query.md +2 -0
- package/skills/guancli/references/metric-commands.md +25 -10
- package/skills/guancli/references/metric-query-recipes.md +6 -0
- package/skills/guancli/references/preview-and-output.md +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## @guandata/guancli 1.0.66 - 2026-10-14
|
|
4
|
+
|
|
5
|
+
- 新增本地 `analyze` 表格处理与 `report` 排名分析入口,可对 CSV/JSON 结果进行字段对齐、计算、分组排名和占比输出。
|
|
6
|
+
- 修复指标查询中计算字段作为维度或排序列时的列名解析错误。
|
|
7
|
+
|
|
8
|
+
## @guandata/guancli 1.0.65 - 2026-10-12
|
|
9
|
+
|
|
10
|
+
- 子表行更新前校验分页总数与行标识;读取不完整时停止操作,避免误删现有行。
|
|
11
|
+
- 认证请求拒绝跨源重定向,防止 BI 凭据被转发到其他站点。
|
|
12
|
+
- 平台包发布校验兼容 npm 12 的元数据格式。
|
|
13
|
+
|
|
14
|
+
## @guandata/guancli 1.0.64 - 2026-10-12
|
|
15
|
+
|
|
16
|
+
- 补齐请求转发 / API Gateway 的 CLI 支持与使用文档,支持通过观远 BI 调用外部接口。
|
|
17
|
+
- `ds execute-sql -f json` 新增 `--typed` 选项,支持输出 `null` 和 JSON 数字。
|
|
18
|
+
- 支持按主题读取指标目录树。
|
|
19
|
+
- 修复 `etl get` 的上游刷新配置读取与展示,所有上游均开启时显示“全部开启”。
|
|
20
|
+
- 优化 `npm link` 开发场景提示:缺少本地构建时,引导执行 `npm run build`。
|
|
21
|
+
|
|
3
22
|
## @guandata/guancli 1.0.63 - 2026-09-24
|
|
4
23
|
|
|
5
24
|
- 指标查询新增 `--explain-requests -f json`,只读展示实际请求顺序与请求体,方便检查参数组合;不会执行取数。
|
package/README.md
CHANGED
|
@@ -45,6 +45,24 @@ guancli chatbi query --theme-name "经营主题" --message "最近30天营业收
|
|
|
45
45
|
|
|
46
46
|
## 版本更新
|
|
47
47
|
|
|
48
|
+
### @guandata/guancli 1.0.66
|
|
49
|
+
|
|
50
|
+
- 新增本地 `analyze` 表格处理与 `report` 排名分析入口,可对 CSV/JSON 结果进行字段对齐、计算、分组排名和占比输出。
|
|
51
|
+
- 修复指标查询中计算字段作为维度或排序列时的列名解析错误。
|
|
52
|
+
|
|
53
|
+
### @guandata/guancli 1.0.65
|
|
54
|
+
|
|
55
|
+
- 子表行更新前校验分页总数与行标识;读取不完整时停止操作,避免误删现有行。
|
|
56
|
+
- 认证请求拒绝跨源重定向,防止 BI 凭据被转发到其他站点。
|
|
57
|
+
- 平台包发布校验兼容 npm 12 的元数据格式。
|
|
58
|
+
|
|
59
|
+
### @guandata/guancli 1.0.64
|
|
60
|
+
|
|
61
|
+
- 指标目录树支持 `-d / --dir-id <topic-id>`,只读取所选主题的目录树,保留原有权限和输出格式。
|
|
62
|
+
- 新增请求转发路由的创建、查找、详情和调用命令;创建前可用 `--dry-run` 查看请求配置与访问范围。
|
|
63
|
+
- `ds execute-sql -f json --typed` 可保留空值及数值类型;ETL 调度详情能正确识别全部上游更新后触发。
|
|
64
|
+
- 从源码目录运行但尚未构建时,启动器会提示先执行 `npm run build`。
|
|
65
|
+
|
|
48
66
|
### @guandata/guancli 1.0.63
|
|
49
67
|
|
|
50
68
|
- 指标查询新增 `--explain-requests -f json`,只读展示实际请求顺序与请求体,方便检查参数组合;不会执行取数。
|
package/bin/run.js
CHANGED
|
@@ -60,11 +60,24 @@ function resolvePlatformBinaries(options = {}) {
|
|
|
60
60
|
// Local development fallback. The generated directory is excluded from
|
|
61
61
|
// the published main package, so installed users always use the optional
|
|
62
62
|
// platform dependency above.
|
|
63
|
-
const
|
|
63
|
+
const pkgRoot = path.join(__dirname, "..");
|
|
64
|
+
const localBinDir = path.join(pkgRoot, "platforms", target.suffix, "bin");
|
|
64
65
|
const binaryPaths = {};
|
|
65
66
|
for (const binary of target.binaries) {
|
|
66
67
|
const binaryPath = path.join(localBinDir, binary);
|
|
67
68
|
if (!exists(binaryPath)) {
|
|
69
|
+
// scripts/ is not published, so this is a source checkout (npm link).
|
|
70
|
+
// npm link never installs the optional platform package; reinstalling
|
|
71
|
+
// from the registry would not help, the local build is missing.
|
|
72
|
+
if (exists(path.join(pkgRoot, "scripts", "build.js"))) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`Missing local build for ${key}: ${binaryPath}\n` +
|
|
75
|
+
`This ${PACKAGE_PREFIX} is a source checkout (npm link), which runs the ` +
|
|
76
|
+
`binaries built into platforms/ instead of the optional platform package.\n` +
|
|
77
|
+
`Build them first:\n` +
|
|
78
|
+
` cd "${pkgRoot}" && npm run build`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
68
81
|
throw new Error(
|
|
69
82
|
`Missing optional platform package ${target.packageName} for ${key}.\n` +
|
|
70
83
|
`Reinstall without disabling optional dependencies:\n` +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guandata/guancli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.66",
|
|
4
4
|
"description": "观远 BI 命令行工具 - 通过 API 操作 ETL、数据集、页面、表单等资源,并提供 ChatBI 问数/洞察能力",
|
|
5
5
|
"bin": {
|
|
6
6
|
"guancli": "bin/run.js"
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
"node": ">=14"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
|
-
"@guandata/guancli-darwin-arm64": "1.0.
|
|
46
|
-
"@guandata/guancli-darwin-x64": "1.0.
|
|
47
|
-
"@guandata/guancli-linux-x64": "1.0.
|
|
48
|
-
"@guandata/guancli-linux-arm64": "1.0.
|
|
49
|
-
"@guandata/guancli-win32-x64": "1.0.
|
|
45
|
+
"@guandata/guancli-darwin-arm64": "1.0.66",
|
|
46
|
+
"@guandata/guancli-darwin-x64": "1.0.66",
|
|
47
|
+
"@guandata/guancli-linux-x64": "1.0.66",
|
|
48
|
+
"@guandata/guancli-linux-arm64": "1.0.66",
|
|
49
|
+
"@guandata/guancli-win32-x64": "1.0.66"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"registry": "https://registry.npmjs.org/",
|
package/skills/guancli/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: guancli
|
|
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
|
|
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 整包”,或要根据第三方接口文档创建、配置、调用“请求转发 / API Gateway”时,也要使用这个 skill。用户要删除、重命名、移动页面时,本 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
|
|
|
@@ -19,6 +19,7 @@ guancli 是 BI 资源的查询分析入口,并支持 Form 表单填报 CRUD、
|
|
|
19
19
|
- 用户要搜索指标、获取指标详情、查询指标数据、查看指标目录、执行指标树归因,或让你生成/解释指标泛化查询命令。
|
|
20
20
|
- 用户给出数据集 ID,想查看该数据集创建或影响到的所有指标,包括直接原子指标以及下游复合指标、衍生指标。
|
|
21
21
|
- 用户要创建、发布或更新超级应用 / SuperApp,或要把平台上的 SuperApp 整包下载成本地 zip。
|
|
22
|
+
- 用户给出第三方接口文档,希望转换成观远 BI 请求转发配置、创建路由或生成调用代码。
|
|
22
23
|
- 用户要删除、重命名、移动页面(本 skill 只负责把用户路由到 `guanvis page`,命令不在 guancli)。
|
|
23
24
|
- 用户要为已有仪表板或智能洞察卡片生成智能洞察结果。
|
|
24
25
|
- 用户已经取得本地 CSV/JSON,需要稳定处理 BOM/null/嵌套字段、对齐两个结果集、执行安全四则运算,或做通用分组 TopN/占比;不再临时生成 Python 拼接脚本。
|
|
@@ -66,6 +67,7 @@ guancli 是 BI 资源的**查询分析入口**,并支持 Form 表单填报 CRU
|
|
|
66
67
|
| Form CRUD、子表、ChatBI 主题问数/洞察 | `references/form-chatbi.md` |
|
|
67
68
|
| 指标与指标树全量命令 | `references/metric-commands.md` |
|
|
68
69
|
| 指标泛化查询参数与示例 | `references/metric-generic-query.md` |
|
|
70
|
+
| 请求转发配置生成、创建、调用与安全边界 | `references/gateway.md` |
|
|
69
71
|
| 指标 query 参数模式、互斥矩阵与真实请求体 | `references/metric-query-recipes.md` |
|
|
70
72
|
| 本地 CSV/JSON 规范化、对齐、基础计算、TopN | `references/analysis-primitives.md` |
|
|
71
73
|
|
|
@@ -160,8 +162,9 @@ guancli 在这条链路上只出只读的那一环:`guancli page search` / `pa
|
|
|
160
162
|
- 必须解析的命令不得用 `2>/dev/null` 隐藏 stderr,也不得用 `2>&1` 将错误文本送入 JSON 解码器。不要用会让末端命令成功掩盖上游失败的管道;允许组合执行时用 `&&` 衔接“输出到文件 → 解析摘要”,不为读取文件另起一轮推理,必须使用管道时先启用 `set -o pipefail`。
|
|
161
163
|
- 同类语法错误只允许出现一次;第一次失败后先执行对应命令的 `--help` 或读取本 Skill 的参考文档,再按真实契约纠正,不连续尝试相近写法。
|
|
162
164
|
- 普通 `--filter`、可重复 `--filter-json`、单个 `--filter-file` 三选一,禁止混用。复杂筛选优先使用 `--filter-json`(可重复)或 `--filter-file` 条件树。Agent 执行任意单条 `metric query`(包括无参数的基础查询)前都必须先用同一组查询参数追加 `--explain-requests -f json`,核对真实接口顺序和最终 request body;只有 `valid=true`、`executable=true` 且 body 符合业务意图时,才移除 explain 执行真实查询。`batch-query` 是独立批量契约,不支持 explain,不套用这条单条查询门禁;它仍按上文同轮批量规则使用。只需人工快速检查维度/筛选时可用 `--dry-run -f json`,但不能替代 Agent 的 explain-first 门禁。explain 会调用与真实执行相同的 request builder:泛化查询给出最终 `metric-data/v2` body,基础查询只读保存的 card edit meta 后给出完整 session/modify/data 计划;它不创建 edit session、不执行 POST、不取数。完整模式矩阵见 `references/metric-query-recipes.md`。dry-run 只读取指标详情做查询维度、筛选字段和类型校验,不执行指标取数,也不支持普通文件或 stderr 输出目标;保存卡片高级计算列不在指标详情中,因此这类排序候选在 dry-run 中不会被猜测为有效,explain/真实执行会读取既有 card 配置校验。不支持的 `--dim`、普通 `--filter` 的字段、`--sort-asc`/`--sort-desc` 的字段都按指标详情中的字段(适用维度 / 时间维度 / 指标字段名)校验,未命中返回 `METRIC_UNSUPPORTED_DIMENSION`;结构化 `--filter-json`/`--filter-file` 在解析阶段按同一份字段集合校验,未命中返回 `FILTER_UNKNOWN_FIELD`。两类错误都不会静默忽略条件或透传未知字段。普通展示别名只对 `--dim` 与排序生效;若指标详情的 `publicDimensionMap` 把唯一公共维度名映射到一个适用维度,则 `--dim`、排序和筛选也可使用该公共维度名,CLI 会保留物理 `fdId` 并把公共维度名作为 alias;同名映射到多个物理字段时拒绝猜测。仅由 CLI 为排序注入、以指标 ID 充当 `fdId` 的“指标名伪字段”不能用于筛选,若指标详情的 `fdInfos` 本身含同名原始字段和真实 `fdId`,仍可正常筛选。`--sort-asc`/`--sort-desc` 额外接受保存卡片中真实存在的高级计算列,以及泛化查询的结果列名 `<指标名>_<后缀>`(`_yoy`/`_mom`/`_qoq`/`_wow`/`_dod`/`_ytd`/`_qtd`/`_mtd`/`_wtd`/`_dtd`/`_last`/`_recent_*`/`_percentage`/`_rank`)。遇到这些错误时先用 `guancli metric get` 读取适用维度再改字段。条件组使用 `combineType: AND|OR` 和 `conditions` 数组,叶子使用 `field/operator/value|values`;`IN` 至少一个值,`BT` 恰好两个值。当前指标取数接口不能无损表达多分支 OR,真实执行会在取数前返回 `FILTER_OR_EXECUTION_UNSUPPORTED`,不得拆成多次聚合查询后拼接。失败时按稳定错误码修正,不猜错误文本。
|
|
165
|
+
- 查询计算字段维度或按计算字段排序时,直接使用指标详情中的字段名(日期子维度仍可加 `toMonth` 等粒度),无需手工传公式;CLI 会从指标详情把 `formula` 带入基础卡片和泛化查询的维度/排序请求。先用 `metric get <id> --raw` 核对计算字段的 `formula/fdType`,再用同参数的 `--explain-requests -f json` 检查最终请求体。若不再报 `UNRESOLVED_COLUMN`,但维度值为空或筛选报 `DATATYPE_MISMATCH`,对照 `ds get --raw` 与 `ds preview` 核查公式实际结果和字段声明类型;不能把请求成功当成维度结果正确。详见 [计算字段查询排查](references/metric-query-recipes.md#计算字段维度与排序)。
|
|
163
166
|
- 搜索并同时查看业务口径、数据集和适用维度等详情时,优先使用 `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`。
|
|
164
|
-
-
|
|
167
|
+
- `metric search --fuzzy` 的每项关键词按原文匹配,不自动拆词或解析型号、客户等筛选实体;多个关键词使用重复的 `--fuzzy` 参数,彼此为 OR。后端最多接受 10 个关键词,每项最长 100 个字符。候选发现默认首轮最多 5 个去重关键词;禁止相同范围下换序、轻微改写或取子集重复搜索。仅发现具体错误或新线索时,说明依据和参数修正,最多追加一轮纠错;单纯无命中不是重查依据。仍不能确定则说明关键词、范围和原因,必要时请用户补充信息,不断言指标不存在。完整协议及纠错边界见 `references/metric-commands.md`。
|
|
165
168
|
- 指标结果加工前,先读取成功 query envelope 的实际 `columns` 和行对象 keys,按业务含义选择列;禁止硬编码或猜测指标展示列名(包括高级计算后缀),也不能按列位置取值。使用 `python3 references/examples/metric-query-rows.py <envelope.json> --list-columns` 发现列,再用 `--column "<已确认的实际列名>"` 精确选择;候选缺失或多义时停止并返回实际列集合,不猜近似名称。该参数属于消费 recipe,不是 `guancli metric query` 的参数。
|
|
166
169
|
- 普通指标数据查询用 `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)。
|
|
167
170
|
- 同一批量查询既用于计算又用于展示时,使用 `valueFormat: "both"`;原始 `rows` 用于计算,`formattedRows` 用于展示,不按格式重复取数。仅需一种格式时使用 raw 或 formatted,避免额外输出。
|
|
@@ -217,13 +220,33 @@ GUANCLI_DOWNLOAD_TIMEOUT=1200 guancli app download <appId> # 大包/慢网络
|
|
|
217
220
|
|
|
218
221
|
## 请求转发路由
|
|
219
222
|
|
|
220
|
-
|
|
223
|
+
创建请求转发、查找已有路由或生成 SuperApp 调用代码时,先读 `references/gateway.md`。创建主流程是:整理配置草案 → 用户确认敏感数据引用、权限范围和启用状态 → `--dry-run` → 真实创建。不要把真实 token、密码、AK/SK 或 client secret 写入配置文件或对话;只引用 BI 中已保存的 `${SECRET.xxx}`。
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
guancli gateway create gateway.json --dry-run
|
|
227
|
+
guancli gateway create gateway.json
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
创建接口要求当前用户拥有请求转发 `UPDATE` 权限,环境还需开通超级应用商业授权。`--dry-run` 只验证本地 JSON 结构并展示请求,不证明权限、授权或服务端创建一定成功。
|
|
231
|
+
|
|
232
|
+
用户用自然语言描述要调用的业务接口、但不知道识别符时,先用业务名或系统名搜索,再读取候选路由的稳定调用契约:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
guancli gateway search CRM --enabled
|
|
236
|
+
guancli gateway get 42
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
`search` 只按名称或识别符匹配,返回当前分页;无结果时可缩短关键词或省略关键词,不能把单页结果当作全量。多个候选无法可靠区分时,向用户确认,不要猜路由。`get` 默认输出脱敏后的 v1.0 调用契约,包括 BI 网关路径、方法、追加路径、Query/Header/Body 映射、访问约束、文档说明和调用示例;不得根据 `--raw` 中的目标 URL 生成应用代码。
|
|
240
|
+
|
|
241
|
+
生成代码前检查 `enabled`、`gatewayMethod`、`loginRequired`、允许用户/用户组、`allowedCallerHosts` 和所有 `required` 入参。POST 路由即使 `bodyRequired=false` 也必须保留可选的透传 body 支持;该字段只决定是否强制要求 body。响应解析必须保留上游类型:空的 204/205 返回 `null`,再按 Content-Type 选择 `json()`、`text()` 或 `blob()`,不得固定执行 `response.json()`。代码只能访问 `gatewayPath` / `gatewayUrlTemplate` 指向的 BI 网关。路由未启用、方法不匹配、来源不允许或必填参数缺失时,明确指出修复动作,不能改为直连第三方地址。
|
|
242
|
+
|
|
243
|
+
需要实际调试已有路由时使用 `gateway invoke`:
|
|
221
244
|
|
|
222
245
|
```bash
|
|
223
246
|
guancli gateway invoke orders --method GET --path 2026/detail --query tenant=cn
|
|
224
247
|
```
|
|
225
248
|
|
|
226
|
-
`invoke` 支持重复 `--query key=value`、`--header key=value`,以及互斥的 `--body` / `--body-file`。默认直接输出解析后的响应 JSON body;排查请求时增加 `--verbose`,可额外查看 `statusCode` 和脱敏后的 `headers`。`--raw`
|
|
249
|
+
`invoke` 支持重复 `--query key=value`、`--header key=value`,以及互斥的 `--body` / `--body-file`。默认直接输出解析后的响应 JSON body;排查请求时增加 `--verbose`,可额外查看 `statusCode` 和脱敏后的 `headers`。`--raw` 只输出原始响应体。非 2xx 响应会先完成上述输出,再返回错误并使进程退出码非零;脚本既要保留输出用于诊断,也必须检查退出码。
|
|
227
250
|
|
|
228
251
|
为避免覆盖 CLI 到 BI 的认证上下文,`Cookie`、`Authorization`、`token`、`X-Auth-Token`、`X-Personal-Token`、`x-dom-id` 和 `user-id` 等保留 Header 不能通过 `--header` 传入;目标服务鉴权应配置在路由模板或 Secret 中。
|
|
229
252
|
|
|
@@ -52,29 +52,28 @@
|
|
|
52
52
|
{
|
|
53
53
|
"id": 5,
|
|
54
54
|
"prompt": "帮我找‘复购成交贡献’相关指标。附件给出了本轮可重复的指标搜索返回,请展示你会执行的候选发现命令和最终答复。",
|
|
55
|
-
"expected_output": "
|
|
55
|
+
"expected_output": "代理应说明 --fuzzy 每项原文匹配、各项 OR 的契约,使用重复参数构造关键词;附件空结果仅证明该次搜索未命中,后续发现与停止遵循调用方业务指令,不由 CLI 强制一轮结束。",
|
|
56
56
|
"files": [
|
|
57
57
|
"fixtures/metric-candidate-empty-search.json"
|
|
58
58
|
],
|
|
59
59
|
"expectations": [
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"不把附件中的直接名称搜索计入候选发现 fuzzy 轮次"
|
|
60
|
+
"多个关键词使用重复的 --fuzzy 参数,说明原文匹配且各项 OR",
|
|
61
|
+
"遵守单次请求最多 10 个关键词、每项最长 100 字符的接口限制",
|
|
62
|
+
"报告本次实际关键词和搜索范围,不将空结果断言为指标不存在",
|
|
63
|
+
"不把 CLI 接口限制当成业务发现轮数或固定停止规则"
|
|
65
64
|
]
|
|
66
65
|
},
|
|
67
66
|
{
|
|
68
67
|
"id": 6,
|
|
69
68
|
"prompt": "上一请求曾按附件记录搜索‘复购成交贡献’且没有候选。现在这是一个新的用户请求:再帮我找一次‘复购成交贡献’相关指标。请给出本次请求的下一条候选发现命令;不要沿用附件发生时的指标可见性。",
|
|
70
|
-
"expected_output": "
|
|
69
|
+
"expected_output": "代理不能把上一请求的空结果作为本次指标不存在的证明;本次搜索基于当前可见范围,关键词与停止条件遵循当前调用方指令和接口限制。",
|
|
71
70
|
"files": [
|
|
72
71
|
"fixtures/metric-candidate-prior-request.json"
|
|
73
72
|
],
|
|
74
73
|
"expectations": [
|
|
75
74
|
"即使附件记录上一请求无结果,本次仍生成一条新的 metric search --fuzzy 命令",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
75
|
+
"使用重复的 --fuzzy 参数表达多个关键词,不将它们拼接成一句话",
|
|
76
|
+
"遵守单次请求最多 10 个关键词、每项最长 100 字符的接口限制",
|
|
78
77
|
"不把上一请求的 stop_reason 当成本次请求的搜索结果"
|
|
79
78
|
]
|
|
80
79
|
},
|
|
@@ -17,7 +17,35 @@
|
|
|
17
17
|
|
|
18
18
|
- CLI 只提供 loader、字段对齐、安全四则运算、分组排序、TopN 和占比。
|
|
19
19
|
- “本期/同期/预算”“同比/达成率”“毛利贡献”“价格/成本效应”等属于上层分析 recipe。调用方应显式选择字段并组合通用原语,禁止假设 CLI 内置这些业务口径。
|
|
20
|
-
-
|
|
20
|
+
- 优先用下述 report 统一入口;需要其他组合时再逐步调用原语。命令失败后读取错误并修正字段或策略,不用临时 Python 脚本绕过契约。
|
|
21
|
+
|
|
22
|
+
## 首选:统一排名分析入口 report
|
|
23
|
+
|
|
24
|
+
常见“每组 TopN+补充同键指标/贡献占比/比率”用一条命令,不必生成中间文件,也不需要 DSL:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 两份查询按相同品类、型号粒度取 raw,并先核实取数完整。
|
|
28
|
+
guancli analyze report profit.json --group-by 品类 --value-field 毛利额 \
|
|
29
|
+
--limit 1 --complete-input --enrich margin-rate.json --key 品类,型号 \
|
|
30
|
+
-o category-leaders.json
|
|
31
|
+
|
|
32
|
+
# 全局收入排名+占比+同键利润安全除法复核。
|
|
33
|
+
guancli analyze report income.json --global --value-field 收入 \
|
|
34
|
+
--limit 4 --share-field contribution --complete-input \
|
|
35
|
+
--enrich profit.json --key 客户 --operator divide \
|
|
36
|
+
--left-field extra.毛利额 --right-field 收入 --output-field margin \
|
|
37
|
+
-o income-ranking.json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- 沿用 loader;batch 主文件用 --result-id,补充文件用独立 --enrich-result-id。单查 raw、batch raw/both。
|
|
41
|
+
- 固定流程:规范化 → 可选 left 对齐完整候选池 → 可选安全计算 → 分组排名/占比。只输出最终 analysis/v1,operation 为 report。
|
|
42
|
+
- 必须显式二选一 --group-by / --global;“各品类哪款最高”上游同时取品类+型号,并按品类分组,不是全局排名。
|
|
43
|
+
- --complete-input 必须先核验后声明;不证明分页完结或补抓数据。query 默认 50 行不能当全量,report 的 limit 只是每组输出数量。
|
|
44
|
+
- 补充指标须指定完整组合键,默认任一侧重复键失败,即使最终不入榜。显式传 `--allow-repeated-source-keys` 可用唯一补充行匹配多条主输入行(多对一),补充侧重复键仍拒绝;不增加、合并或聚合主输入行。右侧额外对象不进入结果,缺失补充值保持 null。普通 `align` 仍要求两侧键唯一。
|
|
45
|
+
- 补充后非键列为 source.<原列> / extra.<原列>。value-field、group-by、计算操作数可用主输入原列名(自动映射),补充列须 extra.<原列>;计算结果列使用 output-field 原名。
|
|
46
|
+
- operator/left-field/right-field/output-field 必须一起传入。空值传播,除零返回 null;不猜测财务口径。
|
|
47
|
+
- share 分母为截断前完整分区合计。多个指标独立排名应分别从完整原始输入调用 report,不能用已截断子集推算另一指标全池排名。
|
|
48
|
+
- 跨期、严格除零、自定义排序或其他 join 仍使用下面原语;report 不替代所有分析能力。
|
|
21
49
|
|
|
22
50
|
## 规范化
|
|
23
51
|
|
|
@@ -28,10 +56,10 @@ guancli analyze normalize raw.json --input-format json -o normalized.json
|
|
|
28
56
|
|
|
29
57
|
- 自动识别 CSV/JSON,也可以用 `--input-format` 明确指定。
|
|
30
58
|
- 去除 UTF-8 BOM;JSON 嵌套对象扁平化为 `父字段.子字段`。
|
|
31
|
-
- CSV 按记录读取,JSON
|
|
59
|
+
- CSV 按记录读取,JSON 对象数组按元素读取,envelope/二维 rows 通过同一 loader 适配;最终规范化表仍会保留在内存中,超大结果应在上游先过滤。
|
|
32
60
|
- JSON 数字按原始十进制文本解析并原样写回,超过 JavaScript 安全整数范围的 ID 不会先转成浮点数而丢失精度。
|
|
33
61
|
- CSV/JSON 字符串中的空字符串、`null`、`None`、`<nil>` 默认转成 JSON `null`。需要其他契约时可重复传 `--null-value`;一旦显式传入,就只使用调用方给出的集合。
|
|
34
|
-
- JSON 顶层支持对象数组、单个对象、`rows`
|
|
62
|
+
- JSON 顶层支持对象数组、单个对象、`rows`/`data` 对象数组、`columns`+二维 `rows`、`analysis/v1` 和下述 query/batch envelope。列名保持精确匹配。
|
|
35
63
|
- 使用 `-o` 时先写同目录临时文件并同步,成功后再原子替换目标;写入、同步或关闭失败时保留原输出文件。
|
|
36
64
|
|
|
37
65
|
## 对齐
|
|
@@ -90,6 +118,88 @@ guancli analyze topn calculated.json \
|
|
|
90
118
|
```
|
|
91
119
|
|
|
92
120
|
- `--group-by` 是分区字段,不指定时对全表排序。
|
|
93
|
-
-
|
|
121
|
+
- 占比分母是输入文件中该分区全部非空行的数值之和,不是 TopN 截断后的合计;只有输入覆盖完整候选池,才可称为该分区全量占比。
|
|
94
122
|
- 空值排在有效数值之后,占比为 `null`;分区合计为 0 时占比同样为 `null`。
|
|
95
123
|
- `topn` 不做隐式聚合。存在重复粒度时,先使用具备明确聚合口径的上游查询或工具处理。
|
|
124
|
+
|
|
125
|
+
## 查询 → 本地加工(无需解包脚本)
|
|
126
|
+
|
|
127
|
+
单查实际生产契约是 `schemaVersion:"1.0", command:"metric.query"`,inline 的 `columns` 为字符串数组,`data` 为对象行数组。file 模式的绝对 `path` 指向对象行数组文件,loader 自动读取该文件,并校验 rowCount 和必需列;文件缺失、列缺失、版本或类型变化会失败。单查 envelope 不记录 valueFormat,查询时必须显式选择 `--value-format raw`,不要拿格式化字符串做数值计算。
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# 替换为已确认的指标 ID、维度和实际输出列;此处示例业务字段为“区域”“金额”。
|
|
131
|
+
guancli metric query <metricId> --dim 区域 --limit 10000 --value-format raw -f json > query.json
|
|
132
|
+
# 先检查 rowCount/实际返回行数和候选池完整性;10000也不保证全量。
|
|
133
|
+
guancli analyze normalize query.json -o normalized.json
|
|
134
|
+
# 只有确认候选池完整后才排名;否则继续取数或标明结果仅覆盖已取窗口。
|
|
135
|
+
guancli analyze topn normalized.json --value-field 金额 --limit 10 -o topn.json
|
|
136
|
+
# 单查大结果返回 file envelope 时,仍将 stdout 保存为 query.json,使用相同命令。
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
batch 的生产契约是 `results[].result.columns:[{name,role}]` + 二维 `rows`,**不是**单查 `data` 对象数组。必须按输入项精确 id 选择:所有子命令支持 `--result-id`;align 左侧用此参数,右侧用 `--right-result-id`。不按顺序猜项,不自动拼接整批结果。所选项必须 status=success;planned/error、重复或不存在的 id、行宽/rowCount 不一致都失败。partial_failure 中的明确成功项可以单独加工,失败项错误中会保留 code/message/httpStatus/businessStatus。只接受 raw/both;both 消费 `rows`,不消费展示用 `formattedRows`。
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# queries.json 先按 metric-batch-query.md 编写,显式填写 limit/offset;current/prior 是用户定义的查询项 id。
|
|
143
|
+
# 两个结果都确认覆盖完整、同口径候选池后,才执行下面的排名链路。
|
|
144
|
+
guancli metric batch-query --input queries.json -f json > batch.json
|
|
145
|
+
guancli analyze normalize batch.json --result-id current -o current.json
|
|
146
|
+
guancli analyze align --left batch.json --result-id current \
|
|
147
|
+
--right batch.json --right-result-id prior --key 区域 \
|
|
148
|
+
--left-prefix current --right-prefix prior -o aligned.json
|
|
149
|
+
guancli analyze calculate aligned.json --operator subtract \
|
|
150
|
+
--left-field current.金额 --right-field prior.金额 --output-field difference -o delta.json
|
|
151
|
+
guancli analyze topn delta.json --value-field difference --limit 10 -o topn.json
|
|
152
|
+
# 直接在 batch 成功项内计算两个已确认的字段也可行:
|
|
153
|
+
guancli analyze calculate batch.json --result-id current --operator divide \
|
|
154
|
+
--left-field 金额 --right-field 预算 --output-field ratio --zero-divisor null -o ratio.json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
只有位置式输入需要 `columns` 映射单元格;重复/空列名会拒绝,JSON 数字精度及 null 处理复用原 loader。空查询结果仍保留声明的 columns。CLI 只加工所选查询已返回的行,不补抓分页、不推断聚合口径;分组键和计算字段从实际列及业务意图确定。旧 CSV/对象数组/analysis/v1 输入和输出契约保持兼容。
|
|
158
|
+
|
|
159
|
+
## 排名前确认完整候选池
|
|
160
|
+
|
|
161
|
+
`metric query` 和 batch 每项的默认 limit 都是 **50**。`analyze topn --limit` 只是本地每个分区保留的排名数,不能代替上游查询 limit。开始排名或占比前,先明确筛选范围、分组粒度、候选池和预期资源量,显式规划查询 limit/offset,再根据实际返回和权威总量/上限证据确认取数完结。
|
|
162
|
+
|
|
163
|
+
- `rowCount == limit` 或返回量碰到已知后端/卡片上限时,视为可能截断,继续分页/扩大取数窗口或核对权威完结证据;不能直接对前50行宣称各品类 Top1。`rowCount < limit` 也须排除更小的后端上限、查询失败或范围不一致。
|
|
164
|
+
- 单查 query **没有 --offset**,不要编造该参数;可增大显式 limit 后重新取完整窗口,或使用 batch 的 offset/limit。batch 非零 offset 必须显式设置稳定排序,offset+limit 不超过10000;排序同值与跨请求数据变化可能导致重复/漏行,需按唯一键、同一筛选范围和数据一致性核对。分页契约见 [batch-query](metric-batch-query.md)。
|
|
165
|
+
- 例如下面两页仅用于规划和核查;不能直接把任一页送入 topn 后称全量结果。若确认候选池低于10000,可重新用 offset=0、足够的 limit 取完整候选池后加工。若仍超上限,按有依据的互斥筛选范围拆分并核实覆盖,或明确报告完整性未确认。CLI 不自动补抓/拼接分页,也不做业务聚合。
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
[
|
|
169
|
+
{"id":"sales-p0","metricId":"<已确认指标ID>","dimensions":["品类","商品"],"sortAsc":"商品","offset":0,"limit":1000,"valueFormat":"raw"},
|
|
170
|
+
{"id":"sales-p1","metricId":"<已确认指标ID>","dimensions":["品类","商品"],"sortAsc":"商品","offset":1000,"limit":1000,"valueFormat":"raw"}
|
|
171
|
+
]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
排序示例要求“商品”在候选池中唯一且为指标支持字段;不满足时先选择有依据的唯一排序/互斥查询范围。检查每页 status、rowCount、offset/limit 和键覆盖。排名输入必须覆盖每个分区完整候选池;份额计算的各指标还须覆盖相同口径的完整候选池。
|
|
175
|
+
|
|
176
|
+
## 按分区 Top1 后关联同键比率
|
|
177
|
+
|
|
178
|
+
前提:`sales.json` 已覆盖全部“品类+商品”候选,`margin-rate.json` 按相同粒度包含所选商品的毛利率。实际列名从查询结果确认;比率直接关联,不按商品外的粒度猜值。先选销售额 Top1,再以 Top1 为左表、**显式 --join left** 关联;full join 会重新引入未入选商品。
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
guancli analyze topn sales.json --group-by 品类 --value-field 销售额 \
|
|
182
|
+
--limit 1 --rank-field sales_rank -o sales-top1.json
|
|
183
|
+
guancli analyze align --left sales-top1.json --right margin-rate.json \
|
|
184
|
+
--key 品类 --key 商品 --join left --left-prefix selected --right-prefix rate \
|
|
185
|
+
-o sales-top1-with-rate.json
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
输出行集合仍是每品类选中的 Top1,毛利率列为 `rate.毛利率`;缺少同键比率时保留 null,核实缺失原因,不猜0,也无需再用 Node/Python 过滤整池。重复组合键会报错,先核实上游粒度。并列值按原输入顺序取一个,若业务要保留并列需另行确认口径。
|
|
189
|
+
|
|
190
|
+
## 多指标对齐后分别排名与占比
|
|
191
|
+
|
|
192
|
+
前提:销售额与毛利额查询均覆盖相同筛选范围、相同“品类+商品”粒度的完整候选池。这里 full join 用于保留并核查两侧全集;不用于给已截断的 Top1 补列。对齐后的缺失指标保持 null;不把缺失当0或声称口径已完整,确认后再执行排名。
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
guancli analyze align --left sales.json --right gross-profit.json \
|
|
196
|
+
--key 品类 --key 商品 --join full --left-prefix sales --right-prefix profit \
|
|
197
|
+
-o all-metrics.json
|
|
198
|
+
# 核对两侧键集合/缺失值与完整性;两条 topn 都读取尚未截断的 all-metrics.json。
|
|
199
|
+
guancli analyze topn all-metrics.json --group-by 品类 --value-field sales.销售额 \
|
|
200
|
+
--limit 1 --rank-field sales_rank --share-field sales_share -o sales-leaders.json
|
|
201
|
+
guancli analyze topn all-metrics.json --group-by 品类 --value-field profit.毛利额 \
|
|
202
|
+
--limit 1 --rank-field profit_rank --share-field profit_share -o profit-leaders.json
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`sales_share` 的分母是该品类完整候选池的销售额合计,`profit_share` 的分母是同池的毛利额合计。不要把 sales-leaders.json 再用于毛利额排名或全池占比;销售领先与毛利领先可能是不同商品。合计为0时占比为null,负值仍按实际数值求和,业务解释由调用方确认。
|
|
@@ -152,6 +152,7 @@ guancli form delete <subFmId> <subId>
|
|
|
152
152
|
**注意**:
|
|
153
153
|
- 子表 add 内部通过主表 update API 间接完成(后端限制),CLI 自动保留已有子行
|
|
154
154
|
- add 会分页读取已有子行并通过主表 update 全量回写以保留已有行;非并发安全
|
|
155
|
+
- 旧子行查询必须包含有效 `data` 数组、`count` 总数和行标识;缺失、分页不完整或总数变化时停止,不提交全量替换。协议依据为 SurveyEngine `d4f37aca` 的 `DataController.get` / `DataService.getSubData`,短页本身不能证明读取完成。
|
|
155
156
|
- `--stdin` 批量插入部分失败时 CLI 返回非零退出码,summary 中显示成功/失败计数
|
|
156
157
|
|
|
157
158
|
### 典型工作流
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# 请求转发创建与调用辅助
|
|
2
|
+
|
|
3
|
+
用于把第三方或客户内部接口文档转换为观远 BI 请求转发配置,并通过 `guancli gateway create` 创建。产品语义以[请求转发 / API Gateway](https://docs.guandata.com/product/bi/api-gateway)为准。
|
|
4
|
+
|
|
5
|
+
## 从接口文档生成配置
|
|
6
|
+
|
|
7
|
+
先提取并向用户展示配置草案,至少标明每项来自文档的哪一段:
|
|
8
|
+
|
|
9
|
+
- 目标方法、URL、超时时间。
|
|
10
|
+
- Header、Query、Body 入参及必填性。
|
|
11
|
+
- 鉴权方式;需要登录或换 token 时转成前置请求。
|
|
12
|
+
- 前置响应 JSONPath 与主请求 `${PRE_REQ.xxx}` 引用。
|
|
13
|
+
- 网关入口方法、路由识别符、登录要求、用户/用户组、调用方 Host 和日志脱敏 Header。
|
|
14
|
+
- 文档地址与调用说明 `usageMarkdown`。
|
|
15
|
+
|
|
16
|
+
不确定的权限范围、Host 白名单、Secret key 和启用状态必须列为待确认项。不要猜用户 ID、用户组 ID 或把凭据明文放入 JSON。用户确认后再生成配置文件。
|
|
17
|
+
|
|
18
|
+
## JSON 契约
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"basicInfo": {
|
|
23
|
+
"name": "CRM 查询用户",
|
|
24
|
+
"routes": "crm-query-user",
|
|
25
|
+
"gatewayMethod": "GET",
|
|
26
|
+
"targetMethod": "GET",
|
|
27
|
+
"documentUrl": "https://docs.example.com/crm/users",
|
|
28
|
+
"usageMarkdown": "Query: keyword;返回 CRM 用户列表。",
|
|
29
|
+
"enabled": true,
|
|
30
|
+
"loginRequired": true,
|
|
31
|
+
"allowedUsers": [{"id": "user-id"}],
|
|
32
|
+
"allowedUserGroups": [{"id": "group-id"}],
|
|
33
|
+
"targetUrl": "https://crm.example.com/api/users",
|
|
34
|
+
"allowedCallerHosts": ["app.example.com"],
|
|
35
|
+
"maskHeaders": ["Authorization", "Cookie", "X-Auth-Token"]
|
|
36
|
+
},
|
|
37
|
+
"config": {
|
|
38
|
+
"request": {
|
|
39
|
+
"timeoutSeconds": 120,
|
|
40
|
+
"headers": [
|
|
41
|
+
{
|
|
42
|
+
"paramName": "Authorization",
|
|
43
|
+
"paramValueOrExpr": "Bearer ${PRE_REQ.accessToken}",
|
|
44
|
+
"paramDescription": "前置登录返回的 token"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"query": [
|
|
48
|
+
{
|
|
49
|
+
"paramName": "keyword",
|
|
50
|
+
"paramValueOrExpr": "${REQUEST.query.keyword}",
|
|
51
|
+
"paramDescription": "搜索关键词"
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"preRequestList": [
|
|
56
|
+
{
|
|
57
|
+
"name": "获取 CRM Token",
|
|
58
|
+
"requestMethod": "POST",
|
|
59
|
+
"url": "https://crm.example.com/oauth/token",
|
|
60
|
+
"timeoutSeconds": 30,
|
|
61
|
+
"documentUrl": "https://docs.example.com/crm/auth",
|
|
62
|
+
"headers": [{"paramName": "Content-Type", "paramValueOrExpr": "application/json"}],
|
|
63
|
+
"query": [],
|
|
64
|
+
"body": "{\"clientId\":\"${SECRET.crm_client_id}\",\"clientSecret\":\"${SECRET.crm_client_secret}\"}",
|
|
65
|
+
"responseExtractors": [{"name": "accessToken", "jsonPath": "$.accessToken"}]
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
规则:
|
|
73
|
+
|
|
74
|
+
- `routes` 只能包含字母、数字和中划线;创建后不要修改识别符。
|
|
75
|
+
- `gatewayMethod` 只支持 `GET`、`POST`;`targetMethod` 支持 `GET`、`POST`、`PUT`、`DELETE`、`PATCH`。
|
|
76
|
+
- 主请求及前置请求超时为 1–300 秒。
|
|
77
|
+
- `allowedUsers`、`allowedUserGroups` 传资源 ID,不传名称代替 ID。登录开启但两者为空时,所有已登录用户可访问。
|
|
78
|
+
- Header 和 Query 只有显式配置的参数才转发;Body 由调用方整体透传并执行占位符替换。
|
|
79
|
+
- Header 和 Query 配置通过 `required: true|false` 保留原接口的必填性;省略时按可选处理。`gateway get` 只对必填入参生成缺失检查,可选 Query/Header 未传时不会被序列化为 `undefined`。
|
|
80
|
+
- CLI 会在输出 dry-run 计划前检查 Header、Query、前置请求 Body、目标/前置请求 URL 的 query 与 userinfo。`Authorization`、`token`、`password`、`AK/SK`、`API Key`、`client secret` 等敏感参数只能由 `${SECRET.xxx}` 或 `${PRE_REQ.xxx}` 服务端引用组成;明文及 `${REQUEST.xxx}` 会被拒绝,且不会回显配置。自定义 Header 固定值默认拒绝;只有确认为公开非凭据值时才在该参数上显式设置 `allowPlaintext: true`,例如 `X-API-Version: 2026-09`、`X-Client-Type: superapp`、`Prefer: return=representation`。敏感 Header 名或 Bearer/Basic/API-key/JWT 等凭据形式不允许用 `allowPlaintext` 绕过。`allowPlaintext` 只是 CLI 本地确认字段,dry-run 的 `request` 和真实 POST body 都会在提交投影中剔除它,两者保持一致。
|
|
81
|
+
- JSON Body 任意层级出现重复字段时会在 dry-run 和真实创建前直接拒绝,避免校验器只检查最后一个值、却把未规范化的原始 Body 提交给 BI。
|
|
82
|
+
- `enabled`、`loginRequired` 省略时服务端默认 `true`,配置草案中仍应显式写出,便于用户确认。
|
|
83
|
+
|
|
84
|
+
常用占位符:`${REQUEST.path.n}`、`${REQUEST.query.xxx}`、`${REQUEST.header.xxx}`、`${REQUEST.body.xxx}`、`${CURRENT_USER.xxx}`、`${PRE_REQ.xxx}`、`${SECRET.xxx}`、`${SYSTEM.xxx}`。
|
|
85
|
+
|
|
86
|
+
## 创建流程
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
guancli auth status
|
|
90
|
+
guancli gateway create ./gateway.json --dry-run
|
|
91
|
+
guancli gateway create ./gateway.json
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
先检查 dry-run 输出中的目标地址、权限、Secret key、参数映射和 `enabled`。真实创建是外部写操作;只有用户确认草案后才执行。dry-run 计划和创建结果均使用 `schemaVersion: "1.0"`;创建成功返回 `id`、`name`、`routeCode`、`gatewayPath` 和 `enabled`。
|
|
95
|
+
|
|
96
|
+
服务端仍会最终校验权限、商业授权、路由重名、用户/用户组、Secret 与配置合法性。创建端点为 `POST /api/gateway/manage/routes`,权限资源为 `GATEWAY_ROUTE.UPDATE`;自 2026-09-01 起还需要超级应用商业授权。
|
|
97
|
+
|
|
98
|
+
## 查找路由并读取调用契约
|
|
99
|
+
|
|
100
|
+
当用户只给出自然语言需求(例如“调用 CRM 查询客户信息接口”),不要要求用户预先提供识别符,也不要从创建文件或历史对话猜测:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
guancli gateway search CRM --enabled --limit 20
|
|
104
|
+
guancli gateway get 42
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
- `search [keyword]` 调用 `POST /api/gateway/manage/routes/query`,关键词由服务端匹配名称或识别符;支持 `--enabled=true|false`、`--offset`、`--limit`。输出为 `schemaVersion: "1.0"` 的脱敏摘要,包含路由 ID、名称、识别符、BI 网关路径、方法、启用状态、访问约束、文档地址和业务说明。
|
|
108
|
+
- 查询结果只代表当前分页。`total` 大于 `items` 数量时仍有后续页;无候选时缩短关键词或省略关键词继续查询。多个候选的名称、说明和方法不足以唯一判断时,列出候选并请用户确认。
|
|
109
|
+
- `get <id>` 调用 `GET /api/gateway/manage/routes/{id}`,默认把后端详情投影成 `schemaVersion: "1.0"` 的稳定调用契约:`gatewayUrlTemplate`、网关方法、追加路径占位符、Query/Header/Body 输入映射、是否必填、访问约束、原始文档/业务说明、CLI 与 SuperApp 示例。
|
|
110
|
+
- 默认输出不包含第三方目标 URL、前置请求 URL 或 `${SECRET.xxx}` 引用。`--raw` 只用于管理员诊断,会原样显示后端详情;不要把 raw 输出放进对话、日志或 SuperApp 代码。
|
|
111
|
+
|
|
112
|
+
管理查询需要 `GATEWAY_ROUTE.READ`。使用 PAT 时,还需 BI 环境已提供“请求转发”权限点,并在创建 PAT 时选择对应的 `read` / `update` 权限;已有 PAT 不会自动增加新权限。CLI 的本地契约测试只能验证请求构造和字段投影;最终权限、资源存在性和当前配置仍由 BI 服务端裁决。
|
|
113
|
+
|
|
114
|
+
## 生成 SuperApp 调用
|
|
115
|
+
|
|
116
|
+
必须先以 `gateway get` 的返回值为事实源。生成前逐项检查:
|
|
117
|
+
|
|
118
|
+
- `route.enabled` 必须为 `true`;否则提示管理员启用。
|
|
119
|
+
- 调用方法必须等于 `invocation.method`,不可用目标请求方法代替网关请求方法。
|
|
120
|
+
- 按 `appendPathPlaceholders` 顺序追加并 URL 编码路径;`${REQUEST.path.1}` 对应第一段。若配置引用 `${REQUEST.path.3}`,前两段也必须提供,即使第二段没有被目标模板直接引用。
|
|
121
|
+
- 为所有 `inputMappings[].required=true` 的 Query、Header、Body 输入组装值;缺少时在调用前报出具体参数名。
|
|
122
|
+
- POST 路由的 `bodyMode=passthrough` 表示调用方提供请求体时应原样透传;`bodyRequired=false` 只表示请求体可省略,不得据此从生成代码中删除 body 支持。字符串请求体直接发送,对象请求体再做 JSON 序列化。
|
|
123
|
+
- 响应保持上游语义:204/205 返回 `null`;JSON Content-Type(`application/json` 或 `+json`)调用 `json()`;文本、XML、JavaScript 和表单响应调用 `text()`;其余文件或二进制响应调用 `blob()`。不得无条件执行 `response.json()`。
|
|
124
|
+
- `loginRequired`、`allowedUsers`、`allowedUserGroups` 和 `allowedCallerHosts` 是访问约束。当前用户或来源不满足时提示申请权限或调整白名单。
|
|
125
|
+
- 代码只调用 `/api/gateway/routes/{routeCode}`,不得出现目标服务 URL、前置请求 URL 或敏感凭据。
|
|
126
|
+
|
|
127
|
+
示例:
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
const response = await fetch(
|
|
131
|
+
`/api/gateway/routes/crm-query-user?keyword=${encodeURIComponent(keyword)}`,
|
|
132
|
+
{ method: "GET", credentials: "include" },
|
|
133
|
+
);
|
|
134
|
+
if (!response.ok) {
|
|
135
|
+
throw new Error(`请求转发调用失败:${response.status}`);
|
|
136
|
+
}
|
|
137
|
+
const data = await response.json();
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
追加路径按顺序映射为 `${REQUEST.path.1}`、`${REQUEST.path.2}`。CLI 调试调用示例:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
guancli gateway invoke crm-query-user --method GET --query keyword=张三 --verbose
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
出现未授权、路由停用、方法不匹配或参数缺失时,结合返回状态和错误体说明具体修复动作,不要改为绕过网关直连目标服务。
|
|
147
|
+
|
|
148
|
+
`gateway invoke` 无论成功或失败都会先输出目标响应体;`--verbose` 还会输出状态码和脱敏响应头。HTTP 4xx/5xx 等非 2xx 响应在完成输出后返回错误,进程退出码非零,脚本必须同时保留输出并检查退出码。
|
|
@@ -80,3 +80,5 @@ lite/kit 执行会在 replay 轮汇集独立请求;只读请求可标为 paral
|
|
|
80
80
|
- 只观察到指标引用了某个旧 ID,而没有对相同维度键的实际值做比较。
|
|
81
81
|
|
|
82
82
|
最终结果至少区分 `same`、`different`、`query_error`、`inconclusive_truncated`。汇报 `different` 时给出第一个真正相同维度键下的值差异;汇报 `inconclusive_truncated` 时给出双方行数、限制参数和建议的分片方式。
|
|
83
|
+
|
|
84
|
+
`guancli analyze` 可直接消费单查 inline/file 与 batch 成功项;batch 使用 `--result-id`,align 右侧使用 `--right-result-id`。查询→规范化→对齐→计算→TopN 完整示例见 [本地分析原语](analysis-primitives.md)。计算选择 raw/both,both 读取 raw rows;是否使用此加工方式由调用方决定。
|
|
@@ -87,17 +87,22 @@ guancli metric search [keyword] [flags]
|
|
|
87
87
|
- `--with-detail` 需要组合多个接口的结果,因此不兼容 `--raw`、`-f csv` 和 `-f excel`。
|
|
88
88
|
- `[keyword]` 走旧指标名称搜索接口;`--fuzzy` 走新的统一模糊搜索接口,二者不能同时使用。
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
- 如果单批搜索无候选,立即结束本轮候选发现。回答必须包含:`attempted_keywords`、`search_scope`、无结果原因“当前可见指标的名称、业务口径和可搜索业务属性均未命中”,以及 `stop_reason=no_candidate_within_budget`。
|
|
97
|
-
- 只有请求本身因可识别的认证、网络或服务错误失败时,才按对应错误恢复流程处理;业务无命中不是重试理由。
|
|
98
|
-
- 不缓存、不持久化、也不跨请求复用“未找到指标”的结论。每个新请求都必须基于当时的指标可见性、权限和指标内容重新判断。
|
|
90
|
+
模糊搜索输入与结果边界:
|
|
91
|
+
|
|
92
|
+
- 每项关键词按原文匹配,不自动拆词,也不把型号、客户等实体解析为取数筛选。多个关键词使用重复参数,例如 `--fuzzy "毛利率" --fuzzy "标准成本"`,彼此为 OR。
|
|
93
|
+
- 后端硬上限是 10 个关键词,每个关键词最长 100 个字符;这是单次请求的接口限制,不是业务发现轮数或停止条件。
|
|
94
|
+
- 空结果只表示本次关键词在当前可见范围未命中,不证明指标不存在。
|
|
95
|
+
- 搜索结果受当前权限、范围和指标内容影响,不作为跨请求有效的“指标不存在”证明。
|
|
99
96
|
- 已知指标主题 ID 时用 `-d <metric_topic_id>` 缩小 `search_scope`;未知主题时要说明搜索覆盖当前用户可见的全部指标主题。一次 CLI 调用在未知主题时可能内部扫描多个主题,不能把它表述成一次 HTTP 请求。
|
|
100
97
|
|
|
98
|
+
候选发现预算与纠错重查:
|
|
99
|
+
|
|
100
|
+
- 首轮保留用户原词,合并必要同义词后批量搜索,默认最多 5 个关键词;先 trim、合并连续空白,并按大小写不敏感语义去重。
|
|
101
|
+
- 禁止无效重复:相同关键词和范围的重复请求、仅换序、轻微改写或取已搜关键词子集,都不构成新的搜索依据。已有候选先核验,不因候选不唯一就重复搜索。
|
|
102
|
+
- 默认一轮;仅发现具体错误或新线索时,最多追加一轮纠错搜索。例如误把型号当指标名、选错指标主题,或候选详情提供了此前未知的业务名称。重查前说明依据、原参数的问题及本次修正;单纯“没找到”或猜测更多同义词不是纠错依据。
|
|
103
|
+
- 没有明确纠错依据,或纠错一轮后仍不能确定时停止,说明已尝试的关键词、搜索范围及未能确认的原因;必要时请用户补充信息,不断言指标不存在。用户补充新信息后重新判断,不跨请求复用“未找到”的结论。
|
|
104
|
+
- 认证、网络或服务错误按对应恢复流程处理,不将业务无命中当成服务错误重试。
|
|
105
|
+
|
|
101
106
|
回答要求:
|
|
102
107
|
|
|
103
108
|
- 必须逐条返回命中的指标,至少包含指标 ID、指标名称、状态、类型。
|
|
@@ -367,7 +372,7 @@ CLI 会把条件树确定性展开为“组内 AND、组间 OR”的查询计划
|
|
|
367
372
|
|
|
368
373
|
### metric tree
|
|
369
374
|
|
|
370
|
-
|
|
375
|
+
获取指标目录树。默认输出树形结构,最外层展示指标主题。`-d / --dir-id <topic-id>` 仅读取所选主题的目录树:保留原主题列表的权限过滤和原始输出形状,不读取其他主题的目录树;主题不存在或不在当前身份的主题列表中时返回空结果。
|
|
371
376
|
|
|
372
377
|
```bash
|
|
373
378
|
guancli metric tree [flags]
|
|
@@ -380,6 +385,7 @@ guancli metric tree --profile default
|
|
|
380
385
|
guancli metric tree --profile default --brief
|
|
381
386
|
guancli metric tree --profile default -f json
|
|
382
387
|
guancli metric tree --profile default --raw
|
|
388
|
+
guancli metric tree -d <topic-id> --profile default --raw
|
|
383
389
|
```
|
|
384
390
|
|
|
385
391
|
> 指标创建、编辑、删除、指标主题/目录创建、公共维度管理、Excel 标准化已迁移到 `guanmetric`。
|
|
@@ -518,6 +524,15 @@ guancli metric_attribution query <metric_tree_id> --profile test43 --target dim
|
|
|
518
524
|
|
|
519
525
|
### 查询结果消费
|
|
520
526
|
|
|
527
|
+
`guancli analyze` 支持规范化、对齐、四则运算、TopN/占比,可直接读取 query envelope:
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
guancli analyze normalize query-envelope.json -o normalized.json
|
|
531
|
+
guancli analyze normalize batch.json --result-id current -o current.json
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
batch 必须选择 success 的 raw/both 项;both 使用 raw rows。batch 使用 `--result-id`,align 右侧使用 `--right-result-id`。完整查询→加工链路见 [本地分析原语](analysis-primitives.md)。以下为 Python/jq 消费示例;使用哪种加工方式由调用方决定。
|
|
535
|
+
|
|
521
536
|
机器查询统一用 `-f json`。`query` 的 `data` 和文件载荷都是行对象数组;search 的 `data` 是指标数组,get/tree 的 `data` 是单个对象。`rowCount` 属于 stdout envelope,不能从行数组读取。query 的 `columns` 保留真实业务列名,可以是中文;search/get 的 `id/name/dimensions` 是 canonical 英文字段。
|
|
522
537
|
|
|
523
538
|
下面示例在 Skill 目录执行;先确认 CLI 成功,再解析 stdout,stderr 单独保存:
|
|
@@ -49,6 +49,12 @@ guancli metric query <metric_id> --profile <profile> <查询参数> --explain-re
|
|
|
49
49
|
|
|
50
50
|
`--dry-run` 和 `--explain-requests` 是两个互斥的计划模式,不能同时传。
|
|
51
51
|
|
|
52
|
+
### 计算字段维度与排序
|
|
53
|
+
|
|
54
|
+
指标详情的适用维度、时间维度或日期子维度若带有 `formula`,`--dim` 和 `--sort-asc/--sort-desc` 使用字段名即可;CLI 会把公式随维度和排序对象送入基础卡片查询的 `zoneData.row/sorting`,或泛化查询的 `dimensions/sorting`。只传排序、不传 `--dim` 时也需要保留公式。`--percentage-dim`、`--rank-dim` 和时间类高级计算使用字段 ID,筛选由服务端按字段 ID 解析计算字段;`--columns` 只在客户端处理。
|
|
55
|
+
|
|
56
|
+
排查计算字段时先看 `metric get <id> --raw` 中字段的 `fdId/fdType/formula`,再用同参数的 `--explain-requests -f json` 检查实际请求中的维度与排序对象。`--dry-run` 的 `resolvedDimensions` 只展示部分字段,不足以确认公式是否进入最终请求。请求不再报 `UNRESOLVED_COLUMN` 仍不代表结果正确:若公式返回整数却把字段声明为 `DATE`,日期筛选可能报 `DATATYPE_MISMATCH`,分组值也可能异常或为空;应对照 `ds get --raw` 与 `ds preview` 核查字段类型和实际值。
|
|
57
|
+
|
|
52
58
|
## 3. 每种模式的最小合法命令
|
|
53
59
|
|
|
54
60
|
```bash
|
|
@@ -13,6 +13,8 @@ guancli ds execute-sql -inputs <ds_id> --sql-file - < query.sql # 从 stdin 读
|
|
|
13
13
|
`execute-sql` 的旧版 public-api fallback 不支持 disable-cache;`--limit` 在非 raw 输出渲染前本地截断,`--raw` 保持后端原始响应。
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
程序比对结果时用 `-f json --typed`:NULL 输出 `null`,数值列(按后端 `columns[].fdType`)输出 JSON 数字(原样保留后端的数字文本,长整数和小数位不丢)。不加 `--typed` 的 `-f json` 保持旧格式:所有值都是字符串、NULL 为空串 `""`,分不清 NULL、空串与数字。
|
|
17
|
+
|
|
16
18
|
`--sql` 与 `--sql-file` 二选一。SQL 较长、包含多层引号或由模型生成时,优先写入 `.sql` 文件再传 `--sql-file`;传 `--sql-file -` 时从 stdin 读取,不会把终端中的普通空输入当作 SQL。
|
|
17
19
|
|
|
18
20
|
数据集 ID (dsId) 可通过 `ds tree` 或 `ds search` 获取。
|