@josephyan/qingflow-app-user-mcp 1.1.26 → 1.1.28

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.
Files changed (47) hide show
  1. package/README.md +4 -6
  2. package/package.json +1 -1
  3. package/pyproject.toml +1 -1
  4. package/skills/qingflow-app-user/SKILL.md +5 -3
  5. package/skills/qingflow-app-user/references/public-surface-sync.md +4 -2
  6. package/src/qingflow_mcp/builder_facade/models.py +167 -71
  7. package/src/qingflow_mcp/builder_facade/service.py +617 -155
  8. package/src/qingflow_mcp/cli/commands/builder.py +3 -1
  9. package/src/qingflow_mcp/cli/main.py +8 -3
  10. package/src/qingflow_mcp/server_app_builder.py +9 -8
  11. package/src/qingflow_mcp/tools/ai_builder_tools.py +231 -180
  12. package/src/qingflow_mcp/version.py +2 -0
  13. package/skills/qingflow-app-builder/SKILL.md +0 -277
  14. package/skills/qingflow-app-builder/agents/openai.yaml +0 -4
  15. package/skills/qingflow-app-builder/references/build-complete-system.md +0 -428
  16. package/skills/qingflow-app-builder/references/build-single-app.md +0 -530
  17. package/skills/qingflow-app-builder/references/create-app.md +0 -149
  18. package/skills/qingflow-app-builder/references/environments.md +0 -63
  19. package/skills/qingflow-app-builder/references/flow-actors-and-permissions.md +0 -123
  20. package/skills/qingflow-app-builder/references/gotchas.md +0 -108
  21. package/skills/qingflow-app-builder/references/match-rules.md +0 -114
  22. package/skills/qingflow-app-builder/references/public-surface-sync.md +0 -75
  23. package/skills/qingflow-app-builder/references/solution-playbooks.md +0 -52
  24. package/skills/qingflow-app-builder/references/tool-selection.md +0 -107
  25. package/skills/qingflow-app-builder/references/update-flow.md +0 -186
  26. package/skills/qingflow-app-builder/references/update-layout.md +0 -68
  27. package/skills/qingflow-app-builder/references/update-schema.md +0 -72
  28. package/skills/qingflow-app-builder/references/update-views.md +0 -291
  29. package/skills/qingflow-app-builder-code-integrations/SKILL.md +0 -137
  30. package/skills/qingflow-app-builder-code-integrations/agents/openai.yaml +0 -4
  31. package/skills/qingflow-app-builder-code-integrations/references/code-block.md +0 -66
  32. package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +0 -77
  33. package/skills/qingflow-workflow-builder/SKILL.md +0 -96
  34. package/skills/qingflow-workflow-builder/manifest.yaml +0 -8
  35. package/skills/qingflow-workflow-builder/references/01-overview.md +0 -45
  36. package/skills/qingflow-workflow-builder/references/02-update-mode.md +0 -53
  37. package/skills/qingflow-workflow-builder/references/03-flow-patterns.md +0 -57
  38. package/skills/qingflow-workflow-builder/references/04-stage1-business-modeling.md +0 -131
  39. package/skills/qingflow-workflow-builder/references/05-stage2-members-roles.md +0 -29
  40. package/skills/qingflow-workflow-builder/references/06-stage3-build-spec.md +0 -165
  41. package/skills/qingflow-workflow-builder/references/07-stage4-validate-spec.md +0 -33
  42. package/skills/qingflow-workflow-builder/references/08-stage5-apply-verify.md +0 -51
  43. package/skills/qingflow-workflow-builder/references/09-stage6-summary.md +0 -88
  44. package/skills/qingflow-workflow-builder/references/10-node-config-reference.md +0 -93
  45. package/skills/qingflow-workflow-builder/references/11-troubleshooting.md +0 -15
  46. package/skills/qingflow-workflow-builder/scripts/diff_flow_spec.py +0 -275
  47. package/skills/qingflow-workflow-builder/scripts/validate_flow_spec.py +0 -605
@@ -1,186 +0,0 @@
1
- # Update Flow
2
-
3
- Use this when the app already exists and the task is only about workflow.
4
-
5
- ## Minimal sequence
6
-
7
- 1. `builder_tool_contract(tool_name="app_flow_apply")`
8
- 2. `app_get_fields`
9
- 3. `app_get_flow`
10
- 4. `role_search` or `member_search`
11
- 5. `role_create` if the user wants a reusable directory role and no good role exists
12
- 6. start from a canonical preset when possible
13
- 7. patch the skeleton instead of freehanding a full graph
14
- 8. reuse preset node ids when patching:
15
- - `basic_approval` -> patch `approve_1`
16
- - `basic_fill_then_approve` -> patch `fill_1` and `approve_1`
17
- Do not add a second approval/fill node with a new id unless you are intentionally replacing the skeleton.
18
- The MCP now auto-aligns the simplest single-node preset overrides, but still prefer explicit preset ids so the merged graph stays predictable.
19
- 9. `app_flow_apply`
20
- 10. `app_get_flow` when apply returns `partial_success` or the user asked for verification
21
-
22
- If you are unsure about presets or node shapes, call `builder_tool_contract(tool_name="app_flow_apply")` before guessing.
23
-
24
- ## Example
25
-
26
- Canonical preset mapping:
27
-
28
- - “默认审批/基础审批/普通审批” -> `basic_approval`
29
- - “先填报再审批/提交后审批” -> `basic_fill_then_approve`
30
-
31
- Apply a simple approval flow with a role assignee and node-level editable fields:
32
-
33
- ```json
34
- {
35
- "tool_name": "app_flow_apply",
36
- "arguments": {
37
- "profile": "default",
38
- "app_key": "APP_123",
39
- "preset": "basic_approval",
40
- "publish": true,
41
- "nodes": [
42
- {
43
- "id": "approve_1",
44
- "type": "approve",
45
- "name": "部门审批",
46
- "assignees": {
47
- "role_names": ["项目经理"]
48
- },
49
- "permissions": {
50
- "editable_fields": ["状态", "审批意见"]
51
- }
52
- }
53
- ]
54
- }
55
- }
56
- ```
57
-
58
- For flexible business requirements, do not jump straight to a full custom graph. Use this safer pattern:
59
-
60
- 1. build a base skeleton from a preset
61
- 2. identify the business-specific changes
62
- 3. patch nodes/transitions explicitly
63
-
64
- ## Targeted node updates
65
-
66
- To change one or a few nodes without rewriting the full spec, use `patch_nodes[]` instead of `spec`:
67
-
68
- ```json
69
- {
70
- "tool_name": "app_flow_apply",
71
- "arguments": {
72
- "profile": "default",
73
- "app_key": "APP_123",
74
- "publish": true,
75
- "patch_nodes": [
76
- {
77
- "id": "approve_1",
78
- "set": {
79
- "name": "总监审批",
80
- "assignees": {"role_names": ["总监"]}
81
- }
82
- }
83
- ]
84
- }
85
- }
86
- ```
87
-
88
- `patch_nodes[]` reads the current flow, merges `set` keys and removes `unset` keys on the matched node, then writes the full spec back. It returns `FLOW_NODE_NOT_FOUND` if the `id` does not match any existing node — call `app_get_flow` first to confirm ids.
89
-
90
- Do NOT use `patch_nodes` and `spec` together in the same call.
91
-
92
- Public flow building is intentionally limited to linear workflows. Use only:
93
-
94
- - `start`
95
- - `approve`
96
- - `fill`
97
- - `copy`
98
- - `webhook`
99
- - `end`
100
-
101
- Do not generate `branch` or `condition` nodes through `app_flow_apply`. The backend workflow route is not front-end stable for those node types, and MCP now returns `FLOW_NODE_TYPE_UNSUPPORTED` instead of writing a visually broken flow.
102
- After `app_flow_apply` returns blocking issues or canonical arguments, prefer reusing its `suggested_next_call.arguments` directly. Do not rewrite the result into internal fields such as `role_entries` or `editable_que_ids`.
103
- When you patch a preset, patch the preset node itself. Do not leave the preset approval node unassigned while adding a second custom approval node.
104
-
105
- ## Common failures
106
-
107
- ### `FLOW_ASSIGNEE_REQUIRED`
108
-
109
- Approval, fill, and copy nodes must declare at least one assignee.
110
-
111
- If this happens after using a preset, check for this specific mistake first:
112
-
113
- - the preset created `approve_1` or `fill_1`
114
- - your patch created a different node id instead of patching that preset node
115
- - the original preset node remained in the graph without assignees
116
-
117
- Preferred fix order:
118
-
119
- 1. `role_search`
120
- 2. `member_search` only if the user explicitly named members
121
- 3. `role_create` if the business needs a reusable role
122
- 4. patch the preset node id itself with canonical `assignees.*`
123
- 5. retry `app_flow_apply`
124
-
125
- ### `FLOW_DEPENDENCY_MISSING`
126
-
127
- The workflow depends on fields that do not exist yet, usually `status`. Fix schema first.
128
-
129
- Preferred recovery:
130
-
131
- 1. use the returned `suggested_next_call`
132
- 2. apply the minimal schema patch
133
- 3. rerun `app_get_fields`
134
- 4. rerun `app_flow_apply`
135
-
136
- ### `INVALID_FLOW_EDGE`
137
-
138
- One or more transitions reference unknown nodes or create an invalid graph.
139
-
140
- ### `UNKNOWN_FLOW_FIELD`
141
-
142
- The workflow referenced a field name that does not exist, often in:
143
-
144
- - `permissions.editable_fields`
145
-
146
- Call `app_get_fields` and retry with the exact field names returned by the app.
147
-
148
- ### `FLOW_NODE_TYPE_UNSUPPORTED`
149
-
150
- The public workflow builder only supports linear flows. Remove `branch` and `condition` nodes and redesign the flow with stable sequential nodes instead of retrying the same graph.
151
-
152
- ### `STATUS_FIELD_REQUIRED`
153
-
154
- The app has no explicit status field recognized by the internal workflow compiler. Add one with `app_schema_apply`, then retry.
155
-
156
- ### `FLOW_STAGE_CONTEXT_MISSING`
157
-
158
- Internal flow stage context was missing or invalid. Re-run `app_flow_apply` with the normalized arguments, and do not switch to hidden `solution_*` tools.
159
-
160
- ### `VALIDATION_ERROR`
161
-
162
- Do not keep guessing preset names or node shapes. First:
163
-
164
- 1. inspect `suggested_next_call`
165
- 2. reuse `canonical_arguments` if present
166
- 3. check `allowed_values`
167
- 4. retry with canonical preset or canonical node types
168
- 5. for workflow actors and permissions, always convert to:
169
- - `assignees.role_names`
170
- - `assignees.member_names`
171
- - `permissions.editable_fields`
172
-
173
- Do not copy internal keys from old plan outputs or logs, including:
174
-
175
- - `role_entries`
176
- - `editable_que_ids`
177
-
178
- ## Notes
179
-
180
- - `mode=replace` is the only supported flow apply mode when using `spec`; `patch_nodes[]` does not require a `mode`
181
- - `app_flow_apply` publishes by default
182
- - Prefer roles over explicit members unless the user explicitly asks for named members
183
- - `basic_approval` and `basic_fill_then_approve` are skeletons, not complete business workflows
184
- - Report results precisely:
185
- - “基础流程骨架已创建” when only the preset landed
186
- - “业务定制规则已补齐” only after the patch phase is complete
@@ -1,68 +0,0 @@
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
@@ -1,72 +0,0 @@
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
@@ -1,291 +0,0 @@
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
- - When creating any new table or card view, always include `query_conditions` with `enabled: true`. In `rows`, list the fields users would most commonly search by — typically the data-title field, any status/type select fields, date fields, and member fields. Do not omit `query_conditions` or leave `rows` empty on a new view.
34
- - 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.
35
- - Use `app_associated_resources_apply` for the associated report/view resource pool, selected resources, and match rules. `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.
36
- - For gantt, use `start_field`, `end_field`, and optionally `title_field`
37
- - If `app_get.views` or `app_get_views` shows duplicate view names, include `view_key` in `upsert_views[]` and update that exact target
38
- - 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`.
39
- - 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.
40
-
41
- Apply a default table view:
42
-
43
- ```json
44
- {
45
- "tool_name": "app_views_apply",
46
- "arguments": {
47
- "profile": "default",
48
- "app_key": "APP_123",
49
- "publish": true,
50
- "upsert_views": [
51
- {
52
- "name": "全部订单",
53
- "view_key": "VIEW_KEY_IF_DUPLICATE_NAMES_EXIST",
54
- "type": "table",
55
- "columns": ["订单编号", "客户名称", "订单金额", "状态", "负责人", "创建时间"],
56
- "query_conditions": {
57
- "enabled": true,
58
- "exact": false,
59
- "hide_before_query": false,
60
- "rows": [["订单编号", "客户名称"], ["状态", "负责人"], ["创建时间"]]
61
- }
62
- }
63
- ],
64
- "remove_views": []
65
- }
66
- }
67
- ```
68
- 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`.
69
-
70
- Existing table view: replace only frontend query conditions:
71
-
72
- ```json
73
- {
74
- "tool_name": "app_views_apply",
75
- "arguments": {
76
- "profile": "default",
77
- "app_key": "APP_123",
78
- "publish": true,
79
- "patch_views": [
80
- {
81
- "view_key": "VIEW_KEY",
82
- "set": {
83
- "query_conditions": {
84
- "enabled": true,
85
- "exact": false,
86
- "hide_before_query": false,
87
- "rows": [["客户名称", "负责人"], ["创建时间"]]
88
- }
89
- }
90
- }
91
- ],
92
- "remove_views": []
93
- }
94
- }
95
- ```
96
-
97
- Meaning:
98
-
99
- - `filters` are saved view filters and apply immediately when the view opens.
100
- - `query_conditions` only configures which fields appear in the frontend query panel. The query values come later from the user through the page.
101
- - `query_conditions.rows` is a matrix of field names and is compiled to backend `queryCondition` field ids.
102
- - The patch call preserves the view's existing columns, saved filters, type-specific date/card/board config, buttons, visibility, and other backend-required fields.
103
-
104
- View associated resources example:
105
-
106
- ```json
107
- {
108
- "tool_name": "app_associated_resources_apply",
109
- "arguments": {
110
- "profile": "default",
111
- "app_key": "APP_123",
112
- "upsert_resources": [],
113
- "remove_associated_item_ids": [],
114
- "reorder_associated_item_ids": [],
115
- "view_configs": [
116
- {
117
- "view_key": "VIEW_KEY",
118
- "visible": true,
119
- "limit_type": "select",
120
- "associated_item_ids": [123, 124]
121
- }
122
- ]
123
- }
124
- }
125
- ```
126
-
127
- 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.
128
-
129
- Create and show a BI indicator-card report in the same call:
130
-
131
- ```json
132
- {
133
- "tool_name": "app_associated_resources_apply",
134
- "arguments": {
135
- "profile": "default",
136
- "app_key": "APP_123",
137
- "upsert_resources": [
138
- {
139
- "client_key": "total_hours_card",
140
- "graph_type": "chart",
141
- "target_app_key": "TIMESHEET_APP",
142
- "chart_key": "CHART_KEY",
143
- "report_source": "app",
144
- "match_mappings": [
145
- {"target_field": "关联员工", "source_field": "数据ID"},
146
- {"target_field": "状态", "value": "待提交"}
147
- ]
148
- }
149
- ],
150
- "remove_associated_item_ids": [],
151
- "reorder_associated_item_ids": [],
152
- "view_configs": [
153
- {
154
- "view_key": "VIEW_KEY",
155
- "visible": true,
156
- "limit_type": "select",
157
- "associated_item_refs": ["total_hours_card"]
158
- }
159
- ]
160
- }
161
- }
162
- ```
163
-
164
- Board example:
165
-
166
- ```json
167
- {
168
- "tool_name": "app_views_apply",
169
- "arguments": {
170
- "profile": "default",
171
- "app_key": "APP_123",
172
- "upsert_views": [
173
- {
174
- "name": "按状态看板",
175
- "type": "board",
176
- "group_by": "状态",
177
- "columns": ["订单编号", "客户名称", "订单金额"]
178
- }
179
- ],
180
- "remove_views": []
181
- }
182
- }
183
- ```
184
-
185
- Gantt example with filters:
186
-
187
- ```json
188
- {
189
- "tool_name": "app_views_apply",
190
- "arguments": {
191
- "profile": "default",
192
- "app_key": "APP_123",
193
- "upsert_views": [
194
- {
195
- "name": "项目甘特图",
196
- "type": "gantt",
197
- "columns": ["项目名称", "开始日期", "结束日期", "状态"],
198
- "start_field": "开始日期",
199
- "end_field": "结束日期",
200
- "title_field": "项目名称",
201
- "filters": [
202
- {
203
- "field_name": "状态",
204
- "operator": "eq",
205
- "value": "进行中"
206
- }
207
- ]
208
- }
209
- ],
210
- "remove_views": []
211
- }
212
- }
213
- ```
214
-
215
- ## Common failures
216
-
217
- ### `UNKNOWN_VIEW_FIELD`
218
-
219
- At least one `columns` or `group_by` field name does not exist.
220
-
221
- ### `INVALID_VIEW_TYPE`
222
-
223
- Public view types are only `table`, `card`, `board`, `gantt`.
224
-
225
- Map old or intuitive labels before calling the tool:
226
-
227
- - `tableView` -> `table`
228
- - `cardView` -> `card`
229
- - `kanban` -> `board`
230
-
231
- ### `INVALID_GANTT_CONFIG`
232
-
233
- Gantt views require at least:
234
-
235
- - `start_field`
236
- - `end_field`
237
-
238
- Also make sure these field names already exist on the app.
239
-
240
- ### `VIEW_APPLY_FAILED`
241
-
242
- The backend rejected the normalized view payload. Re-read fields and inspect `request_id` before retrying.
243
-
244
- Do not repeat `app_views_apply` with guessed keys. First:
245
-
246
- 1. check `suggested_next_call`
247
- 2. reuse `canonical_arguments` if present
248
- 3. call `app_get_views` to see whether any requested views landed anyway
249
- 4. if needed, call `builder_tool_contract`
250
- 5. retry only the minimal failed view patch
251
-
252
- ### `VIEW_FILTER_READBACK_MISMATCH`
253
-
254
- The view object was created or updated, but the readback config did not keep the intended filter values.
255
-
256
- Treat this as:
257
-
258
- - the view exists
259
- - the filter is **not yet verified**
260
-
261
- Do not tell the user the filter is active until the readback verification matches the intended filter.
262
-
263
- ### `VIEW_QUERY_CONDITION_READBACK_MISMATCH`
264
-
265
- The view object was created or updated, but the readback config did not keep the intended frontend query-condition settings.
266
-
267
- Treat this as:
268
-
269
- - the view exists
270
- - the query panel configuration is **not yet verified**
271
-
272
- Do not tell the user the query condition is active until readback matches the intended `query_conditions`.
273
-
274
- ### `QUERY_CONDITION_FIELD_NOT_FOUND`
275
-
276
- At least one `query_conditions.rows` field does not exist on the app.
277
-
278
- ### `INVALID_QUERY_CONDITION_FIELD`
279
-
280
- 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.
281
-
282
- ## Notes
283
-
284
- - `fields` is accepted as an alias for `columns`, but skill examples should still use `columns`
285
- - `column_names` should not appear in skill examples
286
- - `app_get_views` should be treated as canonical readback and now returns `columns`
287
- - If `app_views_apply` returns `AMBIGUOUS_VIEW`, stop and re-run `app_get_views`; then retry with the exact `view_key`
288
- - `filters` are ANDed together as one flat condition group
289
- - `query_conditions.rows` does not mean OR; it controls frontend query-field layout
290
- - `app_views_apply` publishes by default
291
- - For select-style filters, success means the backend preserved the option value in readback, not just that the view name now exists