@wubaoqi/guancopilot 0.0.0-stage → 0.2.0
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/NOTICE.md +17 -0
- package/README.md +146 -2
- package/assets/coreutils.wasm +0 -0
- package/assets/find.wasm +0 -0
- package/assets/guanbi.wasm +4 -0
- package/assets/guancli.wasm +0 -0
- package/assets/guanhelm.wasm +0 -0
- package/assets/jq.wasm +0 -0
- package/assets/openskills.wasm +0 -0
- package/assets/rg.wasm +0 -0
- package/assets/sed.wasm +0 -0
- package/bin/guancopilot +0 -0
- package/bin/guanvm +0 -0
- package/bin/platforms.cjs +6 -0
- package/bin/run.cjs +39 -0
- package/bin/runtime.cjs +44 -0
- package/licenses/Go-LICENSE +27 -0
- package/licenses/browser-_speed-highlight_core-LICENSE +121 -0
- package/licenses/browser-_speed-highlight_core-package.json +14 -0
- package/licenses/browser-dompurify-LICENSE +202 -0
- package/licenses/browser-dompurify-LICENSE-MPL +373 -0
- package/licenses/browser-dompurify-package.json +10 -0
- package/licenses/browser-marked-LICENSE +44 -0
- package/licenses/browser-marked-package.json +10 -0
- package/licenses/coreutils-LICENSE +18 -0
- package/licenses/findutils-LICENSE +18 -0
- package/licenses/github.com_BurntSushi_toml_v1.6.0-COPYING +21 -0
- package/licenses/github.com_dustin_go-humanize_v1.0.1-LICENSE +21 -0
- package/licenses/github.com_google_jsonschema-go_v0.4.3-LICENSE +21 -0
- package/licenses/github.com_google_uuid_v1.6.0-LICENSE +27 -0
- package/licenses/github.com_jackc_pgpassfile_v1.0.0-LICENSE +22 -0
- package/licenses/github.com_jackc_pgservicefile_v0.0.0-20240606120523-5a60cdf6a761-LICENSE +22 -0
- package/licenses/github.com_jackc_pgx_v5_v5.11.0-LICENSE +22 -0
- package/licenses/github.com_jackc_puddle_v2_v2.2.2-LICENSE +22 -0
- package/licenses/github.com_mattn_go-isatty_v0.0.20-LICENSE +9 -0
- package/licenses/github.com_modelcontextprotocol_go-sdk_v1.8.0-LICENSE +216 -0
- package/licenses/github.com_ncruces_go-strftime_v1.0.0-LICENSE +21 -0
- package/licenses/github.com_remyoudompheng_bigfft_v0.0.0-20230129092748-24d4a6f8daec-LICENSE +27 -0
- package/licenses/github.com_santhosh-tekuri_jsonschema_v6_v6.0.3-LICENSE +175 -0
- package/licenses/github.com_segmentio_asm_v1.1.3-LICENSE +21 -0
- package/licenses/github.com_segmentio_encoding_v0.5.4-LICENSE +21 -0
- package/licenses/github.com_tetratelabs_wazero_v1.12.0-LICENSE +201 -0
- package/licenses/github.com_tetratelabs_wazero_v1.12.0-NOTICE +2 -0
- package/licenses/github.com_yosida95_uritemplate_v3_v3.0.2-LICENSE +25 -0
- package/licenses/golang.org_x_image_v0.44.0-LICENSE +27 -0
- package/licenses/golang.org_x_net_v0.58.0-LICENSE +27 -0
- package/licenses/golang.org_x_oauth2_v0.36.0-LICENSE +27 -0
- package/licenses/golang.org_x_sync_v0.22.0-LICENSE +27 -0
- package/licenses/golang.org_x_sys_v0.47.0-LICENSE +27 -0
- package/licenses/golang.org_x_text_v0.41.0-LICENSE +27 -0
- package/licenses/golang.org_x_time_v0.15.0-LICENSE +27 -0
- package/licenses/guanbi-skills-LICENSE +133 -0
- package/licenses/guanbi-skills-LICENSE.README.md +28 -0
- package/licenses/guanbi-skills-LICENSE.zh-CN +82 -0
- package/licenses/jq-COPYING +176 -0
- package/licenses/modernc.org_libc_v1.73.4-LICENSE +27 -0
- package/licenses/modernc.org_libc_v1.73.4-LICENSE-3RD-PARTY.md +305 -0
- package/licenses/modernc.org_mathutil_v1.7.1-LICENSE +27 -0
- package/licenses/modernc.org_memory_v1.11.0-LICENSE +27 -0
- package/licenses/modernc.org_memory_v1.11.0-LICENSE-GO +27 -0
- package/licenses/modernc.org_memory_v1.11.0-LICENSE-LOGO +1 -0
- package/licenses/modernc.org_memory_v1.11.0-LICENSE-MMAP-GO +25 -0
- package/licenses/modernc.org_sqlite_v1.53.0-LICENSE +26 -0
- package/licenses/mvdan.cc_sh_v3_v3.13.1-LICENSE +27 -0
- package/licenses/ripgrep-COPYING +3 -0
- package/licenses/ripgrep-LICENSE-MIT +21 -0
- package/licenses/sed-LICENSE +21 -0
- package/manifest.json +972 -0
- package/package.json +30 -4
- package/plugin/guancopilot.js +193 -0
- package/skills-bundle/.guanvm-skills-bundle +0 -0
- package/skills-bundle/_recipes/dashboard/gates/page_check.js +16 -0
- package/skills-bundle/_recipes/dashboard/gates/report_check.js +4 -0
- package/skills-bundle/_recipes/dashboard/knowledge/01.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/02.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/03.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/04.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/05.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/06.md +1 -0
- package/skills-bundle/_recipes/dashboard/template.json +41 -0
- package/skills-bundle/_recipes/etl/gates/etl_live_check.js +10 -0
- package/skills-bundle/_recipes/etl/gates/etl_report_check.js +3 -0
- package/skills-bundle/_recipes/etl/knowledge/01.md +1 -0
- package/skills-bundle/_recipes/etl/knowledge/02.md +9 -0
- package/skills-bundle/_recipes/etl/knowledge/03.md +1 -0
- package/skills-bundle/_recipes/etl/knowledge/04.md +1 -0
- package/skills-bundle/_recipes/etl/knowledge/05.md +1 -0
- package/skills-bundle/_recipes/etl/template.json +39 -0
- package/skills-bundle/_recipes/hints.json +46 -0
- package/skills-bundle/guancli/.commandface.json +155 -0
- package/skills-bundle/guancli/SKILL.md +342 -0
- package/skills-bundle/guancli/evals/evals.json +156 -0
- package/skills-bundle/guancli/evals/fixtures/metric-candidate-empty-search.json +13 -0
- package/skills-bundle/guancli/evals/fixtures/metric-candidate-prior-request.json +13 -0
- package/skills-bundle/guancli/evals/fixtures/metric-consumption-columns.json +46 -0
- package/skills-bundle/guancli/evals/fixtures/metric-consumption-metadata.json +36 -0
- package/skills-bundle/guancli/evals/fixtures/metric-consumption-query.json +18 -0
- package/skills-bundle/guancli/references/analysis-primitives.md +95 -0
- package/skills-bundle/guancli/references/auth-and-config.md +131 -0
- package/skills-bundle/guancli/references/examples/metric-date-in.json +7 -0
- package/skills-bundle/guancli/references/examples/metric-query-rows.py +83 -0
- package/skills-bundle/guancli/references/examples/metric-query.sh +6 -0
- package/skills-bundle/guancli/references/form-chatbi.md +199 -0
- package/skills-bundle/guancli/references/gateway.md +148 -0
- package/skills-bundle/guancli/references/metric-batch-query.md +82 -0
- package/skills-bundle/guancli/references/metric-commands.md +562 -0
- package/skills-bundle/guancli/references/metric-generic-query.md +215 -0
- package/skills-bundle/guancli/references/metric-json-migration.md +18 -0
- package/skills-bundle/guancli/references/metric-query-recipes.md +358 -0
- package/skills-bundle/guancli/references/preview-and-output.md +192 -0
- package/skills-bundle/guancli/references/resource-query.md +101 -0
- package/skills-bundle/guands/SKILL.md +281 -0
- package/skills-bundle/guands/references/calc-fields-boundaries-and-pitfalls.md +160 -0
- package/skills-bundle/guands/references/command-reference.md +267 -0
- package/skills-bundle/guands/references/incremental-and-schedule.md +157 -0
- package/skills-bundle/guands/references/workflows.md +256 -0
- package/skills-bundle/guanetl/SKILL.md +391 -0
- package/skills-bundle/guanetl/evals/evals.json +41 -0
- package/skills-bundle/guanetl/references/ETL_AI_DEVELOP.md +456 -0
- package/skills-bundle/guanmetric/SKILL.md +144 -0
- package/skills-bundle/guanmetric/evals/evals.json +117 -0
- package/skills-bundle/guanmetric/evals/fixtures/atomic-detail-read-model.json +18 -0
- package/skills-bundle/guanmetric/evals/fixtures/confirmed-template-summary.json +12 -0
- package/skills-bundle/guanmetric/evals/fixtures/create-result-unknown-state.json +13 -0
- package/skills-bundle/guanmetric/evals/forward-eval-2026-09-21.json +62 -0
- package/skills-bundle/guanmetric/references/metric-api-contract-examples.json +690 -0
- package/skills-bundle/guanmetric/references/metric-api-contract.schema.json +349 -0
- package/skills-bundle/guanmetric/references/metric-api-contracts.md +436 -0
- package/skills-bundle/guanmetric/references/metric-atomic-mutation.md +238 -0
- package/skills-bundle/guanmetric/references/metric-batch-status.md +71 -0
- package/skills-bundle/guanmetric/references/metric-business-dictionary-api-contract-examples.json +53 -0
- package/skills-bundle/guanmetric/references/metric-business-dictionary-api-contract.schema.json +26 -0
- package/skills-bundle/guanmetric/references/metric-business-dictionary.md +76 -0
- package/skills-bundle/guanmetric/references/metric-common-fields.md +246 -0
- package/skills-bundle/guanmetric/references/metric-composite-mutation.md +165 -0
- package/skills-bundle/guanmetric/references/metric-delete-mutation.md +70 -0
- package/skills-bundle/guanmetric/references/metric-derived-mutation.md +453 -0
- package/skills-bundle/guanmetric/references/metric-excel-template.md +365 -0
- package/skills-bundle/guanmetric/references/metric-expression-rules.md +146 -0
- package/skills-bundle/guanmetric/references/metric-flow-generate-example.json +79 -0
- package/skills-bundle/guanmetric/references/metric-flow-generate.schema.json +93 -0
- package/skills-bundle/guanmetric/references/metric-flow.md +218 -0
- package/skills-bundle/guanmetric/references/metric-hierarchy-api-contract-examples.json +171 -0
- package/skills-bundle/guanmetric/references/metric-hierarchy-api-contract.schema.json +167 -0
- package/skills-bundle/guanmetric/references/metric-hierarchy-api-contracts.md +193 -0
- package/skills-bundle/guanmetric/references/metric-mutation.md +155 -0
- package/skills-bundle/guanmetric/references/metric-public-dimension-api-contract-examples.json +62 -0
- package/skills-bundle/guanmetric/references/metric-public-dimension-api-contract.schema.json +47 -0
- package/skills-bundle/guanmetric/references/metric-public-dimension.md +155 -0
- package/skills-bundle/guanmetric/references/metric-tree-api-contract-examples.json +277 -0
- package/skills-bundle/guanmetric/references/metric-tree-api-contract.schema.json +263 -0
- package/skills-bundle/guanmetric/references/metric-tree-api-contracts.md +53 -0
- package/skills-bundle/guanmetric/references/metric-tree-mutation.md +500 -0
- package/skills-bundle/guanmetric/references/metric-validation-ownership.md +74 -0
- package/skills-bundle/guanvis/SKILL.md +333 -0
- package/skills-bundle/guanvis/evals/china_map/card_01_basic_map.js +13 -0
- package/skills-bundle/guanvis/evals/china_map/card_02_world_map.js +10 -0
- package/skills-bundle/guanvis/evals/china_map/card_03_point_map.js +12 -0
- package/skills-bundle/guanvis/evals/china_map/page.js +10 -0
- package/skills-bundle/guanvis/evals/china_map/schema.js +10 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/README.md +30 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/card_01_comparative_mvp.js +72 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/page.js +6 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/schema.js +22 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/verify_default_roundtrip.sh +92 -0
- package/skills-bundle/guanvis/evals/complex_report_pro/card_01_monthly.js +63 -0
- package/skills-bundle/guanvis/evals/complex_report_pro/page.js +6 -0
- package/skills-bundle/guanvis/evals/complex_report_pro/schema.js +6 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/card_01_bar.js +13 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/card_02_pie.js +13 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/charts/bar.js +11 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/charts/pie.js +15 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/page.js +5 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/schema.js +9 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/card_01_level_nodes.js +19 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.css +51 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.html +1 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.js +28 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/page.js +5 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/schema.js +7 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/card_01_dynamic_dataset.js +20 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/card_02_dynamic_metric_chart.js +16 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/metrics.js +19 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/page.js +9 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/schema.js +7 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/verify_default_roundtrip.sh +137 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/README.md +26 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/card_01_percentage_advcalc.js +44 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/card_02_scroll_percentage.js +12 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/page.js +6 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/schema.js +22 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/README.md +28 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/card_01_rank_advcalc.js +59 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/page.js +6 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/schema.js +22 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/verify_default_roundtrip.sh +135 -0
- package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/README.md +15 -0
- package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/card_01_running_total_advcalc.js +74 -0
- package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/page.js +6 -0
- package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/schema.js +22 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_01_revenue_column.js +10 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_02_trend_line.js +9 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_03_kpi.js +6 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_04_pie.js +9 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_05_calc_field_test.js +12 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/page.js +11 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/schema.js +14 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/selector_01_region.js +10 -0
- package/skills-bundle/guanvis/evals/split_charts/card_01_column_split.js +10 -0
- package/skills-bundle/guanvis/evals/split_charts/card_02_line_split.js +10 -0
- package/skills-bundle/guanvis/evals/split_charts/card_03_combo_split.js +11 -0
- package/skills-bundle/guanvis/evals/split_charts/page.js +10 -0
- package/skills-bundle/guanvis/evals/split_charts/schema.js +14 -0
- package/skills-bundle/guanvis/evals/tab_layout/card_00_total_revenue.js +6 -0
- package/skills-bundle/guanvis/evals/tab_layout/card_01_revenue.js +10 -0
- package/skills-bundle/guanvis/evals/tab_layout/card_02_trend.js +9 -0
- package/skills-bundle/guanvis/evals/tab_layout/card_03_story.js +11 -0
- package/skills-bundle/guanvis/evals/tab_layout/page.js +23 -0
- package/skills-bundle/guanvis/evals/tab_layout/schema.js +11 -0
- package/skills-bundle/guanvis/evals/tab_layout/selector_01_region.js +8 -0
- package/skills-bundle/guanvis/references/api-reference.md +476 -0
- package/skills-bundle/guanvis/references/builder-reference.md +1676 -0
- package/skills-bundle/guanvis/references/chart-properties.md +2101 -0
- package/skills-bundle/guanvis/references/checkout-editing.md +53 -0
- package/skills-bundle/guanvis/references/complex-report-pro-patterns.md +398 -0
- package/skills-bundle/guanvis/references/dir-and-page-management.md +48 -0
- package/skills-bundle/guanvis/references/metric-chart-reference.md +258 -0
- package/skills-bundle/guanvis/references/publish-and-constraints.md +60 -0
- package/skills-bundle/guanvis/references/selector-reference.md +431 -0
- package/skills-bundle/guanvis/references/tableau-migration.md +73 -0
- package/skills-bundle/guanvis/references/theme.md +123 -0
- package/skills-bundle/guanvis/references/troubleshooting.md +25 -0
- package/skills-bundle/guanvis/references/validation-and-chart-patterns.md +205 -0
- package/skills-bundle/guanwf/SKILL.md +543 -0
- package/skills-bundle/guanwf/references/ETL_AI_DEVELOP.md +456 -0
- package/skills-bundle/guanwf/references/TASK_NODE_CONTRACTS.md +64 -0
- package/skills-bundle/guanwf/references/WORKFLOW_DSL.md +536 -0
- package/skills-bundle/guanwf/references/WORKFLOW_NODES.md +166 -0
- package/skills-bundle/js/SKILL.md +145 -0
|
@@ -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
|
+
}
|
|
@@ -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` 不做隐式聚合。存在重复粒度时,先使用具备明确聚合口径的上游查询或工具处理。
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# guancli 认证与配置
|
|
2
|
+
|
|
3
|
+
## 首次配置(认证)
|
|
4
|
+
|
|
5
|
+
### 方式一:用户名密码登录
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
guancli auth login
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
交互式输入:
|
|
12
|
+
1. 环境名称(默认 `default`,可自定义如 `staging`、`prod`)
|
|
13
|
+
2. BI 系统 URL(如 `https://bi.example.com`)
|
|
14
|
+
3. 选择登录方式:`1` 用户名密码
|
|
15
|
+
4. Domain(如 `demo`)
|
|
16
|
+
5. 用户名(邮箱)
|
|
17
|
+
6. 密码
|
|
18
|
+
|
|
19
|
+
账号或密码错误时,交互式登录会保留已输入的环境、URL、Domain 和 Login ID,直接提示重新输入密码。登录成功后 Token 自动保存在系统标准配置目录下的 `guancli/config.json`,并自动切换到刚登录的环境;无需再执行 `auth use`。密码方式支持 Token 过期后自动刷新。
|
|
20
|
+
|
|
21
|
+
### 方式二:直接输入 uIdToken
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
guancli auth login
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
选择登录方式 `2`,直接粘贴已有的 uIdToken。适用于已从 Web 界面或其他途径获取 uIdToken 的场景。
|
|
28
|
+
|
|
29
|
+
如需按登录 Domain 筛选这个 profile,可在非交互式登录时同时保存:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
guancli auth login --url https://bi.example.com --domain demo --token <uid-token>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 方式三:Personal Access Token
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
guancli auth login --url https://bi.example.com --pat <pat>
|
|
39
|
+
```
|
|
40
|
+
|
|
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`)时判定有效。
|
|
42
|
+
|
|
43
|
+
`chatbi` 子命令支持 uIdToken 或 OIDC Access Token;PAT 仍不支持。
|
|
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
|
+
### 多环境管理
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
guancli auth login --profile staging # 添加 staging 并切换为当前环境
|
|
65
|
+
guancli auth login --profile prod # 添加 prod 并切换为当前环境
|
|
66
|
+
guancli auth list # 列出所有环境
|
|
67
|
+
guancli auth list --domain demo # 按登录 Domain 筛选
|
|
68
|
+
guancli auth list --url https://bi.example.com/page/123 # 按页面 URL 筛选
|
|
69
|
+
guancli auth status # 查看当前认证状态
|
|
70
|
+
guancli auth use staging # 切换默认环境为 staging
|
|
71
|
+
guancli auth use --domain demo # 按登录 Domain 切换
|
|
72
|
+
guancli auth use --url https://bi.example.com/page/123 # 按页面 URL 切换
|
|
73
|
+
guancli auth remove staging # 删除 staging 环境
|
|
74
|
+
guancli auth logout staging # 吊销并清理 OIDC 自管 Token,保留 profile
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`auth list` 可用 `--domain` 或 `--url` 只读筛选 profile;`auth use` 使用相同筛选条件切换默认 profile。`--domain` 只匹配 profile 保存的登录 Domain,忽略大小写;`--url` 必须为不含 userinfo 的 HTTP(S) URL,且编码路径不得把 `/`、`.` 或 `..` 作为 path segment;它按相同协议、主机和最长的 `base_url` 路径前缀匹配,因此可直接传页面深链。`auth use` 遇到多个候选会拒绝切换,需改用 profile 名称明确选择。
|
|
78
|
+
|
|
79
|
+
使用特定环境(不切换默认):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
guancli --profile staging etl tree
|
|
83
|
+
guancli --profile staging chatbi list-theme
|
|
84
|
+
GUANCLI_PROFILE=staging guancli auth status
|
|
85
|
+
GUANCLI_PROFILE=staging guancli etl tree
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
显式的子命令 `--profile` 优先于根级 `--profile` / `GUANCLI_PROFILE`;未指定时才使用配置中的默认环境。高层 skill(如 `guanetl`)使用 `GUANCLI_PROFILE` 绑定当前进程链,不修改机器级默认环境。
|
|
89
|
+
|
|
90
|
+
### ChatBI 配置
|
|
91
|
+
|
|
92
|
+
ChatBI 统一复用当前 profile 的 `base_url` 和 uIdToken/OIDC Access Token。
|
|
93
|
+
|
|
94
|
+
- 不需要单独配置 ChatBI URL
|
|
95
|
+
- 不需要第二套 token / cookie
|
|
96
|
+
- `guancli` 会在内部自动推导并探测可用的 ChatBI Public API 地址,默认优先尝试同域名下的 `/api/chat/public-api`
|
|
97
|
+
|
|
98
|
+
## Token 管理
|
|
99
|
+
|
|
100
|
+
- 密码登录方式:Token 过期后自动调用 sign-in API 刷新。
|
|
101
|
+
- OIDC 自管 Token:请求前主动刷新;Refresh Token 失效时 macOS/Windows 自动进行浏览器登录,Linux/未适配平台提示手动执行 `auth login --oidc`。读请求遇到 401 最多刷新并重试一次,写请求只刷新不重放。
|
|
102
|
+
- OIDC 上游 Token:环境变量优先于上游钥匙串和本地凭据;过期或 401 时提示上游刷新,不使用上游 Refresh Token。
|
|
103
|
+
- 每次 API 响应中如果包含新 Token,且距上次签发超过可配置间隔(默认 10 分钟),会自动更新缓存。
|
|
104
|
+
- Token 的签发时间和过期时间记录在配置文件中。
|
|
105
|
+
- 可通过修改 `config.json` 中的 `token_refresh_interval_seconds` 调整刷新间隔。
|
|
106
|
+
|
|
107
|
+
## 配置文件位置
|
|
108
|
+
|
|
109
|
+
- macOS: `~/Library/Application Support/guancli/config.json`
|
|
110
|
+
- Linux: `~/.config/guancli/config.json`
|
|
111
|
+
- Windows: `%AppData%\\guancli\\config.json`
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"profiles": {
|
|
116
|
+
"default": {
|
|
117
|
+
"name": "default",
|
|
118
|
+
"base_url": "https://bi.example.com",
|
|
119
|
+
"domain": "demo",
|
|
120
|
+
"login_id": "user@example.com",
|
|
121
|
+
"password": "yourpassword",
|
|
122
|
+
"auth_method": "password",
|
|
123
|
+
"token": "...",
|
|
124
|
+
"issued_at": 1711234567,
|
|
125
|
+
"expires_at": 0,
|
|
126
|
+
"is_default": true
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"token_refresh_interval_seconds": 600
|
|
130
|
+
}
|
|
131
|
+
```
|
|
@@ -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,199 @@
|
|
|
1
|
+
# guancli 表单填报与 ChatBI
|
|
2
|
+
|
|
3
|
+
## 6. 表单填报操作 (Form CRUD)
|
|
4
|
+
|
|
5
|
+
类似 Airtable 风格的表单数据 CRUD,用户始终用**字段名**操作,CLI 内部自动映射到 fdId。
|
|
6
|
+
|
|
7
|
+
### 列出表单
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
guancli form list # 列出所有表单
|
|
11
|
+
guancli form list 关键词 # 搜索表单
|
|
12
|
+
guancli form list --tree # 目录树形式展示
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### 查看表单结构
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
guancli form schema <fmId> # 查看字段结构(LLM 消费核心)
|
|
19
|
+
guancli form schema <fmId> -f json # JSON 格式
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 查询数据
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
guancli form query <fmId> # 查询数据(默认 50 行)
|
|
26
|
+
guancli form query <fmId> --limit 100 # 指定行数
|
|
27
|
+
guancli form query <fmId> --filter "姓名 EQ 张三" # 筛选(服务端执行)
|
|
28
|
+
guancli form query <fmId> --sort-asc 值 # 按值升序(仅当前页)
|
|
29
|
+
guancli form query <fmId> --columns "姓名,值" # 只显示指定列
|
|
30
|
+
guancli form query <fmId> -f json # JSON 格式(rowId 完整)
|
|
31
|
+
guancli form query <fmId> -f expanded # PG 风格竖排
|
|
32
|
+
```
|
|
33
|
+
|
|
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` 取回全部数据后再排序。
|
|
88
|
+
|
|
89
|
+
**重要**:`rowId` 在 auto 表格格式中可能被截断,使用 `-f json` 或 `-f expanded` 获取完整 rowId。
|
|
90
|
+
|
|
91
|
+
### 插入数据
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
guancli form add <fmId> --data '{"字段名": "值", "数字字段": 42}'
|
|
95
|
+
guancli form add <fmId> --set "字段名=值" --set "数字字段=42"
|
|
96
|
+
echo '[{"字段名":"a"},{"字段名":"b"}]' | guancli form add <fmId> --stdin
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 更新数据
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
guancli form update <fmId> <rowId> --data '{"主键字段": "当前主键值", "字段名": "新值"}'
|
|
103
|
+
guancli form update <fmId> <rowId> --set "主键字段=当前主键值" --set "字段名=新值"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`rowId` 和未编辑主键的当前值通过 `form query` 获取。更新载荷必须包含表单配置的全部业务主键字段(内置
|
|
107
|
+
`c_uid` 除外);CLI 只负责字段名映射和请求透传,不读取当前行、不补齐主键,也不在本地重复后端校验。
|
|
108
|
+
|
|
109
|
+
### 删除数据
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
guancli form delete <fmId> <rowId> # 删除单行
|
|
113
|
+
guancli form delete <fmId> <rowId1> <rowId2> # 删除多行
|
|
114
|
+
guancli form delete <fmId> --all --yes # 删除全部(需确认)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 子表操作
|
|
118
|
+
|
|
119
|
+
主表中 `TABLE` / `MATRIX_TABLE` 类型字段对应子表。子表有独立的 `subFmId`,可以用 `schema` 查看其字段结构。
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# 1. 查看主表 schema,找到 TABLE 字段的 subFmId
|
|
123
|
+
guancli form schema <mainFmId>
|
|
124
|
+
# 输出中 TABLE 字段的备注列显示 "子表 subFmId=..."
|
|
125
|
+
|
|
126
|
+
# 2. 查看子表字段结构
|
|
127
|
+
guancli form schema <subFmId>
|
|
128
|
+
|
|
129
|
+
# 3. 查询子表数据(返回结果包含主表字段,rowId 为主表行 ID,subId 为子行 ID)
|
|
130
|
+
guancli form query <subFmId>
|
|
131
|
+
|
|
132
|
+
# 4. 向子表插入行(需指定主表行的 rowId)
|
|
133
|
+
guancli form add <subFmId> --parent-row <主表rowId> --set "字段名=值"
|
|
134
|
+
|
|
135
|
+
# 5. 更新子表行(使用 subId 作为 rowId)
|
|
136
|
+
guancli form update <subFmId> <subId> --set "字段名=新值"
|
|
137
|
+
|
|
138
|
+
# 6. 删除子表行
|
|
139
|
+
guancli form delete <subFmId> <subId>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**子表 ID 映射规则**(AI 调用时注意区分):
|
|
143
|
+
|
|
144
|
+
| 操作 | fmId 参数 | 行 ID 参数 | 额外参数 |
|
|
145
|
+
|------|-----------|-----------|---------|
|
|
146
|
+
| schema | subFmId | - | - |
|
|
147
|
+
| query | subFmId | - | 返回 rowId(主表行) + subId(子行) |
|
|
148
|
+
| add | subFmId | - | `--parent-row <主表rowId>` |
|
|
149
|
+
| update | subFmId | **subId** (作为 rowId 位置参数) | - |
|
|
150
|
+
| delete | subFmId | **subId** (作为 rowId 位置参数) | - |
|
|
151
|
+
|
|
152
|
+
**注意**:
|
|
153
|
+
- 子表 add 内部通过主表 update API 间接完成(后端限制),CLI 自动保留已有子行
|
|
154
|
+
- add 会分页读取已有子行并通过主表 update 全量回写以保留已有行;非并发安全
|
|
155
|
+
- `--stdin` 批量插入部分失败时 CLI 返回非零退出码,summary 中显示成功/失败计数
|
|
156
|
+
|
|
157
|
+
### 典型工作流
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# 1. 找到表单
|
|
161
|
+
guancli form list 测试
|
|
162
|
+
|
|
163
|
+
# 2. 查看结构
|
|
164
|
+
guancli form schema <fmId>
|
|
165
|
+
|
|
166
|
+
# 3. 插入数据
|
|
167
|
+
guancli form add <fmId> --data '{"测试1": "hello", "值": 42}'
|
|
168
|
+
|
|
169
|
+
# 4. 查询并获取 rowId
|
|
170
|
+
guancli form query <fmId> -f json
|
|
171
|
+
|
|
172
|
+
# 5. 更新(同时携带业务主键)
|
|
173
|
+
guancli form update <fmId> <rowId> --set "名称=当前名称" --set "值=99"
|
|
174
|
+
|
|
175
|
+
# 6. 删除
|
|
176
|
+
guancli form delete <fmId> <rowId>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## 7. ChatBI 主题问数 / 洞察
|
|
180
|
+
|
|
181
|
+
先列主题,再执行问数或洞察;如果用户没有指定主题,不要猜。
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
guancli chatbi list-theme
|
|
185
|
+
guancli chatbi list-theme --insight
|
|
186
|
+
guancli chatbi query --theme-name "经营主题" --message "最近30天营业收入是多少?"
|
|
187
|
+
guancli chatbi query --theme-id "<theme_id>" --message "最近30天营业收入是多少?"
|
|
188
|
+
guancli chatbi insight --theme-name "经营主题" --message "分析最近30天营业收入变化原因"
|
|
189
|
+
guancli chatbi insight --theme-id "<theme_id>" --message "分析最近30天营业收入变化原因" --agent-mode single_agent
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
规则:
|
|
193
|
+
|
|
194
|
+
- `list-theme` 输出 markdown 表格
|
|
195
|
+
- `list-theme --insight` 可列出仅用于洞察的主题
|
|
196
|
+
- `query` 输出 L1 markdown,包含解释和结果表格
|
|
197
|
+
- `insight` 输出 L2 markdown;如返回 `GuanViz.json`,CLI 会自动降级成 markdown 表格
|
|
198
|
+
- ChatBI 命令复用当前 profile 的 `uIdToken`
|
|
199
|
+
- 默认超时 300 秒、轮询间隔 2 秒;必要时可传 `--timeout-ms` / `--poll-interval-ms`
|