@guandata/guancli 1.0.51 → 1.0.52

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,14 @@
1
1
  # Changelog
2
2
 
3
+ ## @guandata/guancli 1.0.52 - 2026-08-20
4
+
5
+ - 新增资源全局搜索与资源 URL 获取能力,便于快速定位并访问 BI 资源。
6
+ - `metric search` 支持返回指标详情,并优化查询加速命中优先级说明、兼容性探测及请求预算控制。
7
+ - 修复 `form query --filter` 被忽略及多类筛选条件误切、字段元信息丢失和列名歧义问题,提升筛选准确性与错误可见性。
8
+ - 文件上传超时支持通过 `GUANCLI_UPLOAD_TIMEOUT` 配置,适配大文件或较慢网络环境。
9
+ - 优化交互式登录和并发自动重登恢复机制,移除废弃的 AdminToken 认证链路。
10
+ - 改进 npm 自动安装 Skill 的反馈、删除确认及 Windows CLI 兼容性。
11
+
3
12
  ## @guandata/guancli 1.0.51 - 2026-08-13
4
13
 
5
14
  - 优化指标查询结果的排序逻辑,支持按查询优先级更合理地返回指标,提升指标检索与选择体验。
package/README.md CHANGED
@@ -5,10 +5,10 @@
5
5
  ## 安装
6
6
 
7
7
  ```bash
8
- npm install -g @guandata/guancli
8
+ npm install -g --foreground-scripts @guandata/guancli
9
9
  ```
10
10
 
11
- > 全局安装/升级时会通过 postinstall 自动执行一次 `guancli install-skill` 刷新 AI skill;CI 等无需 skill 的环境可设 `GUAN_SKIP_INSTALL_SKILL=1` 跳过。
11
+ > 全局安装/升级时会通过 postinstall 自动执行一次 `guancli install-skill` 刷新 AI skill。`--foreground-scripts` 用于显示明确的成功、失败或跳过结果;失败时按提示手动运行 `guancli install-skill`。CI 等无需 skill 的环境可设 `GUAN_SKIP_INSTALL_SKILL=1` 跳过。
12
12
 
13
13
  也可以直接使用:
14
14
 
@@ -41,6 +41,13 @@ guancli chatbi query --theme-name "经营主题" --message "最近30天营业收
41
41
 
42
42
  ## 版本更新
43
43
 
44
+ ### @guandata/guancli 1.0.52
45
+
46
+ - 新增资源全局搜索与资源 URL 获取能力,定位和访问 BI 资源更便捷。
47
+ - 指标搜索可返回指标详情,并优化登录、自动重登和查询稳定性。
48
+ - 修复表单与卡片筛选条件被忽略、误切或字段信息丢失等问题。
49
+ - 文件上传超时可通过 `GUANCLI_UPLOAD_TIMEOUT` 配置。
50
+
44
51
  ### @guandata/guancli 1.0.51
45
52
 
46
53
  - 指标查询结果会按查询优先级合理排序,指标检索与选择更准确。
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ const { spawnSync } = require("child_process");
4
+
5
+ const SANITIZED_MARKER = "GUAN_INSTALL_ENV_SANITIZED";
6
+ const SAFE_DELETE_TARGET = String.raw`(?:"(?:[^"]*[\\/])?genie-safe-delete\.cjs"|'(?:[^']*[\\/])?genie-safe-delete\.cjs'|(?:[^\s"']*[\\/])?genie-safe-delete\.cjs)`;
7
+
8
+ function envKey(env, expected) {
9
+ return Object.keys(env).find((key) => key.toLowerCase() === expected.toLowerCase());
10
+ }
11
+
12
+ function stripWorkBuddySafeDelete(nodeOptions) {
13
+ const pattern = new RegExp(
14
+ String.raw`(^|\s)(?:--require|-r)(?:=|\s+)${SAFE_DELETE_TARGET}(?=\s|$)(?:\s+|$)`,
15
+ "gi"
16
+ );
17
+ let removed = false;
18
+ const value = String(nodeOptions || "").replace(pattern, (_, prefix) => {
19
+ removed = true;
20
+ return prefix ? " " : "";
21
+ }).trim();
22
+ return { value, removed };
23
+ }
24
+
25
+ function hasWorkBuddySafeDelete(env = process.env) {
26
+ const key = envKey(env, "NODE_OPTIONS");
27
+ return Boolean(key && stripWorkBuddySafeDelete(env[key]).removed);
28
+ }
29
+
30
+ function createInstallChildEnv(env = process.env) {
31
+ const childEnv = { ...env };
32
+ for (const key of Object.keys(childEnv)) {
33
+ if (key.toLowerCase() === "npm_config_global") {
34
+ delete childEnv[key];
35
+ }
36
+ }
37
+
38
+ const nodeOptionsKey = envKey(childEnv, "NODE_OPTIONS");
39
+ if (nodeOptionsKey) {
40
+ const cleaned = stripWorkBuddySafeDelete(childEnv[nodeOptionsKey]);
41
+ if (cleaned.removed) {
42
+ if (cleaned.value) childEnv[nodeOptionsKey] = cleaned.value;
43
+ else delete childEnv[nodeOptionsKey];
44
+ childEnv[SANITIZED_MARKER] = "1";
45
+ }
46
+ }
47
+ return childEnv;
48
+ }
49
+
50
+ function reexecInstallCommand(scriptPath, args, options = {}) {
51
+ const env = options.env || process.env;
52
+ if (env[SANITIZED_MARKER] === "1" || !hasWorkBuddySafeDelete(env)) {
53
+ return false;
54
+ }
55
+
56
+ const spawn = options.spawn || spawnSync;
57
+ const exit = options.exit || process.exit;
58
+ const nodePath = options.nodePath || process.execPath;
59
+ const result = spawn(nodePath, [scriptPath, ...args], {
60
+ stdio: "inherit",
61
+ env: createInstallChildEnv(env),
62
+ shell: false,
63
+ });
64
+ if (result.error) throw result.error;
65
+ exit(result.status == null ? 1 : result.status);
66
+ return true;
67
+ }
68
+
69
+ module.exports = {
70
+ createInstallChildEnv,
71
+ hasWorkBuddySafeDelete,
72
+ reexecInstallCommand,
73
+ };
@@ -41,18 +41,21 @@ function main() {
41
41
  );
42
42
  if (result.error || result.status !== 0) {
43
43
  console.warn(
44
- `[${CLI_NAME}] postinstall: automatic skill install did not complete` +
44
+ `[${CLI_NAME}] postinstall: AI skill update FAILED` +
45
45
  (result.error ? ` (${result.error.message})` : ` (exit ${result.status})`) +
46
46
  `; run \`${CLI_NAME} install-skill\` manually to refresh SKILL.md.`
47
47
  );
48
+ return;
48
49
  }
50
+ console.log(`[${CLI_NAME}] postinstall: AI skill updated successfully.`);
49
51
  }
50
52
 
51
53
  try {
52
54
  main();
53
55
  } catch (err) {
54
56
  console.warn(
55
- `[${CLI_NAME}] postinstall: ${err.message}; run \`${CLI_NAME} install-skill\` manually.`
57
+ `[${CLI_NAME}] postinstall: AI skill update FAILED (${err.message}); ` +
58
+ `run \`${CLI_NAME} install-skill\` manually.`
56
59
  );
57
60
  }
58
61
  process.exit(0);
package/bin/run.js CHANGED
@@ -6,6 +6,7 @@ const { execFileSync, execSync, spawnSync } = require("child_process");
6
6
  const path = require("path");
7
7
  const fs = require("fs");
8
8
  const os = require("os");
9
+ const { createInstallChildEnv, reexecInstallCommand } = require("./install-env");
9
10
 
10
11
  const PLATFORM_MAP = {
11
12
  "darwin-arm64": "guancli-darwin-arm64",
@@ -111,6 +112,7 @@ function resolveNpxInvocation() {
111
112
  }
112
113
 
113
114
  if (process.argv[2] === "install-skill") {
115
+ reexecInstallCommand(__filename, process.argv.slice(2));
114
116
  const pkgRoot = path.join(__dirname, "..");
115
117
  const extraArgs = process.argv.slice(3);
116
118
  const args = [
@@ -128,8 +130,11 @@ if (process.argv[2] === "install-skill") {
128
130
  console.log("Installing guancli to AI coding assistants...");
129
131
  const npxInvocation = resolveNpxInvocation();
130
132
  const result = spawnSync(npxInvocation.command, [...npxInvocation.argsPrefix, ...args], {
133
+ // Avoid leaking project-only Agent markers (for example PromptScript) from
134
+ // the caller's cwd into this global installation.
135
+ cwd: pkgRoot,
131
136
  stdio: "inherit",
132
- env: process.env,
137
+ env: createInstallChildEnv(process.env),
133
138
  shell: false,
134
139
  });
135
140
  if (result.error) throw result.error;
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.51",
3
+ "version": "1.0.52",
4
4
  "description": "观远 BI 命令行工具 - 通过 API 操作 ETL、数据集、页面、表单等资源,并提供 ChatBI 问数/洞察能力",
5
5
  "bin": {
6
6
  "guancli": "bin/run.js"
@@ -38,7 +38,7 @@
38
38
  "node": ">=14"
39
39
  },
40
40
  "publishConfig": {
41
- "access": "public",
42
- "registry": "https://registry.npmjs.org/"
41
+ "registry": "https://registry.npmjs.org/",
42
+ "access": "public"
43
43
  }
44
44
  }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: guancli
3
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 模板项目”时,也要使用这个 skill,并引导使用 `guancli app create`。即使用户只说"看一下这个 page""贴一下这个 ETL 的 SQL""搜个叫 X 的数据集""这个数据集长啥样""页面卡片用了哪些 ds""帮我查这个指标""生成指标泛化查询命令""帮我创建一个超级应用",也要触发。它直接调用 BI HTTP API 拉数据并整理成 AI 友好的中文结论,定位是 BI 查询分析 + 表单填报 CRUD + 指标查询分析 + SuperApp 模板项目创建。创建/编辑/删除指标、指标主题、指标目录或公共维度走 guanmetric;修改 ETL 走 guanetl;新建/改 Card/Page 走 guanvis;数据源/数据集 CRUD/增量/调度走 guands;页面 PNG 视觉验证走 guanvis screenshot。若用户希望直接分析 BI 项目而不是手工点页面,或希望直接通过 ChatBI 进行主题问数/洞察分析,也应优先使用这个 skill。
4
- compatibility: Requires Node.js 14+. Install via npm install -g @guandata/guancli.
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
 
7
7
  # guancli
@@ -69,11 +69,25 @@ guancli page tree --max-depth 2
69
69
  guancli etl search 关键词
70
70
  guancli ds search 关键词
71
71
  guancli page search 关键词
72
+ guancli search 资源名 --limit 50 --offset 0
72
73
  guancli etl get <resource_id>
73
74
  guancli ds get <resource_id>
74
75
  guancli ds get <resource_id> --brief
75
76
  guancli ds get <resource_id> --assoc
76
77
  guancli page get <resource_id>
78
+ guancli url page <page_id>
79
+ guancli url card <cd_id> --page-id <page_id>
80
+ # 卡片 Web URL 格式为 /page/<page_id>?anchor=<card_id>
81
+ guancli url ds <ds_id> # 自动反查父目录并生成数据集详情页 URL
82
+ guancli url ds <ds_id> --parent-id <dataset_dir_id>
83
+ guancli url ds-dir <dataset_dir_id> # 数据集目录 URL
84
+ guancli url etl <etl_id>
85
+ guancli url etl <etl_id> --parent-id <parent_dir_id> # 通常无需手填,CLI 会从 ETL 详情自动获取父目录;自动失败时再传
86
+ guancli url metric-dir <metric_dir_id> # 自动反查指标主题并生成指标目录 URL
87
+ guancli url metric-dir <metric_dir_id> --project-id <metric_project_id>
88
+ # 指标目录 Web URL 格式为 /metrics-store/project/<metric_project_id>/<metric_dir_id>
89
+ # 数据集详情 Web URL 格式为 /data-center/data-sets/<dataset_dir_id>/<ds_id>/details/overview?limit=50
90
+ # 数据集目录 Web URL 格式为 /data-center/data-sets/<dataset_dir_id>
77
91
  guancli ds preview <ds_id> --limit 20
78
92
  guancli card get <cd_id>
79
93
  guancli card preview <cd_id> --value-format raw -f csv
@@ -89,10 +103,25 @@ guancli insight card <cd_id> --page-id <page_id>
89
103
 
90
104
  详细筛选、输出、动态参数和复杂报表 Pro 行为见 `references/preview-and-output.md`。
91
105
 
106
+ ## Form 关键规则
107
+
108
+ - `form query --filter` 在**服务端**执行,格式 `"列名 操作符 [值]"`,可重复;多条件默认
109
+ `AND`,用 `--combine-type OR` 改成 `OR`。操作符可用性取决于字段控件类型:比较和区间
110
+ 操作符(`GT`/`GE`/`LT`/`LE`/`BT` 系列)只支持 `NUMBER` 和 `DATE_TIME`,
111
+ `CONTAIN_ALL`/`CONTAIN_ANY` 只支持多选字段,`IN` 只支持文本类字段。先用
112
+ `form schema <fmId>` 确认字段的 `type` 再选操作符;用错类型会直接报错。
113
+ - **不支持 `STARTSWITH` / `ENDSWITH`**(后端无实现),请用 `CONTAINS`(语义更宽,匹配任意
114
+ 位置的子串)。
115
+ - `form query --sort-asc/--sort-desc` **只对当前页取回的行排序,不是全表排序**(后端接口不
116
+ 接受排序参数)。**不要把 `--limit N --sort-desc 列` 当作全表 Top-N**——它得到的是「这 N
117
+ 行里最大的」。要回答"最大/最小/前几名"这类问题,先用 `--filter` 把范围收敛到能一次取回,
118
+ 或取回全部数据后再排序;并在结论中说明排序范围。
119
+ - 完整操作符表、子表 ID 映射规则见 `references/form-chatbi.md`。
120
+
92
121
  ## 指标关键规则
93
122
 
94
- - 普通指标数据查询用 `guancli metric query <metric_id>`,可加 `--dim`、`--filter`、排序、列筛选、输出格式等;未指定 `-o/--output` 且结果超过 1000 行时会自动写入 `metric_<metricId>_<timestamp>.<ext>`。回答指标数据查询结果时,必须检查输出中的 `查询加速` summary 或 `_queryAccelerate` 列:命中时明确说明“本次查询命中查询加速”,并列出源指标 ID、加速指标 ID 和优先级;未命中时说明“未命中查询加速”;如果显示 `未知: 后端未返回`,说明当前后端未返回命中 metadata,不能推断是否命中。
95
- - 搜索指标支持两种方式:`guancli metric search <keyword>` 按指标名称模糊搜索;`guancli metric search --fuzzy <keyword>` 同时按指标名称、业务口径、自定义业务属性值做 OR 模糊搜索,可多次传参,命中优先级为 name=1、desc=2、bizAttr=3。`[keyword]` 和 `--fuzzy` 互斥。
123
+ - 普通指标数据查询用 `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)。
124
+ - 搜索指标支持两种方式:`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`。
96
125
  - 回答指标搜索结果时,必须逐条说明“命中的指标”和“命中方式”:至少包含指标 ID、指标名称、命中条件/字段、命中优先级、命中关键词;不要把用户输入默认解释为指标名称精确匹配。如果结果中有“命中条件”“命中优先级”“命中关键词”列,必须原样纳入结论。
97
126
  - 按数据集反查指标用 `guancli metric by-dataset <ds_id>`;如果已知指标主题,可加 `-d <metric_topic_id>` 缩小范围;需要结构化结果时用 `-f json`。
98
127
  - 只要传入 `--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>`。
@@ -166,6 +195,6 @@ guancli --raw insight agent ask <agent_id> --session-id <session_id> --expert-id
166
195
 
167
196
  - 用中文输出,优先给“可执行结论”。
168
197
  - 不只贴原始命令结果,必须做逻辑归纳(按链路/主题)。
169
- - 对 `guancli metric query` 的结果,必须在结论中单独交代查询加速命中情况;如果命中,必须点名具体加速指标 ID,不能只说“用了加速”。
198
+ - 对 `guancli metric query` 的结果,必须在结论中单独交代查询加速命中情况;如果命中,必须点名具体加速指标 ID,并用页面查询顺序表述命中的是第几个加速计划;不能只说“用了加速”。输出里的 `优先级N` 是后端排序权重,数字越大越先尝试,不等同于页面查询顺序。
170
199
  - 涉及时间相关信息时给出明确日期。
171
200
  - 如果用户给的是模糊对象名,先说明你是如何定位到具体资源 ID 的。
@@ -16,7 +16,7 @@ guancli auth login
16
16
  5. 用户名(邮箱)
17
17
  6. 密码
18
18
 
19
- 登录成功后 Token 自动保存在系统标准配置目录下的 `guancli/config.json`。密码方式支持 Token 过期后自动刷新。
19
+ 账号或密码错误时,交互式登录会保留已输入的环境、URL、Domain 和 Login ID,直接提示重新输入密码。登录成功后 Token 自动保存在系统标准配置目录下的 `guancli/config.json`,并自动切换到刚登录的环境;无需再执行 `auth use`。密码方式支持 Token 过期后自动刷新。
20
20
 
21
21
  ### 方式二:直接输入 uIdToken
22
22
 
@@ -45,8 +45,8 @@ guancli auth login --url https://bi.example.com --pat <pat>
45
45
  ### 多环境管理
46
46
 
47
47
  ```bash
48
- guancli auth login --profile staging # 添加 staging 环境
49
- guancli auth login --profile prod --default # 添加 prod 并设为默认
48
+ guancli auth login --profile staging # 添加 staging 并切换为当前环境
49
+ guancli auth login --profile prod # 添加 prod 并切换为当前环境
50
50
  guancli auth list # 列出所有环境
51
51
  guancli auth list --domain demo # 按登录 Domain 筛选
52
52
  guancli auth list --url https://bi.example.com/page/123 # 按页面 URL 筛选
@@ -24,14 +24,67 @@ guancli form schema <fmId> -f json # JSON 格式
24
24
  ```bash
25
25
  guancli form query <fmId> # 查询数据(默认 50 行)
26
26
  guancli form query <fmId> --limit 100 # 指定行数
27
- guancli form query <fmId> --filter "姓名 EQ 张三" # 筛选
28
- guancli form query <fmId> --sort-asc 值 # 按值升序
27
+ guancli form query <fmId> --filter "姓名 EQ 张三" # 筛选(服务端执行)
28
+ guancli form query <fmId> --sort-asc 值 # 按值升序(仅当前页)
29
29
  guancli form query <fmId> --columns "姓名,值" # 只显示指定列
30
30
  guancli form query <fmId> -f json # JSON 格式(rowId 完整)
31
31
  guancli form query <fmId> -f expanded # PG 风格竖排
32
32
  ```
33
33
 
34
- 筛选操作符:`EQ`(等于)、`CONTAINS`(包含)、`STARTSWITH`、`ENDSWITH`、`IS_NULL`、`NOT_NULL`。
34
+ #### 筛选(`--filter`,服务端执行)
35
+
36
+ 格式 `"列名 操作符 [值]"`,可重复指定;多个条件默认 `AND` 组合,用 `--combine-type OR`
37
+ 改成 `OR`。多值操作符(`IN`、`BT` 系列、`CONTAIN_ALL`/`CONTAIN_ANY`,以及多选字段上的 `EQ`)的值用**逗号**
38
+ 分隔;单值操作符的值原样保留其中的空格和逗号(`"姓名 EQ 张 三"` 匹配 `张 三`,`"姓名 EQ a,b"`
39
+ 匹配字面量 `a,b`,都不会被拆开)。
40
+
41
+ 操作符可用性取决于字段的控件类型(用 `form schema` 查看 `type` 列):
42
+
43
+ | 操作符 | 含义 | 适用字段类型 |
44
+ |--------|------|-------------|
45
+ | `EQ` | 等于;多选字段上是**集合相等**(`标签 EQ 红,黄` 匹配恰好选了这两项的行) | 全部 |
46
+ | `NE` | 不等于 | 除多选外 |
47
+ | `IN` | 属于给定值之一(逗号分隔) | 仅文本类(STRING/TEXT/VALUE_CHOOSER…) |
48
+ | `CONTAINS` | 包含子串 | 全部 |
49
+ | `NOT_CONTAINS` | 不包含子串 | 仅 NUMBER / DATE_TIME |
50
+ | `GT` / `GE` / `LT` / `LE` | 大于 / 大于等于 / 小于 / 小于等于 | 仅 NUMBER / DATE_TIME |
51
+ | `BT` | 闭区间 `lo,hi`(lo ≤ x ≤ hi) | 仅 NUMBER / DATE_TIME |
52
+ | `OPEN_BT_OPEN` | 开区间(lo < x < hi) | 仅 NUMBER / DATE_TIME |
53
+ | `OPEN_BT_CLOSE` | 左开右闭(lo < x ≤ hi) | 仅 NUMBER / DATE_TIME |
54
+ | `CLOSE_BT_OPEN` | 左闭右开(lo ≤ x < hi) | 仅 NUMBER / DATE_TIME |
55
+ | `CONTAIN_ALL` | 多选包含全部给定选项 | 仅 MULTI_VALUE_CHOOSER |
56
+ | `CONTAIN_ANY` | 多选包含任一给定选项 | 仅 MULTI_VALUE_CHOOSER |
57
+ | `IS_NULL` | 为空 | 全部 |
58
+ | `NOT_NULL` | 不为空 | 除多选外 |
59
+
60
+ ```bash
61
+ guancli form query <fmId> --filter "姓名 CONTAINS 张" # 子串匹配
62
+ guancli form query <fmId> --filter "金额 BT 100,200" # 数值区间
63
+ guancli form query <fmId> --filter "创建时间 GE 2026-01-01" # 日期比较
64
+ guancli form query <fmId> --filter "标签 CONTAIN_ANY 红,黄" # 多选
65
+ guancli form query <fmId> --filter "状态 IN 待审,已审" # 文本 IN
66
+ guancli form query <fmId> --filter "姓名 EQ 张三" --filter "金额 GT 100" # AND
67
+ guancli form query <fmId> --filter "姓名 EQ 张三" --filter "姓名 EQ 李四" --combine-type OR
68
+ ```
69
+
70
+ 注意:
71
+
72
+ - **不支持 `STARTSWITH` / `ENDSWITH`**(后端无对应实现)。CLI 会直接报错并提示改用
73
+ `CONTAINS`——注意 `CONTAINS` 语义更宽,匹配任意位置的子串。历史版本会把这两个操作符
74
+ 发给后端并**静默返回未筛选的全量数据**。
75
+ - 操作符用在不支持的字段类型上会**直接报错**,不会静默返回未筛选的数据。
76
+ - `DATE_TIME` 的比较由后端按「天」截断(忽略时分秒),`BT` 两端都含端点。
77
+ - 子表(`TABLE` / `MATRIX_TABLE`)字段不能作为筛选列,请直接查询子表。
78
+
79
+ #### 排序(`--sort-asc` / `--sort-desc`)
80
+
81
+ **只对当前页已取回的行排序,不是全表排序。** 后端 `form query` 接口不接受排序参数
82
+ (固定按更新时间倒序返回),排序在 Go 端完成。因此
83
+ `--limit 50 --sort-desc 金额` 得到的是「这 50 行里金额最大的」,**不是**「全表金额最大的
84
+ 50 行」——**不要把它当 Top-N 用**。命中总行数超过本页时 CLI 会在 stderr 输出警告。
85
+
86
+ 需要全表 Top-N 时,先用 `--filter` 把结果收敛到能一次取回的范围,或用 `--limit` /
87
+ `--offset` 取回全部数据后再排序。
35
88
 
36
89
  **重要**:`rowId` 在 auto 表格格式中可能被截断,使用 `-f json` 或 `-f expanded` 获取完整 rowId。
37
90
 
@@ -70,6 +70,9 @@ guancli metric search [keyword] [flags]
70
70
  | --- | --- |
71
71
  | `-d, --dir-id string` | 限定搜索主题 ID |
72
72
  | `--fuzzy strings` | 名称、业务口径、自定义业务属性统一模糊搜索关键词,可多次指定,也支持逗号、中文逗号、顿号分隔;和 `[keyword]` 互斥 |
73
+ | `--offset int` | 搜索结果分页偏移量,默认 `0` |
74
+ | `--limit int` | 搜索结果数量,默认 `0` 表示全部 |
75
+ | `--with-detail` | 同时返回每个命中指标的 `metric get` 详情;默认包含血缘,加 `--brief` 跳过血缘 |
73
76
 
74
77
  `--fuzzy` 语义:
75
78
 
@@ -78,6 +81,10 @@ guancli metric search [keyword] [flags]
78
81
  - 自定义业务属性值统一模糊匹配;后端只匹配启用且可搜索的业务属性。
79
82
  - 结果会在原有指标字段基础上增加命中条件、命中优先级和命中关键词。
80
83
  - 非 `--raw` 输出会额外查询并返回每个指标关联的查询加速摘要,包括查询加速数量和加速指标 ID/优先级/字段摘要。
84
+ - `--with-detail` 会为当前搜索结果中的每个指标补充与 `metric get <metric_id>` 相同的标准化详情;默认终端输出按指标追加详情,`-f json` 则在每条搜索结果的 `指标详情` 中嵌套返回。
85
+ - 默认详情包含血缘;批量搜索只需业务口径、数据集、字段、权限、统计、自定义属性和查询加速等信息时,加 `--brief` 跳过血缘。结果较多时先用 `--limit` 收窄指标数量。
86
+ - `--with-detail` 只补指标详情,不查询指标数据;指标取数仍使用 `metric query`。
87
+ - `--with-detail` 需要组合多个接口的结果,因此不兼容 `--raw`、`-f csv` 和 `-f excel`。
81
88
  - `[keyword]` 走旧指标名称搜索接口;`--fuzzy` 走新的统一模糊搜索接口,二者不能同时使用。
82
89
 
83
90
  回答要求:
@@ -96,6 +103,8 @@ guancli metric search 订购 --profile default -d <metric_topic_id>
96
103
  guancli metric search 订购 --profile default -f json
97
104
  guancli metric search --fuzzy "收入,GMV" --profile default -d <metric_topic_id>
98
105
  guancli metric search --fuzzy 收入 --fuzzy GMV --profile default -f json
106
+ guancli metric search 销售 --profile default --limit 5 --with-detail
107
+ guancli metric search --fuzzy 收入 --profile default --limit 5 --with-detail --brief -f json
99
108
  guancli metric search --fuzzy 订购 --profile default --raw
100
109
  ```
101
110
 
@@ -122,6 +131,8 @@ guancli metric get <metric_id> --profile default --raw
122
131
 
123
132
  查询指标的查询加速配置。后端取数时会按 `acceleratePriority` 从高到低尝试加速指标;只有当查询维度和筛选维度都能被加速指标适用维度覆盖时才会命中。
124
133
 
134
+ `acceleratePriority` 是后端排序权重,数字越大越先尝试;页面上的“查询顺序”是按这个实际尝试顺序重新编号后的展示序号。因此 `acceleratePriority=4` 可能对应页面查询顺序 1。向用户解释命中计划时,优先使用页面查询顺序口径;如需换算,先执行 `metric accelerate list`,按 `acceleratePriority` 倒序排序后编号。
135
+
125
136
  ```bash
126
137
  guancli metric accelerate list <metric_id> [flags]
127
138
  ```
@@ -163,12 +174,14 @@ guancli metric by-dataset <ds_id> --profile default --raw
163
174
 
164
175
  查询指标数据,支持维度、筛选、排序、列筛选和行数限制。泛化查询参数见 `metric-generic-query.md`。
165
176
 
166
- 非 `--raw` 输出会展示本次查询是否命中查询加速:summary 中有 `查询加速`,数据行中有 `_queryAccelerate`。命中时展示源指标 ID、加速指标 ID 和优先级,例如 `metric_xxx->acc_xxx(优先级1)`;未命中时显示 `否`。若后端版本尚未返回查询加速 metadata,则显示 `未知: 后端未返回`。
177
+ 非 `--raw` 输出会展示本次查询是否命中查询加速:summary 中有 `查询加速`,数据行中有 `_queryAccelerate`。命中时展示源指标 ID、加速指标 ID 和后端排序权重,例如 `metric_xxx->acc_xxx(优先级4)`;未命中时显示 `否`。若后端版本尚未返回查询加速 metadata,则显示 `未知: 后端未返回`。
178
+
179
+ 注意:这里的 `优先级N` 是 `acceleratePriority` 原始值,不是页面“查询顺序”。向用户汇报时不要直接说“命中优先级第 N 个”,应在需要时结合 `metric accelerate list` 的完整列表,按 `acceleratePriority` 倒序换算成页面查询顺序。
167
180
 
168
181
  回答要求:
169
182
 
170
183
  - 必须单独说明本次查询加速命中情况。
171
- - 命中时必须明确列出命中的加速指标 ID、对应源指标 ID 和优先级。
184
+ - 命中时必须明确列出命中的加速指标 ID、对应源指标 ID 和页面查询顺序;如果只拿到 `_queryAccelerate` 里的 `优先级N`,需说明这是后端排序权重,数字越大越先尝试。
172
185
  - 未命中时说明未命中查询加速。
173
186
  - 如果是 `未知: 后端未返回`,只能说明后端未返回命中 metadata,不能推断是否命中。
174
187
 
@@ -19,10 +19,14 @@ guancli ds search --limit 500 --offset 500 # 分页扫描数据集
19
19
  guancli ds search --id <dsId> # 按数据集 ID 精确查找并返回单个数据集详情
20
20
  guancli ds search 关键词 --id <dsId> # 按名称 + ID 组合查找
21
21
  guancli page search 关键词 # 搜索页面
22
+ guancli search 资源名 # 全局搜索,默认每种资源类型返回前 50 条
23
+ guancli search 资源名 --limit 100 --offset 100 # 按每种资源类型分页
22
24
  ```
23
25
 
24
26
  `ds search` 默认返回前 500 条,环境数据集较多时用 `--limit` 和 `--offset` 分页扫描;`ds search --id` 会直接按数据集 ID 获取单个数据集详情,`--limit` 和 `--offset` 在 `--id` 模式下忽略。
25
27
 
28
+ `guancli search <资源名>` 调用 `/api/global-search` 并传 `{"keyword":"<资源名>","resourceType":"ALL","isMobile":false,"limit":50,"offset":0}` 做全局搜索,适合资源类型不确定、需要像 MCP `global_search` 一样先定位资源 ID 的场景。`--limit` 和 `--offset` 在 `ALL` 模式下分别作用于每种资源类型;如果某一类型的匹配数超过当前窗口,继续增加 `--offset` 翻页。已知类型时仍优先用 `ds/page/etl search` 获取类型专属字段。
29
+
26
30
  ## 3. 获取详情(含血缘)
27
31
 
28
32
  ```bash
@@ -37,6 +41,25 @@ guancli page get <resource_id> # 页面详情(含卡片列表、血缘
37
41
 
38
42
  **`--assoc` 模式**(仅 `ds get`):在详情末尾追加数据集关联关系摘要,显示关联的 ETL、数据融合等资源。
39
43
 
44
+ ## 4. 获取资源具体 URL
45
+
46
+ ```bash
47
+ guancli url page <page_id> # 仪表板页面前端 URL + API URL
48
+ guancli url card <cd_id> --page-id <page_id> # 卡片所在页面 anchor URL + 卡片 API URL
49
+ guancli url ds <ds_id> # 自动反查父目录并生成数据集详情页 URL
50
+ guancli url ds <ds_id> --parent-id <dataset_dir_id>
51
+ guancli url ds-dir <dataset_dir_id> # 数据集目录 URL
52
+ guancli url etl <etl_or_dir_id> # ETL/数据流基础前端 URL + API URL
53
+ guancli url etl <etl_id> # 普通 ETL 会自动从详情接口获取父目录并生成详情页 URL
54
+ guancli url etl <etl_id> --parent-id <dir_id> # 自动获取失败时手动指定父目录
55
+ guancli url metric-dir <metric_dir_id> # 自动反查指标主题并生成指标目录 URL
56
+ guancli url metric-dir <metric_dir_id> --project-id <metric_project_id>
57
+ guancli url metric-tree <metric_tree_id> # 指标树编辑页面 URL
58
+ guancli -f json url page <page_id> # 结构化输出,便于自动提取 webUrl/apiUrl
59
+ ```
60
+
61
+ `url` 命令读取本地 profile 的 `base_url`。页面 URL 是稳定前端直达链接;卡片没有独立页面,但传 `--page-id` 后会生成 `/page/<pageId>?anchor=<cardId>` 定位具体卡片;数据集会优先读取详情中的 `parentDirId`,自动生成 `/data-center/data-sets/<parentDirId>/<dsId>/details/overview?limit=50`,自动获取失败时再手动传 `--parent-id`;数据集目录使用 `/data-center/data-sets/<dataset_dir_id>`;ETL/数据流会优先读取 ETL 详情中的 `parentDirId`,普通 ETL 自动生成 `/data-center/data-flow/<parentDirId>/<etlId>/details/datasets?limit=50`;详情接口不可用时回退查询 ETL 目录树,目录节点使用 `/data-center/data-flow/<id>`;自动获取失败时再手动传 `--parent-id`。
62
+
40
63
  ## 输出说明
41
64
 
42
65
  - **目录树**:树形结构(├── └──),包含名称和 ID