@qingflow-tech/qingflow-app-user-mcp 1.0.4 → 1.0.5
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/README.md +2 -2
- package/package.json +1 -1
- package/pyproject.toml +2 -1
- package/skills/qingflow-app-user/SKILL.md +2 -1
- package/skills/qingflow-app-user/references/data-gotchas.md +5 -2
- package/skills/qingflow-app-user/references/public-surface-sync.md +5 -3
- package/skills/qingflow-app-user/references/record-patterns.md +9 -0
- package/skills/qingflow-record-analysis/SKILL.md +103 -166
- package/skills/qingflow-record-analysis/agents/openai.yaml +2 -2
- package/skills/qingflow-record-analysis/references/analysis-gotchas.md +56 -110
- package/skills/qingflow-record-analysis/references/analysis-patterns.md +106 -119
- package/skills/qingflow-record-analysis/references/business-context.md +74 -0
- package/skills/qingflow-record-analysis/references/confidence-reporting.md +49 -72
- package/skills/qingflow-record-analysis/references/data-access-playbook.md +106 -0
- package/skills/qingflow-record-analysis/references/pandas-recipes.md +172 -0
- package/skills/qingflow-record-analysis/references/report-format.md +76 -0
- package/skills/qingflow-record-insert/SKILL.md +2 -2
- package/skills/qingflow-record-update/SKILL.md +1 -1
- package/src/qingflow_mcp/backend_client.py +55 -1
- package/src/qingflow_mcp/cli/commands/record.py +44 -5
- package/src/qingflow_mcp/cli/formatters.py +101 -1
- package/src/qingflow_mcp/public_surface.py +2 -1
- package/src/qingflow_mcp/response_trim.py +173 -9
- package/src/qingflow_mcp/server.py +15 -9
- package/src/qingflow_mcp/server_app_user.py +26 -10
- package/src/qingflow_mcp/tools/record_tools.py +12860 -8811
- package/skills/qingflow-record-analysis/references/dsl-templates.md +0 -93
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Install:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npm install @qingflow-tech/qingflow-app-user-mcp@1.0.
|
|
6
|
+
npm install @qingflow-tech/qingflow-app-user-mcp@1.0.5
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @qingflow-tech/qingflow-app-user-mcp@1.0.
|
|
12
|
+
npx -y -p @qingflow-tech/qingflow-app-user-mcp@1.0.5 qingflow-app-user-mcp
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "qingflow-mcp"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.5"
|
|
8
8
|
description = "User-authenticated MCP server for Qingflow"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -29,6 +29,7 @@ dependencies = [
|
|
|
29
29
|
"openpyxl>=3.1,<4.0",
|
|
30
30
|
"pydantic>=2.8,<3.0",
|
|
31
31
|
"pycryptodome>=3.20,<4.0",
|
|
32
|
+
"pypdf>=5.0,<6.0",
|
|
32
33
|
"python-socketio[client]>=5.11,<6.0",
|
|
33
34
|
]
|
|
34
35
|
|
|
@@ -54,7 +54,7 @@ Route to exactly one of these specialized paths:
|
|
|
54
54
|
- If the task involves member, department, or relation fields and the user only has natural names/titles, keep the same route; direct write now supports backend-native auto resolution and may return `needs_confirmation` with candidates instead of failing blind
|
|
55
55
|
- If the task involves linked visibility, upstream/downstream field dependencies, reference-driven auto fill, or formula-driven defaulting, keep the same insert/update route and read field-level `linkage` from the schema before composing payloads
|
|
56
56
|
- If the task is about subtable writes, still route to the matching insert/update skill, but shape the payload as parent subtable field -> row array; do not route users toward top-level leaf selectors
|
|
57
|
-
- If the task is insert-focused and readback
|
|
57
|
+
- If the task is insert-focused and readback/detail context matters, keep the same route and prefer the single-record detail readback after the write; use normalized list readback only when batch row shape is needed
|
|
58
58
|
- If the user sounds like an ordinary workflow assignee rather than a system operator, prefer `$qingflow-task-ops` over direct record mutation whenever both paths could fit
|
|
59
59
|
- If the task is about task discovery by natural language query, still route to `$qingflow-task-ops`; `task_list --query` now uses backend search first and only falls back to local matching when backend returns zero rows
|
|
60
60
|
- If the task is about grouped distributions, ratios, rankings, trends, insights, or any final statistical conclusion, switch to `$qingflow-record-analysis`
|
|
@@ -68,6 +68,7 @@ Route to exactly one of these specialized paths:
|
|
|
68
68
|
- if the task can stay read-only, do not write or act
|
|
69
69
|
- if the task involves a user-uploaded import file, do not modify the file unless the user explicitly authorizes repair or normalization
|
|
70
70
|
- if the task involves record import, call `app_get` first and inspect `data.import_capability` before template download, file repair, or import start
|
|
71
|
+
- if a record detail includes images or attachments, prefer the single-record detail tool's local paths: images from `media_assets.items[].local_path`, documents/tables from `file_assets.items[].local_path` and `extraction.text_path`; remote Qingflow file URLs are not stable direct-read targets
|
|
71
72
|
- if the current MCP capability is unsupported, the workflow is awkward, or the user's need still cannot be satisfied after reasonable use, summarize the gap, ask whether to submit feedback, and call `feedback_submit` only after explicit user confirmation
|
|
72
73
|
|
|
73
74
|
## Shared Helper
|
|
@@ -4,10 +4,12 @@ For final statistics, grouped distributions, rankings, trends, or insight-style
|
|
|
4
4
|
|
|
5
5
|
## Record Reads
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- `
|
|
7
|
+
- For analysis-style reads, use `record_access` through [$qingflow-record-analysis](../../qingflow-record-analysis/SKILL.md)
|
|
8
|
+
- `record_list` is for browsing and sample inspection only
|
|
9
|
+
- `record_get` is for one exact record and downloads readable detail-page images into `media_assets.items[].local_path` plus attachments/documents/tables into `file_assets.items[].local_path`
|
|
9
10
|
- Use `record_browse_schema_get` when field titles are uncertain instead of guessing ids
|
|
10
11
|
- Do not present paged browse output as if it were a grouped or full-population conclusion
|
|
12
|
+
- Use `record_export_direct` only when the user explicitly asks for export/download/Excel output
|
|
11
13
|
|
|
12
14
|
## Direct Writes
|
|
13
15
|
|
|
@@ -27,3 +29,4 @@ For final statistics, grouped distributions, rankings, trends, or insight-style
|
|
|
27
29
|
|
|
28
30
|
- Subtable payloads stay under the parent table field as a row array
|
|
29
31
|
- Attachment fields are two-step: upload first, then write the returned upload payload
|
|
32
|
+
- For reads, attachment/rich-text images returned by `record_get` should be opened from local `media_assets` paths, and non-image files should be read from `file_assets` local paths or `extraction.text_path`, instead of remote file URLs
|
|
@@ -8,11 +8,13 @@ It is not a user-facing product spec. It exists to prevent skill drift.
|
|
|
8
8
|
### User data
|
|
9
9
|
|
|
10
10
|
- Read range first with `app_get`, then `record_browse_schema_get(view_id=...)`
|
|
11
|
+
- Treat `record_browse_schema_get.fields` as the selected Qingflow table view header schema; `record_access.fields` and `record_list` field selectors must stay aligned with it.
|
|
11
12
|
- Standard flows:
|
|
12
|
-
-
|
|
13
|
+
- analyze: `app_get -> record_browse_schema_get -> record_access -> Python`
|
|
14
|
+
- browse detail: `app_get -> record_browse_schema_get -> record_list / record_get`
|
|
15
|
+
- explicit export/download/Excel: `view_get -> record_export_*` or `record_export_direct`
|
|
13
16
|
- insert: `record_insert_schema_get -> record_insert`
|
|
14
17
|
- update: `record_update_schema_get -> record_update`
|
|
15
|
-
- analyze: `app_get -> record_browse_schema_get -> record_analyze`
|
|
16
18
|
|
|
17
19
|
### Tasks
|
|
18
20
|
|
|
@@ -55,7 +57,7 @@ It is not a user-facing product spec. It exists to prevent skill drift.
|
|
|
55
57
|
- Package public tools: do not regress to `package_create` / `package_attach_app` as the public default story
|
|
56
58
|
- App editability: do not let `can_edit_form` imply app base-info writes
|
|
57
59
|
- Portal and chart visibility: keep the public story on `portal_apply` / `app_charts_apply`, not low-level internal writes
|
|
58
|
-
- Analysis
|
|
60
|
+
- Analysis path: standard path stays `record_access -> Python`
|
|
59
61
|
|
|
60
62
|
## Release Checklist For Skill Maintenance
|
|
61
63
|
|
|
@@ -10,6 +10,14 @@ Use `record_browse_schema_get -> record_list` when:
|
|
|
10
10
|
- the target `record_id` is unknown
|
|
11
11
|
- a delete target still needs confirmation
|
|
12
12
|
- the user needs sample rows or a small export
|
|
13
|
+
- the user gives fuzzy text such as a company, project, bug, or contract name
|
|
14
|
+
|
|
15
|
+
For fuzzy lookup, pass `query` and optional `query_fields`. `record_list` returns at most 10 `data.items`, plus `data.pagination.total_count` and `lookup.next_action`.
|
|
16
|
+
|
|
17
|
+
- `lookup.next_action="record_get"`: read the single returned item with `record_get`
|
|
18
|
+
- `lookup.next_action="ask_user"`: ask the user to choose from returned `data.items`
|
|
19
|
+
- `lookup.next_action="refine_query"`: ask for a narrower keyword or add `query_fields`
|
|
20
|
+
- `lookup.next_action="broaden_query"`: remove overly narrow fields or ask for another clue
|
|
13
21
|
|
|
14
22
|
## Detail Pattern
|
|
15
23
|
|
|
@@ -18,6 +26,7 @@ Use `record_browse_schema_get -> record_get` when:
|
|
|
18
26
|
- the exact `record_id` is known
|
|
19
27
|
- the user needs one record in detail
|
|
20
28
|
- a write target needs verification before action
|
|
29
|
+
- the user needs images or attachments shown on the detail page; read downloaded images from `media_assets.items[].local_path`, and read documents/tables from `file_assets.items[].local_path` or `extraction.text_path`
|
|
21
30
|
|
|
22
31
|
## Insert Pattern
|
|
23
32
|
|
|
@@ -1,200 +1,137 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qingflow-record-analysis
|
|
3
|
-
description: Analyze Qingflow record data safely after the MCP is already connected and authenticated. Use when the user wants grouped distributions, ratios, averages, rankings, trends, insights, or any final statistical conclusion across an existing app's data.
|
|
3
|
+
description: Analyze Qingflow record data safely after the MCP is already connected and authenticated. Use when the user wants grouped distributions, ratios, averages, rankings, trends, insights, comparisons, or any final statistical conclusion across an existing app's data. Default to schema-first record_access CSV retrieval plus local Python/pandas; do not use export tools unless the user explicitly asks for a file download.
|
|
4
4
|
metadata:
|
|
5
|
-
short-description: Analyze Qingflow record data with
|
|
5
|
+
short-description: Analyze Qingflow record data with record_access CSV and Python
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Qingflow Record Analysis
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
Assumes MCP is connected, authenticated, and on the correct workspace.
|
|
12
|
-
Analysis tasks must start with `app_get`, then `record_browse_schema_get(view_id=...)`. Read top-level `fields` and `suggested_*`, then build field_id-based DSLs only.
|
|
13
|
-
Analysis tasks must start with `record_browse_schema_get`.
|
|
14
|
-
If `app_get.accessible_views` marks a view with `analysis_supported=false`, do not use that view for `record_list` or `record_analyze`. `boardView` and `ganttView` are special UI views, not list/analyze targets.
|
|
10
|
+
Use this skill only for final statistical conclusions: counts, distributions, ratios, averages, rankings, trends, comparisons, and analysis reports.
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
Default path, every time:
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## Execution Modes
|
|
23
|
-
|
|
24
|
-
Choose the lightest mode that can still support a trustworthy conclusion:
|
|
25
|
-
|
|
26
|
-
1. `server_aggregate`
|
|
27
|
-
- Default and preferred path
|
|
28
|
-
- Use `record_analyze` directly after `app_get -> record_browse_schema_get`
|
|
29
|
-
|
|
30
|
-
2. `client_aggregate_from_record_list`
|
|
31
|
-
- Allowed fallback when `record_analyze` is unstable, unsupported on the target view, or the table is complex enough that service-side aggregation is not trustworthy
|
|
32
|
-
- Still requires `app_get -> record_browse_schema_get` first
|
|
33
|
-
- Use only after disclosing that the result is a fallback built from detail rows
|
|
34
|
-
|
|
35
|
-
3. `cross_app_manual_reconcile`
|
|
36
|
-
- Use when the question depends on joining multiple apps, organization-history alias mapping, or other business logic that current public tools do not express directly
|
|
37
|
-
- Be explicit that the conclusion is based on manual reconciliation rules, not one single DSL execution
|
|
38
|
-
|
|
39
|
-
## Fallback Ladder
|
|
40
|
-
|
|
41
|
-
Trigger a fallback when any of these are true:
|
|
42
|
-
|
|
43
|
-
- `record_analyze` is unstable or cannot complete the scan reliably
|
|
44
|
-
- the target view is unsupported for analysis
|
|
45
|
-
- field semantics are ambiguous enough that a server aggregate would be misleading
|
|
46
|
-
- the question requires cross-app reconciliation
|
|
47
|
-
- the question depends on organization-tree scope, historical department aliases, or other business rules that are not first-class MCP filters
|
|
48
|
-
|
|
49
|
-
When you fall back:
|
|
50
|
-
|
|
51
|
-
1. Keep the standard read order: `app_get -> record_browse_schema_get`
|
|
52
|
-
2. State which fallback mode you chose
|
|
53
|
-
3. State whether the result is still full-scope or only a verified subset
|
|
54
|
-
4. State the time field, organization scope, and any alias mapping used
|
|
55
|
-
5. Prefer concrete numbers plus a conservative conclusion over broad wording
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## DSL Contract
|
|
60
|
-
|
|
61
|
-
### DSL FORMAT (CRITICAL — read this FIRST)
|
|
14
|
+
```text
|
|
15
|
+
app_get -> record_browse_schema_get(view_id=...) -> record_access -> Python/pandas -> final answer
|
|
16
|
+
```
|
|
62
17
|
|
|
63
|
-
|
|
18
|
+
`record_access` may appear either as an MCP tool or as a CLI subcommand. If the active client does not expose an MCP `record_access` tool, do not switch to aggregate helpers. Use the CLI entry instead:
|
|
64
19
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
❌ WRONG: "报价类型" ← string, not a dict
|
|
70
|
-
❌ WRONG: { "field_id": 9500572, "title": "报价类型" } ← "title" is forbidden
|
|
20
|
+
```bash
|
|
21
|
+
qingflow record --help
|
|
22
|
+
qingflow record access --help
|
|
23
|
+
qingflow record access --app-key APP_KEY --view-id VIEW_ID --columns-file columns.json --where-file where.json --order-by-file order_by.json --json
|
|
71
24
|
```
|
|
72
25
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
26
|
+
The CLI command is under the `record` command group, so the discovery path is: first inspect `qingflow record --help`, then inspect `qingflow record access --help`.
|
|
27
|
+
|
|
28
|
+
## Hard Rules
|
|
29
|
+
|
|
30
|
+
- Never start analysis from `record_list`, export, QingBI, or guessed field ids.
|
|
31
|
+
- Never conclude `record_access` is unavailable just because it is not visible as a top-level MCP tool; check the CLI path `qingflow record access`.
|
|
32
|
+
- Never call `record_access` before `record_browse_schema_get`.
|
|
33
|
+
- Use only field ids returned by `record_browse_schema_get.fields`.
|
|
34
|
+
- If `app_get.accessible_views[].analysis_supported=false`, do not use that view for `record_access`.
|
|
35
|
+
- Prefer an explicit time range or business filter. If the user gives none and the table may be large, ask for scope or use a clearly provided month/quarter/year.
|
|
36
|
+
- Read every CSV shard in `record_access.files[].local_path` with Python. Do not print raw CSV or load raw rows into model context.
|
|
37
|
+
- Before final analysis, run a field-quality profile in pandas: row count, null rate, distinct count, and period coverage for candidate grouping fields.
|
|
38
|
+
- Do not use a high-missing field as the main conclusion dimension. If a candidate dimension is sparse, downgrade it to an `已填写样本观察` and choose a cleaner semantic fallback when available.
|
|
39
|
+
- Full final conclusions require `record_access.complete=true` and `record_access.safe_for_final_conclusion=true`.
|
|
40
|
+
- `record_list` is only for sample inspection after the aggregate result is understood.
|
|
41
|
+
- `record_get` is only for single-record detail verification, logs, references, images, or readable attachments. Read images from `media_assets.items[].local_path`; read documents/tables from `file_assets.items[].local_path` and `extraction.text_path`.
|
|
42
|
+
- `record_export_direct` is only for explicit export/download/Excel requests.
|
|
43
|
+
- `chart_get` / QingBI is only for user-provided report URLs or chart ids.
|
|
44
|
+
|
|
45
|
+
## Tool Selection
|
|
46
|
+
|
|
47
|
+
| Need | Tool |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Batch analysis, statistics, comparison, report | `record_access -> Python` |
|
|
50
|
+
| Browse a few example rows | `record_list` |
|
|
51
|
+
| Inspect one record, logs, references, images, attachments | `record_get` |
|
|
52
|
+
| User asks to export/download/Excel | `record_export_direct` |
|
|
53
|
+
| User gives report URL or chart id | `chart_get` |
|
|
54
|
+
| Todo/workflow task actions | `$qingflow-task-ops` |
|
|
55
|
+
|
|
56
|
+
## Standard Procedure
|
|
57
|
+
|
|
58
|
+
1. Run `app_get` and choose a table-style `view_id` from `accessible_views`.
|
|
59
|
+
2. Run `record_browse_schema_get(app_key, view_id)`.
|
|
60
|
+
3. Decide metric intent before fetching data: `count`, `sum`, `avg`, `distinct_count`, ratio, ranking, trend, or comparison.
|
|
61
|
+
4. Choose minimal `record_access.columns`, plus `where` and `order_by`.
|
|
62
|
+
5. Run `record_access` through MCP if visible, otherwise through `qingflow record access`.
|
|
63
|
+
6. Read all returned CSV files in Python; use `fields[]` only when field-id metadata is needed.
|
|
64
|
+
7. Run field-quality checks for all candidate dimensions.
|
|
65
|
+
8. Compute results in pandas.
|
|
66
|
+
9. Report numbers with scope, field choices, field-quality caveats, completeness, and business assumptions.
|
|
67
|
+
|
|
68
|
+
Use field-id DSLs only:
|
|
81
69
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"app_key": "APP_KEY",
|
|
73
|
+
"view_id": "system:all",
|
|
74
|
+
"columns": [{ "field_id": 2 }, { "field_id": 18 }],
|
|
75
|
+
"where": [{ "field_id": 2, "op": "between", "value": ["2026-05-01", "2026-05-31"] }],
|
|
76
|
+
"order_by": [{ "field_id": 2, "direction": "asc" }]
|
|
77
|
+
}
|
|
88
78
|
```
|
|
89
79
|
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
✅ CORRECT: { "by": "记录数", "order": "desc" } ← "by" references an alias
|
|
93
|
-
❌ WRONG: { "by": 9500572, "order": "desc" } ← field_id not allowed in sort
|
|
94
|
-
```
|
|
80
|
+
Never pass `page`, `page_size`, `limit`, `max_rows`, `timeout`, or `profile` to `record_access`.
|
|
95
81
|
|
|
96
|
-
|
|
82
|
+
CSV columns are already readable and field-id anchored, for example `项目状态__field_343283094`. Do not expect separate `schema.json` or `README.md` files.
|
|
97
83
|
|
|
98
|
-
|
|
99
|
-
|------|-------------------|
|
|
100
|
-
| dimension | `field_id`, `alias`, `bucket` |
|
|
101
|
-
| metric | `op`, `field_id`, `alias` |
|
|
102
|
-
| filter | `field_id`, `op`, `value` |
|
|
103
|
-
| sort | `by`, `order` |
|
|
84
|
+
For CLI use, write JSON argument files instead of embedding large JSON in shell text:
|
|
104
85
|
|
|
105
|
-
|
|
86
|
+
```bash
|
|
87
|
+
qingflow record access \
|
|
88
|
+
--app-key APP_KEY \
|
|
89
|
+
--view-id system:all \
|
|
90
|
+
--columns-file columns.json \
|
|
91
|
+
--where-file where.json \
|
|
92
|
+
--order-by-file order_by.json \
|
|
93
|
+
--json
|
|
94
|
+
```
|
|
106
95
|
|
|
107
|
-
|
|
108
|
-
- filters: `eq`, `neq`, `in`, `not_in`, `gt`, `gte`, `lt`, `lte`, `between`, `contains`, `is_null`, `not_null`
|
|
109
|
-
- For `count` metric: do NOT pass `field_id`. For all others: `field_id` is required.
|
|
110
|
-
- If `metrics` is omitted or `[]`, defaults to `[{"op":"count","alias":"记录数"}]`.
|
|
96
|
+
## Status Handling
|
|
111
97
|
|
|
112
|
-
|
|
98
|
+
Read `record_access.status` before reading files or writing conclusions.
|
|
113
99
|
|
|
114
|
-
|
|
100
|
+
- `status=success`, `complete=true`, `safe_for_final_conclusion=true`: full-scope answer is allowed.
|
|
101
|
+
- `status=needs_scope`: no CSV was written. Ask for a time/business range or retry with a user-provided period using `scope.suggested_time_fields`.
|
|
102
|
+
- `status=partial`: read returned files only as a subset. Do not give a full-population conclusion.
|
|
103
|
+
- `complete=false`, `truncated=true`, or `safe_for_final_conclusion=false`: answer as `初步观察` or ask for a narrower scope.
|
|
115
104
|
|
|
116
|
-
|
|
117
|
-
```json
|
|
118
|
-
{
|
|
119
|
-
"dimensions": [{ "field_id": FIELD_ID_FROM_SCHEMA, "alias": "维度名" }],
|
|
120
|
-
"metrics": [{ "op": "count", "alias": "记录数" }],
|
|
121
|
-
"sort": [{ "by": "记录数", "order": "desc" }],
|
|
122
|
-
"limit": 50,
|
|
123
|
-
"strict_full": true
|
|
124
|
-
}
|
|
125
|
-
```
|
|
105
|
+
## Business Context
|
|
126
106
|
|
|
127
|
-
|
|
128
|
-
```json
|
|
129
|
-
{
|
|
130
|
-
"dimensions": [{ "field_id": TIME_FIELD_ID, "alias": "月份", "bucket": "month" }],
|
|
131
|
-
"metrics": [{ "op": "count", "alias": "记录数" }],
|
|
132
|
-
"filters": [{ "field_id": TIME_FIELD_ID, "op": "between", "value": ["2024-03-01", "2024-03-31"] }],
|
|
133
|
-
"sort": [{ "by": "月份", "order": "asc" }],
|
|
134
|
-
"limit": 24,
|
|
135
|
-
"strict_full": true
|
|
136
|
-
}
|
|
137
|
-
```
|
|
107
|
+
If the question mentions department, team, region, owner group, stage, product line, or a named business scope, check whether aliases or child scopes matter before concluding. Use explicit mappings provided by the user or local context; otherwise ask a short clarification.
|
|
138
108
|
|
|
139
|
-
|
|
109
|
+
Example: if `烈焰组` and `飓风组` are sub-departments of `北斗部门`, apply that mapping in Python and state it in the answer.
|
|
140
110
|
|
|
141
|
-
|
|
142
|
-
- `dimensions`: `[]` = whole-table summary; `[{...}]` = grouped.
|
|
143
|
-
- `strict_full`: `true` for final conclusions. `false` allows partial results.
|
|
144
|
-
- `limit`: limits returned rows only, not scan scope.
|
|
145
|
-
- `view_id`: the canonical browse selector. Prefer choosing it from `app_get.accessible_views`.
|
|
146
|
-
- Prefer `view_id` entries where `analysis_supported=true`. If a view is `boardView` or `ganttView`, switch to a system or table-style custom view before calling `record_analyze`.
|
|
147
|
-
- If a chosen `view_id` is `custom:*`, treat the output as analysis over an unverified saved-filter scope unless `verification.view_filter_verified=true`. For critical conclusions, prefer `system:all` plus explicit filters in the DSL.
|
|
148
|
-
- `bucket` in dimensions: only for `suggested_time_fields`. Values: `day`/`week`/`month`/`quarter`/`year`/`null`.
|
|
111
|
+
## Output Shape
|
|
149
112
|
|
|
150
|
-
|
|
113
|
+
Default to:
|
|
151
114
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
- Derived ratios must be computed outside the DSL.
|
|
157
|
-
- Before choosing a DSL shape, first decide whether the question needs `count`, `sum`, `avg`, `distinct_count`, `ratio`, or `ranking`.
|
|
158
|
-
- Rankings must come from structured sorted results.
|
|
159
|
-
- For partial answers, explicitly disclose which parts are complete and which parts remain unresolved.
|
|
160
|
-
- Complex answers should default to `先结构、后解读`.
|
|
161
|
-
- `between`: pass a two-item array.
|
|
162
|
-
- Sort entries must reference an alias already defined in `dimensions` or `metrics`.
|
|
163
|
-
- Final wording should stay as close as possible to schema titles.
|
|
164
|
-
- Do not pass field titles, aliases, or guessed ids.
|
|
165
|
-
- If `completeness.statement_scope=returned_groups_only` or `completeness.rows_truncated=true`, downgrade wording to returned groups only.
|
|
166
|
-
- One DSL per question. Multiple small DSLs > one overloaded request.
|
|
167
|
-
- `record_list` is not the default basis for final statistics. Use it only in an explicit fallback mode and disclose that fallback in the final answer.
|
|
168
|
-
- Set `alias` for any metric you will sort by, compare, or quote.
|
|
115
|
+
1. `结论`
|
|
116
|
+
2. `关键数据`
|
|
117
|
+
3. `口径与范围`
|
|
118
|
+
4. `可信度 / 限制`
|
|
169
119
|
|
|
170
|
-
|
|
120
|
+
Concrete numbers are mandatory. Ratios require both numerator and denominator. Trends require a time field and explicit date range. Rankings must come from a sorted pandas result.
|
|
121
|
+
If a requested dimension has poor quality, say so explicitly and provide the nearest reliable fallback dimension, for example platform or product instead of a mostly empty module field.
|
|
171
122
|
|
|
172
|
-
##
|
|
173
|
-
|
|
174
|
-
- Final answer must show concrete numbers.
|
|
175
|
-
- Final answer must state which execution mode was used whenever the answer is not a straightforward `server_aggregate`
|
|
176
|
-
- If `result.rows` exists, list each returned row; if there are more than 20 rows, show Top 20 and say so.
|
|
177
|
-
- 占比 = 行指标值 / `result.totals.metric_totals` 总值;如 `metric_totals` 缺失,用各行之和作分母。
|
|
178
|
-
- Prefer the structured `ranking` block when it exists.
|
|
179
|
-
- `safe_for_final_conclusion=true` → `全量可信结论`
|
|
180
|
-
- Otherwise → `初步观察`
|
|
181
|
-
- `rows_truncated=true` → 用 `前 N 个分组`, 不用 `全部`/`所有`
|
|
182
|
-
- If you used a fallback mode, explicitly disclose:
|
|
183
|
-
- whether this is full-scope or a manually curated subset
|
|
184
|
-
- which time field was used
|
|
185
|
-
- which organization scope was used
|
|
186
|
-
- whether any historical department aliases or cross-app joins were applied
|
|
123
|
+
## References
|
|
187
124
|
|
|
188
|
-
|
|
125
|
+
Load only what is needed:
|
|
189
126
|
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
-
|
|
127
|
+
- Data access status machine: [references/data-access-playbook.md](references/data-access-playbook.md)
|
|
128
|
+
- Python/pandas templates: [references/pandas-recipes.md](references/pandas-recipes.md)
|
|
129
|
+
- Analysis patterns: [references/analysis-patterns.md](references/analysis-patterns.md)
|
|
130
|
+
- Business mappings and scope: [references/business-context.md](references/business-context.md)
|
|
131
|
+
- Confidence and final wording: [references/confidence-reporting.md](references/confidence-reporting.md)
|
|
132
|
+
- Common mistakes: [references/analysis-gotchas.md](references/analysis-gotchas.md)
|
|
133
|
+
- Report templates: [references/report-format.md](references/report-format.md)
|
|
193
134
|
|
|
194
|
-
##
|
|
135
|
+
## Feedback Escalation
|
|
195
136
|
|
|
196
|
-
|
|
197
|
-
- DSL templates: [references/dsl-templates.md](references/dsl-templates.md)
|
|
198
|
-
- Analysis patterns: [references/analysis-patterns.md](references/analysis-patterns.md)
|
|
199
|
-
- Confidence reporting: [references/confidence-reporting.md](references/confidence-reporting.md)
|
|
200
|
-
- Analysis gotchas: [references/analysis-gotchas.md](references/analysis-gotchas.md)
|
|
137
|
+
If the desired analysis cannot be completed because of missing capability, unsupported data shape, or an awkward workflow after reasonable attempts, summarize the exact gap and ask whether to submit product feedback. Only after explicit user confirmation, call `feedback_submit`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Qingflow Record Analysis"
|
|
3
|
-
short_description: "Analyze Qingflow record data with
|
|
4
|
-
default_prompt: "Use $qingflow-record-analysis for grouped distributions, ratios, rankings, trends, and final statistical conclusions in Qingflow apps. Start with record_browse_schema_get,
|
|
3
|
+
short_description: "Analyze Qingflow record data with record_access CSV and Python"
|
|
4
|
+
default_prompt: "Use $qingflow-record-analysis for grouped distributions, ratios, rankings, trends, and final statistical conclusions in Qingflow apps. Start with app_get and record_browse_schema_get, run record_access with field_id-based columns/where/order_by, then analyze every returned CSV shard with Python. Always run field-quality checks before choosing final grouping dimensions, and downgrade sparse dimensions to filled-sample observations. If record_access is not visible as an MCP tool, discover and use the CLI path qingflow record --help -> qingflow record access --help. Treat record_list as sample-only."
|