@qingflow-tech/qingflow-app-user-mcp 1.0.11 → 1.0.12
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 +9 -3
- package/docs/local-agent-install.md +54 -3
- package/entry_point.py +1 -1
- package/npm/bin/qingflow-skills.mjs +5 -0
- package/npm/lib/runtime.mjs +304 -13
- package/npm/scripts/postinstall.mjs +1 -5
- package/package.json +3 -2
- package/pyproject.toml +1 -1
- package/skills/qingflow-app-builder/SKILL.md +255 -0
- package/skills/qingflow-app-builder/agents/openai.yaml +4 -0
- package/skills/qingflow-app-builder/references/create-app.md +149 -0
- package/skills/qingflow-app-builder/references/environments.md +63 -0
- package/skills/qingflow-app-builder/references/flow-actors-and-permissions.md +123 -0
- package/skills/qingflow-app-builder/references/gotchas.md +107 -0
- package/skills/qingflow-app-builder/references/match-rules.md +114 -0
- package/skills/qingflow-app-builder/references/public-surface-sync.md +75 -0
- package/skills/qingflow-app-builder/references/solution-playbooks.md +52 -0
- package/skills/qingflow-app-builder/references/tool-selection.md +99 -0
- package/skills/qingflow-app-builder/references/update-flow.md +158 -0
- package/skills/qingflow-app-builder/references/update-layout.md +68 -0
- package/skills/qingflow-app-builder/references/update-schema.md +72 -0
- package/skills/qingflow-app-builder/references/update-views.md +284 -0
- package/skills/qingflow-app-builder-code-integrations/SKILL.md +137 -0
- package/skills/qingflow-app-builder-code-integrations/agents/openai.yaml +4 -0
- package/skills/qingflow-app-builder-code-integrations/references/code-block.md +66 -0
- package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +77 -0
- package/skills/qingflow-app-user/SKILL.md +12 -11
- package/skills/qingflow-app-user/references/data-gotchas.md +2 -2
- package/skills/qingflow-app-user/references/public-surface-sync.md +3 -3
- package/skills/qingflow-app-user/references/record-patterns.md +5 -5
- package/skills/qingflow-app-user/references/workflow-usage.md +4 -5
- package/skills/qingflow-mcp-setup/SKILL.md +113 -0
- package/skills/qingflow-mcp-setup/agents/openai.yaml +4 -0
- package/skills/qingflow-mcp-setup/references/claude-desktop.md +34 -0
- package/skills/qingflow-mcp-setup/references/environments.md +62 -0
- package/skills/qingflow-mcp-setup/references/generic-stdio.md +32 -0
- package/skills/qingflow-mcp-setup/scripts/check_local_server.sh +38 -0
- package/skills/qingflow-record-analysis/SKILL.md +6 -7
- package/skills/qingflow-record-analysis/manifest.yaml +10 -0
- package/skills/qingflow-record-delete/SKILL.md +5 -3
- package/skills/qingflow-record-import/SKILL.md +6 -2
- package/skills/qingflow-record-insert/SKILL.md +48 -4
- package/skills/qingflow-record-insert/manifest.yaml +6 -0
- package/skills/qingflow-record-update/SKILL.md +36 -24
- package/skills/qingflow-task-ops/SKILL.md +25 -25
- package/skills/qingflow-task-ops/references/environments.md +0 -1
- package/skills/qingflow-task-ops/references/workflow-usage.md +4 -6
- package/src/qingflow_mcp/__main__.py +6 -2
- package/src/qingflow_mcp/builder_facade/service.py +1488 -288
- package/src/qingflow_mcp/cli/commands/builder.py +2 -2
- package/src/qingflow_mcp/cli/commands/exports.py +2 -2
- package/src/qingflow_mcp/cli/commands/imports.py +1 -1
- package/src/qingflow_mcp/cli/commands/record.py +39 -11
- package/src/qingflow_mcp/cli/context.py +0 -3
- package/src/qingflow_mcp/cli/formatters.py +206 -7
- package/src/qingflow_mcp/cli/main.py +47 -3
- package/src/qingflow_mcp/errors.py +43 -2
- package/src/qingflow_mcp/public_surface.py +21 -15
- package/src/qingflow_mcp/response_trim.py +68 -13
- package/src/qingflow_mcp/server.py +11 -9
- package/src/qingflow_mcp/server_app_builder.py +3 -2
- package/src/qingflow_mcp/server_app_user.py +15 -13
- package/src/qingflow_mcp/solution/executor.py +112 -15
- package/src/qingflow_mcp/tools/ai_builder_tools.py +36 -11
- package/src/qingflow_mcp/tools/app_tools.py +184 -43
- package/src/qingflow_mcp/tools/approval_tools.py +196 -34
- package/src/qingflow_mcp/tools/auth_tools.py +92 -16
- package/src/qingflow_mcp/tools/code_block_tools.py +296 -39
- package/src/qingflow_mcp/tools/custom_button_tools.py +64 -10
- package/src/qingflow_mcp/tools/directory_tools.py +236 -72
- package/src/qingflow_mcp/tools/export_tools.py +230 -33
- package/src/qingflow_mcp/tools/file_tools.py +7 -3
- package/src/qingflow_mcp/tools/import_tools.py +293 -40
- package/src/qingflow_mcp/tools/navigation_tools.py +91 -12
- package/src/qingflow_mcp/tools/package_tools.py +118 -6
- package/src/qingflow_mcp/tools/portal_tools.py +39 -3
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +116 -7
- package/src/qingflow_mcp/tools/record_tools.py +1042 -338
- package/src/qingflow_mcp/tools/resource_read_tools.py +188 -39
- package/src/qingflow_mcp/tools/role_tools.py +80 -9
- package/src/qingflow_mcp/tools/solution_tools.py +57 -15
- package/src/qingflow_mcp/tools/task_context_tools.py +569 -119
- package/src/qingflow_mcp/tools/task_tools.py +113 -29
- package/src/qingflow_mcp/tools/view_tools.py +106 -3
- package/src/qingflow_mcp/tools/workflow_tools.py +17 -1
- package/src/qingflow_mcp/tools/workspace_tools.py +71 -3
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Update Layout
|
|
2
|
+
|
|
3
|
+
Use this when fields already exist and the task is only about form grouping or ordering.
|
|
4
|
+
|
|
5
|
+
## Minimal sequence
|
|
6
|
+
|
|
7
|
+
1. `app_get_fields`
|
|
8
|
+
2. `app_get_layout`
|
|
9
|
+
3. `builder_tool_contract` when the section shape is not already obvious
|
|
10
|
+
4. `app_layout_apply`
|
|
11
|
+
|
|
12
|
+
## Example
|
|
13
|
+
|
|
14
|
+
Apply a custom layout with the canonical public section shape:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"tool_name": "app_layout_apply",
|
|
19
|
+
"arguments": {
|
|
20
|
+
"profile": "default",
|
|
21
|
+
"app_key": "APP_123",
|
|
22
|
+
"mode": "merge",
|
|
23
|
+
"publish": true,
|
|
24
|
+
"sections": [
|
|
25
|
+
{
|
|
26
|
+
"title": "基础信息",
|
|
27
|
+
"rows": [
|
|
28
|
+
["客户名称", "订单金额"],
|
|
29
|
+
["状态", "跟进日期"]
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Common failures
|
|
38
|
+
|
|
39
|
+
### `UNKNOWN_LAYOUT_FIELD`
|
|
40
|
+
|
|
41
|
+
At least one field name does not exist. Re-read with `app_get_fields`.
|
|
42
|
+
|
|
43
|
+
### `DUPLICATE_LAYOUT_FIELD`
|
|
44
|
+
|
|
45
|
+
The same field appears more than once in the requested layout.
|
|
46
|
+
|
|
47
|
+
### `INCOMPLETE_LAYOUT`
|
|
48
|
+
|
|
49
|
+
Only happens in `mode=replace`. Switch to `mode=merge` unless you intend to place every field exactly once.
|
|
50
|
+
|
|
51
|
+
### `LAYOUT_APPLY_FAILED`
|
|
52
|
+
|
|
53
|
+
Re-read with `app_get_layout`. Check `current_field_names`, `request_id`, and `suggested_next_call`.
|
|
54
|
+
|
|
55
|
+
### `VALIDATION_ERROR`
|
|
56
|
+
|
|
57
|
+
Do not keep guessing section keys. Reuse `suggested_next_call`, `canonical_arguments`, `section_allowed_keys`, and `minimal_section_example`.
|
|
58
|
+
|
|
59
|
+
If the same shape error repeats twice, stop free-form retries and re-read `builder_tool_contract(app_layout_apply)`.
|
|
60
|
+
|
|
61
|
+
## Notes
|
|
62
|
+
|
|
63
|
+
- `section_id` is optional; it is generated from the section title
|
|
64
|
+
- `merge` is safer than `replace`
|
|
65
|
+
- Unmentioned fields stay in place or get auto-added to `未分组字段`
|
|
66
|
+
- Public builder layout sections use `title + rows`
|
|
67
|
+
- Do not treat “一行四个字段 / 四列布局 / 每行放四个” as a top-level `columns` parameter; translate it into a `rows` matrix
|
|
68
|
+
- Do not prefer `fields` or `field_ids` once `rows` is known, even though MCP may normalize those shorthands for recovery
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Update Schema
|
|
2
|
+
|
|
3
|
+
Use this when the app already exists and the task is only about fields.
|
|
4
|
+
|
|
5
|
+
## Minimal sequence
|
|
6
|
+
|
|
7
|
+
1. `app_resolve`
|
|
8
|
+
2. `app_get_fields`
|
|
9
|
+
3. `app_schema_apply`
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
|
|
13
|
+
Read current fields first:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"tool_name": "app_get_fields",
|
|
18
|
+
"arguments": {
|
|
19
|
+
"profile": "default",
|
|
20
|
+
"app_key": "APP_123"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Apply the patch:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"tool_name": "app_schema_apply",
|
|
30
|
+
"arguments": {
|
|
31
|
+
"profile": "default",
|
|
32
|
+
"app_key": "APP_123",
|
|
33
|
+
"publish": true,
|
|
34
|
+
"add_fields": [
|
|
35
|
+
{"name": "跟进日期", "type": "date"},
|
|
36
|
+
{"name": "数据封面", "type": "attachment", "as_data_cover": true}
|
|
37
|
+
],
|
|
38
|
+
"update_fields": [
|
|
39
|
+
{"selector": {"name": "金额"}, "set": {"name": "订单金额", "required": true}},
|
|
40
|
+
{"selector": {"name": "客户名称"}, "set": {"as_data_title": true}}
|
|
41
|
+
],
|
|
42
|
+
"remove_fields": [
|
|
43
|
+
{"name": "旧字段"}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Common failures
|
|
50
|
+
|
|
51
|
+
### `FIELD_NOT_FOUND`
|
|
52
|
+
|
|
53
|
+
The selector did not match current schema. Re-read with `app_get_fields` and use `name`, `field_id`, or `que_id`.
|
|
54
|
+
|
|
55
|
+
### `DUPLICATE_FIELD`
|
|
56
|
+
|
|
57
|
+
The field already exists with a different shape. Switch from `add_fields` to `update_fields`.
|
|
58
|
+
|
|
59
|
+
### `SCHEMA_APPLY_FAILED`
|
|
60
|
+
|
|
61
|
+
Treat it as uncertain write state. Read back with `app_get_fields` before retrying.
|
|
62
|
+
|
|
63
|
+
## Notes
|
|
64
|
+
|
|
65
|
+
- `title` and `label` are accepted aliases for `name`
|
|
66
|
+
- `textarea -> long_text`
|
|
67
|
+
- `currency -> amount`
|
|
68
|
+
- `mobile -> phone`
|
|
69
|
+
- `select/radio -> single_select`
|
|
70
|
+
- `checkbox -> multi_select`
|
|
71
|
+
- `as_data_title: true` marks the app data title; the final form must have exactly one top-level data title field
|
|
72
|
+
- `as_data_cover: true` marks the app data cover; the cover is optional and must be a top-level `attachment` field
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# Update Views
|
|
2
|
+
|
|
3
|
+
Use this when the task is only about table, card, board, or gantt views.
|
|
4
|
+
|
|
5
|
+
## Minimal sequence
|
|
6
|
+
|
|
7
|
+
1. `builder_tool_contract(tool_name="app_views_apply")`
|
|
8
|
+
2. `app_get_fields`
|
|
9
|
+
3. `app_get` for current view/chart/button inventory and app-level associated resource ids
|
|
10
|
+
4. `app_views_apply`
|
|
11
|
+
5. Use `app_associated_resources_apply` if the task includes associated reports/views
|
|
12
|
+
6. `app_get` or `view_get` again whenever apply returns `failed` or `partial_success`
|
|
13
|
+
|
|
14
|
+
If you are unsure about keys or view types, call `builder_tool_contract(tool_name="app_views_apply")` before guessing.
|
|
15
|
+
|
|
16
|
+
Important verification rule:
|
|
17
|
+
|
|
18
|
+
- `app_views_apply` can create a view object before every filter is fully verified in readback
|
|
19
|
+
- Do not report “筛选已成功应用” unless the apply result also shows `verification.views_verified=true` and `verification.view_filters_verified=true`
|
|
20
|
+
- Do not report “查询条件已成功配置” unless the apply result also shows `verification.view_query_conditions_verified=true`
|
|
21
|
+
- Do not report “关联资源已成功配置” unless `app_associated_resources_apply` shows `verification.associated_resource_view_configs_verified=true`
|
|
22
|
+
- If apply returns `partial_success`, inspect `verification.by_view`, `details.filter_mismatches`, `details.query_condition_mismatches`, and `details.associated_resource_mismatches` before claiming filters/query conditions/associated resources are active
|
|
23
|
+
|
|
24
|
+
## Example
|
|
25
|
+
|
|
26
|
+
Canonical rules before any example:
|
|
27
|
+
|
|
28
|
+
- Always use `columns`
|
|
29
|
+
- Do not emit `column_names`
|
|
30
|
+
- Treat `fields` only as a legacy alias the MCP may normalize, not as the preferred shape
|
|
31
|
+
- Use `filters` with canonical keys `field_name`, `operator`, `value`/`values`
|
|
32
|
+
- Use `query_conditions` for the frontend query panel. Do not put query-panel fields into `filters`.
|
|
33
|
+
- New views created by `app_views_apply` default the frontend associated report/view area to visible with `limit_type="all"`. Existing views preserve their current associated-resource display unless `associated_resources` is explicitly patched.
|
|
34
|
+
- Use `app_associated_resources_apply` for the associated report/view resource pool, selected resources, and match rules. Permission is split like the backend: resource pool writes use EditAppAuth, while `view_configs` uses the view config/DataManageAuth path. `associated_item_id` is the internal associated-resource id from `app_get.associated_resources`; `view_configs`, remove, and reorder may also pass an existing resource's `chart_id`/`chart_key`/`view_key`, which the tool resolves to the internal id. Do not write backend raw `sourceType`; reports default to BI app reports, and dataset reports use `report_source="dataset"`. Use `match_mappings` for associated view/report filters; read `match-rules.md` if field type compatibility is unclear.
|
|
35
|
+
- For gantt, use `start_field`, `end_field`, and optionally `title_field`
|
|
36
|
+
- If `app_get.views` or `app_get_views` shows duplicate view names, include `view_key` in `upsert_views[]` and update that exact target
|
|
37
|
+
- Builder view writes always use the raw `view_key` from `app_get.views[].view_key`, such as `emsrao25rs02`. Do not pass `custom:emsrao25rs02`; that prefixed form is only for record-data `view_id`.
|
|
38
|
+
- For an existing view, prefer `patch_views` for parameter replacement. Do not send a partial `upsert_views` object such as only `name/type/query_conditions`; backend view saves require other type-specific fields, and the patch path preserves them for you.
|
|
39
|
+
|
|
40
|
+
Apply a default table view:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"tool_name": "app_views_apply",
|
|
45
|
+
"arguments": {
|
|
46
|
+
"profile": "default",
|
|
47
|
+
"app_key": "APP_123",
|
|
48
|
+
"publish": true,
|
|
49
|
+
"upsert_views": [
|
|
50
|
+
{
|
|
51
|
+
"name": "全部订单",
|
|
52
|
+
"view_key": "VIEW_KEY_IF_DUPLICATE_NAMES_EXIST",
|
|
53
|
+
"type": "table",
|
|
54
|
+
"columns": ["订单编号", "客户名称", "订单金额", "状态"]
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"remove_views": []
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
After `app_views_apply` returns canonical arguments or blocking issues, prefer reusing its `suggested_next_call.arguments` directly. Do not rewrite aliases back into non-canonical keys such as `column_names`.
|
|
62
|
+
|
|
63
|
+
Existing table view: replace only frontend query conditions:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"tool_name": "app_views_apply",
|
|
68
|
+
"arguments": {
|
|
69
|
+
"profile": "default",
|
|
70
|
+
"app_key": "APP_123",
|
|
71
|
+
"publish": true,
|
|
72
|
+
"patch_views": [
|
|
73
|
+
{
|
|
74
|
+
"view_key": "VIEW_KEY",
|
|
75
|
+
"set": {
|
|
76
|
+
"query_conditions": {
|
|
77
|
+
"enabled": true,
|
|
78
|
+
"exact": false,
|
|
79
|
+
"hide_before_query": false,
|
|
80
|
+
"rows": [["客户名称", "负责人"], ["创建时间"]]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"remove_views": []
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Meaning:
|
|
91
|
+
|
|
92
|
+
- `filters` are saved view filters and apply immediately when the view opens.
|
|
93
|
+
- `query_conditions` only configures which fields appear in the frontend query panel. The query values come later from the user through the page.
|
|
94
|
+
- `query_conditions.rows` is a matrix of field names and is compiled to backend `queryCondition` field ids.
|
|
95
|
+
- The patch call preserves the view's existing columns, saved filters, type-specific date/card/board config, buttons, visibility, and other backend-required fields.
|
|
96
|
+
|
|
97
|
+
View associated resources example:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"tool_name": "app_associated_resources_apply",
|
|
102
|
+
"arguments": {
|
|
103
|
+
"profile": "default",
|
|
104
|
+
"app_key": "APP_123",
|
|
105
|
+
"upsert_resources": [],
|
|
106
|
+
"remove_associated_item_ids": [],
|
|
107
|
+
"reorder_associated_item_ids": [],
|
|
108
|
+
"view_configs": [
|
|
109
|
+
{
|
|
110
|
+
"view_key": "VIEW_KEY",
|
|
111
|
+
"visible": true,
|
|
112
|
+
"limit_type": "select",
|
|
113
|
+
"associated_item_ids": [123, 124]
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Use `{"visible": true, "limit_type": "all"}` to show all app-level associated resources, and `{"visible": false}` to hide the area. The ids above can be internal `associated_item_id` values or existing resource `chart_id`/`chart_key`/`view_key` values from `app_get.associated_resources`. Before creating a resource, check whether the same `target_app_key + view_key/chart_key` already exists; if it does, use `patch_resources` with that `associated_item_id`. Dataset BI reports must already exist in QingBI and should be attached with `report_source="dataset"`; do not try to create them through `app_charts_apply`. If you create a new associated item in the same call, give it a `client_key` and reference it from `view_configs[].associated_item_refs`; `client_key` is not persisted and cannot deduplicate a later call.
|
|
121
|
+
|
|
122
|
+
Create and show a BI indicator-card report in the same call:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"tool_name": "app_associated_resources_apply",
|
|
127
|
+
"arguments": {
|
|
128
|
+
"profile": "default",
|
|
129
|
+
"app_key": "APP_123",
|
|
130
|
+
"upsert_resources": [
|
|
131
|
+
{
|
|
132
|
+
"client_key": "total_hours_card",
|
|
133
|
+
"graph_type": "chart",
|
|
134
|
+
"target_app_key": "TIMESHEET_APP",
|
|
135
|
+
"chart_key": "CHART_KEY",
|
|
136
|
+
"report_source": "app",
|
|
137
|
+
"match_mappings": [
|
|
138
|
+
{"target_field": "关联员工", "source_field": "数据ID"},
|
|
139
|
+
{"target_field": "状态", "value": "待提交"}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"remove_associated_item_ids": [],
|
|
144
|
+
"reorder_associated_item_ids": [],
|
|
145
|
+
"view_configs": [
|
|
146
|
+
{
|
|
147
|
+
"view_key": "VIEW_KEY",
|
|
148
|
+
"visible": true,
|
|
149
|
+
"limit_type": "select",
|
|
150
|
+
"associated_item_refs": ["total_hours_card"]
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Board example:
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"tool_name": "app_views_apply",
|
|
162
|
+
"arguments": {
|
|
163
|
+
"profile": "default",
|
|
164
|
+
"app_key": "APP_123",
|
|
165
|
+
"upsert_views": [
|
|
166
|
+
{
|
|
167
|
+
"name": "按状态看板",
|
|
168
|
+
"type": "board",
|
|
169
|
+
"group_by": "状态",
|
|
170
|
+
"columns": ["订单编号", "客户名称", "订单金额"]
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
"remove_views": []
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Gantt example with filters:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"tool_name": "app_views_apply",
|
|
183
|
+
"arguments": {
|
|
184
|
+
"profile": "default",
|
|
185
|
+
"app_key": "APP_123",
|
|
186
|
+
"upsert_views": [
|
|
187
|
+
{
|
|
188
|
+
"name": "项目甘特图",
|
|
189
|
+
"type": "gantt",
|
|
190
|
+
"columns": ["项目名称", "开始日期", "结束日期", "状态"],
|
|
191
|
+
"start_field": "开始日期",
|
|
192
|
+
"end_field": "结束日期",
|
|
193
|
+
"title_field": "项目名称",
|
|
194
|
+
"filters": [
|
|
195
|
+
{
|
|
196
|
+
"field_name": "状态",
|
|
197
|
+
"operator": "eq",
|
|
198
|
+
"value": "进行中"
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
"remove_views": []
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Common failures
|
|
209
|
+
|
|
210
|
+
### `UNKNOWN_VIEW_FIELD`
|
|
211
|
+
|
|
212
|
+
At least one `columns` or `group_by` field name does not exist.
|
|
213
|
+
|
|
214
|
+
### `INVALID_VIEW_TYPE`
|
|
215
|
+
|
|
216
|
+
Public view types are only `table`, `card`, `board`, `gantt`.
|
|
217
|
+
|
|
218
|
+
Map old or intuitive labels before calling the tool:
|
|
219
|
+
|
|
220
|
+
- `tableView` -> `table`
|
|
221
|
+
- `cardView` -> `card`
|
|
222
|
+
- `kanban` -> `board`
|
|
223
|
+
|
|
224
|
+
### `INVALID_GANTT_CONFIG`
|
|
225
|
+
|
|
226
|
+
Gantt views require at least:
|
|
227
|
+
|
|
228
|
+
- `start_field`
|
|
229
|
+
- `end_field`
|
|
230
|
+
|
|
231
|
+
Also make sure these field names already exist on the app.
|
|
232
|
+
|
|
233
|
+
### `VIEW_APPLY_FAILED`
|
|
234
|
+
|
|
235
|
+
The backend rejected the normalized view payload. Re-read fields and inspect `request_id` before retrying.
|
|
236
|
+
|
|
237
|
+
Do not repeat `app_views_apply` with guessed keys. First:
|
|
238
|
+
|
|
239
|
+
1. check `suggested_next_call`
|
|
240
|
+
2. reuse `canonical_arguments` if present
|
|
241
|
+
3. call `app_get_views` to see whether any requested views landed anyway
|
|
242
|
+
4. if needed, call `builder_tool_contract`
|
|
243
|
+
5. retry only the minimal failed view patch
|
|
244
|
+
|
|
245
|
+
### `VIEW_FILTER_READBACK_MISMATCH`
|
|
246
|
+
|
|
247
|
+
The view object was created or updated, but the readback config did not keep the intended filter values.
|
|
248
|
+
|
|
249
|
+
Treat this as:
|
|
250
|
+
|
|
251
|
+
- the view exists
|
|
252
|
+
- the filter is **not yet verified**
|
|
253
|
+
|
|
254
|
+
Do not tell the user the filter is active until the readback verification matches the intended filter.
|
|
255
|
+
|
|
256
|
+
### `VIEW_QUERY_CONDITION_READBACK_MISMATCH`
|
|
257
|
+
|
|
258
|
+
The view object was created or updated, but the readback config did not keep the intended frontend query-condition settings.
|
|
259
|
+
|
|
260
|
+
Treat this as:
|
|
261
|
+
|
|
262
|
+
- the view exists
|
|
263
|
+
- the query panel configuration is **not yet verified**
|
|
264
|
+
|
|
265
|
+
Do not tell the user the query condition is active until readback matches the intended `query_conditions`.
|
|
266
|
+
|
|
267
|
+
### `QUERY_CONDITION_FIELD_NOT_FOUND`
|
|
268
|
+
|
|
269
|
+
At least one `query_conditions.rows` field does not exist on the app.
|
|
270
|
+
|
|
271
|
+
### `INVALID_QUERY_CONDITION_FIELD`
|
|
272
|
+
|
|
273
|
+
The field exists but cannot be used in the frontend query-condition panel, such as attachment, relation, Q-Linker, code block, location/address, or subtable/subfield selections.
|
|
274
|
+
|
|
275
|
+
## Notes
|
|
276
|
+
|
|
277
|
+
- `fields` is accepted as an alias for `columns`, but skill examples should still use `columns`
|
|
278
|
+
- `column_names` should not appear in skill examples
|
|
279
|
+
- `app_get_views` should be treated as canonical readback and now returns `columns`
|
|
280
|
+
- If `app_views_apply` returns `AMBIGUOUS_VIEW`, stop and re-run `app_get_views`; then retry with the exact `view_key`
|
|
281
|
+
- `filters` are ANDed together as one flat condition group
|
|
282
|
+
- `query_conditions.rows` does not mean OR; it controls frontend query-field layout
|
|
283
|
+
- `app_views_apply` publishes by default
|
|
284
|
+
- For select-style filters, success means the backend preserved the option value in readback, not just that the view name now exists
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qingflow-app-builder-code-integrations
|
|
3
|
+
description: Configure Qingflow code block and Q-Linker fields through the builder surface when the task involves input field insertion, alias parsing, target field binding, or troubleshooting broken code/q-linker form configurations. In Wingent Momo runtime, use the injected MCP session and recover auth/workspace only after a tool error.
|
|
4
|
+
metadata:
|
|
5
|
+
short-description: Configure Qingflow code blocks and Q-Linkers safely
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Qingflow App Builder Code Integrations
|
|
9
|
+
|
|
10
|
+
Use this skill when the user wants to build or repair:
|
|
11
|
+
- `code_block` fields
|
|
12
|
+
- `q_linker` fields
|
|
13
|
+
- output alias parsing
|
|
14
|
+
- target field binding
|
|
15
|
+
- form configurations that depend on code block or Q-Linker relations
|
|
16
|
+
|
|
17
|
+
Do not use this skill for MCP setup, generic field CRUD, or runtime execution debugging unless those are strictly supporting code block or Q-Linker configuration work.
|
|
18
|
+
|
|
19
|
+
## Core Rule
|
|
20
|
+
|
|
21
|
+
Treat code blocks and Q-Linkers as **integration fields**, not ordinary fields.
|
|
22
|
+
|
|
23
|
+
For both of them, the public builder request may look like one step, but the real backend form structure has multiple layers. Never invent a new backend meaning. Only compile into the backend structures that already exist.
|
|
24
|
+
|
|
25
|
+
## Mental Model
|
|
26
|
+
|
|
27
|
+
### Code block
|
|
28
|
+
|
|
29
|
+
There are three conceptual layers:
|
|
30
|
+
|
|
31
|
+
1. Code block field itself
|
|
32
|
+
2. Parsed output aliases
|
|
33
|
+
3. Target field bindings
|
|
34
|
+
|
|
35
|
+
Current builder support:
|
|
36
|
+
- configure the code block field itself
|
|
37
|
+
- configure input insertion into code content
|
|
38
|
+
- configure alias parsing
|
|
39
|
+
|
|
40
|
+
Important:
|
|
41
|
+
- keep `qf_output = {...}` as a plain assignment
|
|
42
|
+
- do not emit `const qf_output =` or `let qf_output =`
|
|
43
|
+
|
|
44
|
+
### Q-Linker
|
|
45
|
+
|
|
46
|
+
There are two conceptual layers:
|
|
47
|
+
|
|
48
|
+
1. Q-Linker field itself via `remoteLookupConfig`
|
|
49
|
+
2. Target field bindings via relation-default + `questionRelations(relationType=Q_LINKER)`
|
|
50
|
+
|
|
51
|
+
Current builder support:
|
|
52
|
+
- one-step high-level config through `q_linker_binding`
|
|
53
|
+
- internal compilation into existing backend payloads
|
|
54
|
+
|
|
55
|
+
## Operating Order
|
|
56
|
+
|
|
57
|
+
For code block or Q-Linker work, use this order:
|
|
58
|
+
|
|
59
|
+
1. Resolve the app and read fields:
|
|
60
|
+
- `app_resolve`
|
|
61
|
+
- `app_get_fields`
|
|
62
|
+
2. Confirm the target field set already exists.
|
|
63
|
+
3. Apply schema updates with `app_schema_apply`.
|
|
64
|
+
4. Read fields again and verify:
|
|
65
|
+
- field type
|
|
66
|
+
- alias config
|
|
67
|
+
- target field binding shape
|
|
68
|
+
5. For page-safety checks, use user-side schema or insert checks:
|
|
69
|
+
- `record_insert_schema_get`
|
|
70
|
+
- optional safe `record_insert`
|
|
71
|
+
|
|
72
|
+
Do not treat raw apply success as enough. Always re-read the field config.
|
|
73
|
+
|
|
74
|
+
## Code Block Rules
|
|
75
|
+
|
|
76
|
+
Read [references/code-block.md](references/code-block.md) before changing a code block field.
|
|
77
|
+
|
|
78
|
+
Use builder high-level config only for:
|
|
79
|
+
- input field insertion
|
|
80
|
+
- code content
|
|
81
|
+
- alias parsing
|
|
82
|
+
- auto trigger
|
|
83
|
+
- custom button text
|
|
84
|
+
|
|
85
|
+
When binding outputs to target fields, do not guess payload shape from memory. Follow the current builder implementation and the readback shape.
|
|
86
|
+
|
|
87
|
+
Hard rules:
|
|
88
|
+
- target fields must already exist
|
|
89
|
+
- keep target field types business-compatible
|
|
90
|
+
- if a page starts hanging on “关联中”, inspect whether the target field default type or relation config was written incorrectly
|
|
91
|
+
|
|
92
|
+
## Q-Linker Rules
|
|
93
|
+
|
|
94
|
+
Read [references/q-linker.md](references/q-linker.md) before changing a Q-Linker field.
|
|
95
|
+
|
|
96
|
+
First-stage stable support is only:
|
|
97
|
+
- custom mode
|
|
98
|
+
- request config
|
|
99
|
+
- alias parsing
|
|
100
|
+
- target field binding
|
|
101
|
+
- auto trigger / button text
|
|
102
|
+
|
|
103
|
+
Do not generate:
|
|
104
|
+
- template mode
|
|
105
|
+
- openApp/light-wing branches
|
|
106
|
+
- subtable table-match bindings
|
|
107
|
+
|
|
108
|
+
Hard rules:
|
|
109
|
+
- `outputs[*].target_field` is required
|
|
110
|
+
- use only supported target field types
|
|
111
|
+
- on rebinding, old target fields must be restored from relation-default to safe default type
|
|
112
|
+
- `resultFormatPath` must preserve backend-required alias metadata
|
|
113
|
+
|
|
114
|
+
## Verification Checklist
|
|
115
|
+
|
|
116
|
+
After each code block or Q-Linker change, verify all of these:
|
|
117
|
+
|
|
118
|
+
- `app_get_fields` shows the intended field type
|
|
119
|
+
- the high-level config is readable and stable
|
|
120
|
+
- target fields still have valid types
|
|
121
|
+
- insert schema can be opened
|
|
122
|
+
- record insert does not get blocked by malformed integration config
|
|
123
|
+
|
|
124
|
+
If the task explicitly includes runtime verification, keep it separate from configuration verification.
|
|
125
|
+
|
|
126
|
+
## Common Pitfalls
|
|
127
|
+
|
|
128
|
+
- Writing code block code with `const qf_output =`
|
|
129
|
+
- Treating a Q-Linker or code block binding as a plain field default
|
|
130
|
+
- Forgetting to restore old target fields after unbinding
|
|
131
|
+
- Using unsupported target field types
|
|
132
|
+
- Assuming apply success means the form page can open
|
|
133
|
+
|
|
134
|
+
## References
|
|
135
|
+
|
|
136
|
+
- Code block details: [references/code-block.md](references/code-block.md)
|
|
137
|
+
- Q-Linker details: [references/q-linker.md](references/q-linker.md)
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Qingflow Code Integrations"
|
|
3
|
+
short_description: "Configure Qingflow code block and Q-Linker fields safely"
|
|
4
|
+
default_prompt: "Use $qingflow-app-builder-code-integrations when configuring Qingflow code block or Q-Linker fields, especially when input insertion, alias parsing, target field binding, or page-safety verification matter."
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Code Block Builder Notes
|
|
2
|
+
|
|
3
|
+
## What Builder Should Configure
|
|
4
|
+
|
|
5
|
+
- code block field type
|
|
6
|
+
- code content
|
|
7
|
+
- inserted input fields inside code content
|
|
8
|
+
- alias parsing
|
|
9
|
+
- auto trigger
|
|
10
|
+
- custom button text
|
|
11
|
+
|
|
12
|
+
## Stable Writing Rules
|
|
13
|
+
|
|
14
|
+
- Always emit `qf_output = {...}`
|
|
15
|
+
- Never emit `const qf_output = {...}`
|
|
16
|
+
- Never emit `let qf_output = {...}`
|
|
17
|
+
|
|
18
|
+
## Useful CRM Pattern
|
|
19
|
+
|
|
20
|
+
Inputs:
|
|
21
|
+
- customer name
|
|
22
|
+
- source
|
|
23
|
+
- budget
|
|
24
|
+
- timing
|
|
25
|
+
- decision-maker flag
|
|
26
|
+
|
|
27
|
+
Outputs:
|
|
28
|
+
- score
|
|
29
|
+
- level
|
|
30
|
+
- priority
|
|
31
|
+
- summary
|
|
32
|
+
- next follow date
|
|
33
|
+
|
|
34
|
+
## Target Field Rules
|
|
35
|
+
|
|
36
|
+
Required:
|
|
37
|
+
- every `outputs[*].target_field` must point to an existing field
|
|
38
|
+
|
|
39
|
+
Allowed target field types:
|
|
40
|
+
- text
|
|
41
|
+
- long text
|
|
42
|
+
- number
|
|
43
|
+
- amount
|
|
44
|
+
- date
|
|
45
|
+
- datetime
|
|
46
|
+
- single select
|
|
47
|
+
- multi select
|
|
48
|
+
- boolean
|
|
49
|
+
|
|
50
|
+
Do not bind code block outputs to:
|
|
51
|
+
- q_linker
|
|
52
|
+
- code_block
|
|
53
|
+
- relation
|
|
54
|
+
- subtable
|
|
55
|
+
- attachment
|
|
56
|
+
- member
|
|
57
|
+
- department
|
|
58
|
+
- address
|
|
59
|
+
|
|
60
|
+
## Safe Verification
|
|
61
|
+
|
|
62
|
+
- `app_get_fields`
|
|
63
|
+
- `record_insert_schema_get`
|
|
64
|
+
- optional `record_code_block_run`
|
|
65
|
+
|
|
66
|
+
Treat configuration verification and runtime verification as separate checks.
|