@qingflow-tech/qingflow-app-builder-mcp 1.0.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/README.md +32 -0
- package/docs/local-agent-install.md +332 -0
- package/entry_point.py +13 -0
- package/npm/bin/qingflow-app-builder-mcp.mjs +7 -0
- package/npm/lib/runtime.mjs +339 -0
- package/npm/scripts/postinstall.mjs +16 -0
- package/package.json +34 -0
- package/pyproject.toml +67 -0
- package/qingflow-app-builder-mcp +15 -0
- package/skills/qingflow-app-builder/SKILL.md +251 -0
- package/skills/qingflow-app-builder/agents/openai.yaml +4 -0
- package/skills/qingflow-app-builder/references/create-app.md +128 -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 +64 -0
- package/skills/qingflow-app-builder/references/solution-playbooks.md +53 -0
- package/skills/qingflow-app-builder/references/tool-selection.md +93 -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 +68 -0
- package/skills/qingflow-app-builder/references/update-views.md +162 -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/src/qingflow_mcp/__init__.py +5 -0
- package/src/qingflow_mcp/__main__.py +5 -0
- package/src/qingflow_mcp/backend_client.py +649 -0
- package/src/qingflow_mcp/builder_facade/__init__.py +3 -0
- package/src/qingflow_mcp/builder_facade/models.py +1836 -0
- package/src/qingflow_mcp/builder_facade/service.py +15044 -0
- package/src/qingflow_mcp/cli/__init__.py +1 -0
- package/src/qingflow_mcp/cli/commands/__init__.py +18 -0
- package/src/qingflow_mcp/cli/commands/app.py +40 -0
- package/src/qingflow_mcp/cli/commands/auth.py +44 -0
- package/src/qingflow_mcp/cli/commands/builder.py +538 -0
- package/src/qingflow_mcp/cli/commands/chart.py +18 -0
- package/src/qingflow_mcp/cli/commands/common.py +62 -0
- package/src/qingflow_mcp/cli/commands/imports.py +96 -0
- package/src/qingflow_mcp/cli/commands/portal.py +25 -0
- package/src/qingflow_mcp/cli/commands/record.py +331 -0
- package/src/qingflow_mcp/cli/commands/repo.py +80 -0
- package/src/qingflow_mcp/cli/commands/task.py +89 -0
- package/src/qingflow_mcp/cli/commands/view.py +18 -0
- package/src/qingflow_mcp/cli/commands/workspace.py +25 -0
- package/src/qingflow_mcp/cli/context.py +60 -0
- package/src/qingflow_mcp/cli/formatters.py +334 -0
- package/src/qingflow_mcp/cli/json_io.py +50 -0
- package/src/qingflow_mcp/cli/main.py +178 -0
- package/src/qingflow_mcp/config.py +513 -0
- package/src/qingflow_mcp/errors.py +66 -0
- package/src/qingflow_mcp/import_store.py +121 -0
- package/src/qingflow_mcp/json_types.py +18 -0
- package/src/qingflow_mcp/list_type_labels.py +76 -0
- package/src/qingflow_mcp/public_surface.py +233 -0
- package/src/qingflow_mcp/repository_store.py +71 -0
- package/src/qingflow_mcp/response_trim.py +470 -0
- package/src/qingflow_mcp/server.py +212 -0
- package/src/qingflow_mcp/server_app_builder.py +533 -0
- package/src/qingflow_mcp/server_app_user.py +362 -0
- package/src/qingflow_mcp/session_store.py +302 -0
- package/src/qingflow_mcp/solution/__init__.py +6 -0
- package/src/qingflow_mcp/solution/build_assembly_store.py +181 -0
- package/src/qingflow_mcp/solution/compiler/__init__.py +282 -0
- package/src/qingflow_mcp/solution/compiler/chart_compiler.py +96 -0
- package/src/qingflow_mcp/solution/compiler/form_compiler.py +495 -0
- package/src/qingflow_mcp/solution/compiler/icon_utils.py +187 -0
- package/src/qingflow_mcp/solution/compiler/navigation_compiler.py +57 -0
- package/src/qingflow_mcp/solution/compiler/package_compiler.py +19 -0
- package/src/qingflow_mcp/solution/compiler/portal_compiler.py +60 -0
- package/src/qingflow_mcp/solution/compiler/view_compiler.py +51 -0
- package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
- package/src/qingflow_mcp/solution/design_session.py +222 -0
- package/src/qingflow_mcp/solution/design_store.py +100 -0
- package/src/qingflow_mcp/solution/executor.py +2398 -0
- package/src/qingflow_mcp/solution/normalizer.py +23 -0
- package/src/qingflow_mcp/solution/requirements_builder.py +536 -0
- package/src/qingflow_mcp/solution/run_store.py +244 -0
- package/src/qingflow_mcp/solution/spec_models.py +855 -0
- package/src/qingflow_mcp/tools/__init__.py +1 -0
- package/src/qingflow_mcp/tools/ai_builder_tools.py +3419 -0
- package/src/qingflow_mcp/tools/app_tools.py +925 -0
- package/src/qingflow_mcp/tools/approval_tools.py +1062 -0
- package/src/qingflow_mcp/tools/auth_tools.py +875 -0
- package/src/qingflow_mcp/tools/base.py +388 -0
- package/src/qingflow_mcp/tools/code_block_tools.py +777 -0
- package/src/qingflow_mcp/tools/custom_button_tools.py +202 -0
- package/src/qingflow_mcp/tools/directory_tools.py +675 -0
- package/src/qingflow_mcp/tools/feedback_tools.py +238 -0
- package/src/qingflow_mcp/tools/file_tools.py +409 -0
- package/src/qingflow_mcp/tools/import_tools.py +2189 -0
- package/src/qingflow_mcp/tools/navigation_tools.py +210 -0
- package/src/qingflow_mcp/tools/package_tools.py +326 -0
- package/src/qingflow_mcp/tools/portal_tools.py +158 -0
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +374 -0
- package/src/qingflow_mcp/tools/record_tools.py +14037 -0
- package/src/qingflow_mcp/tools/repository_dev_tools.py +552 -0
- package/src/qingflow_mcp/tools/resource_read_tools.py +421 -0
- package/src/qingflow_mcp/tools/role_tools.py +112 -0
- package/src/qingflow_mcp/tools/solution_tools.py +4054 -0
- package/src/qingflow_mcp/tools/task_context_tools.py +2228 -0
- package/src/qingflow_mcp/tools/task_tools.py +890 -0
- package/src/qingflow_mcp/tools/view_tools.py +335 -0
- package/src/qingflow_mcp/tools/workflow_tools.py +376 -0
- package/src/qingflow_mcp/tools/workspace_tools.py +125 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qingflow-app-builder
|
|
3
|
+
description: Build, configure, and modify Qingflow apps and systems after the MCP is already connected and authenticated. Use when the user wants to apply or repair an existing SolutionSpec, modify an existing package with app, view, workflow, portal, navigation, or reporting tools, verify builder-side results, or troubleshoot system-building behavior. Do not use this skill to install the MCP or to author a brand new SolutionSpec from scratch.
|
|
4
|
+
metadata:
|
|
5
|
+
short-description: Build and modify Qingflow apps and systems
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Qingflow App Builder
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
This skill helps a system builder use the AI-native Qingflow builder surface safely. It assumes the MCP is already connected and authenticated. If not, switch to `$qingflow-mcp-setup` first.
|
|
13
|
+
|
|
14
|
+
Before any write or verification flow, identify whether the task targets `test` or `prod` and read [references/environments.md](references/environments.md). If the user did not specify one, default to `prod`.
|
|
15
|
+
|
|
16
|
+
## Tool Selection
|
|
17
|
+
|
|
18
|
+
Pick the smallest tool layer that can finish the task.
|
|
19
|
+
|
|
20
|
+
## Shared Helper
|
|
21
|
+
|
|
22
|
+
- `feedback_submit` is a cross-cutting helper for product feedback submission
|
|
23
|
+
- It does not require Qingflow login or workspace selection
|
|
24
|
+
- If builder capability is unsupported or still cannot satisfy the need after reasonable use, summarize the gap, ask whether to submit feedback, and call `feedback_submit` only after explicit user confirmation.
|
|
25
|
+
|
|
26
|
+
## Mental Model
|
|
27
|
+
|
|
28
|
+
Model builder requests in four layers. Do not flatten them.
|
|
29
|
+
|
|
30
|
+
- `package`: the solution container or app bundle, for example “研发项目管理” or “费控管理系统”
|
|
31
|
+
- `app`: one form/app inside that package, for example “项目”, “需求”, “任务”, “缺陷”, “团队”
|
|
32
|
+
- `field`: one field inside one app
|
|
33
|
+
- `relation`: a field that links one app to another app
|
|
34
|
+
|
|
35
|
+
Interpret user intent with this hierarchy:
|
|
36
|
+
|
|
37
|
+
- If the user says “应用包”, “系统”, “包含多个表单”, “多个模块”, or asks for several named forms that relate to each other, treat it as a `package` with multiple `apps`
|
|
38
|
+
- Do not compress a multi-app system into one app with several text fields
|
|
39
|
+
- Names like “项目/需求/任务/缺陷/团队” or “费用申请/预算管理/报销审批” are usually separate apps, not text fields
|
|
40
|
+
- Build the apps first, then add `relation` fields to connect them
|
|
41
|
+
|
|
42
|
+
Default modeling rules:
|
|
43
|
+
|
|
44
|
+
- One business object -> one app
|
|
45
|
+
- Attributes of that object -> fields inside that app
|
|
46
|
+
- Another business object -> a separate app, not a text field
|
|
47
|
+
- Cross-object links -> relation fields, not text fields
|
|
48
|
+
|
|
49
|
+
- Authentication and workspace: `auth_*`, `workspace_*`
|
|
50
|
+
- File upload: `file_upload_local`
|
|
51
|
+
- Resource resolve/read: `package_list`, `package_resolve`, `package_create`, `builder_tool_contract`, `member_search`, `role_search`, `app_resolve`, `app_get`, `app_get_fields`, `app_get_layout`, `app_get_views`, `app_get_flow`, `app_get_charts`, `portal_list`, `portal_get`, `view_get`, `chart_get`
|
|
52
|
+
- Resource patch: `app_schema_apply`, `app_layout_apply`, `app_flow_apply`, `app_views_apply`, `app_charts_apply`, `portal_apply`, `package_attach_app`, `app_release_edit_lock_if_mine`, `role_create`
|
|
53
|
+
- Publish and verify: `app_publish_verify`
|
|
54
|
+
|
|
55
|
+
Note:
|
|
56
|
+
- Do not try to handcraft raw Qingflow schema or internal solution payloads.
|
|
57
|
+
- Do not rely on low-level `view_*`, `workflow_*`, `qingbi_report_*`, or `portal_*` write payloads from public builder flows.
|
|
58
|
+
- Public builder work should stay on the resource path: `resolve -> summary read -> apply -> attach -> publish_verify`.
|
|
59
|
+
- `app_schema_apply` / `app_layout_apply` / `app_flow_apply` / `app_views_apply` publish by default; pass `publish=false` only when you intentionally want to leave changes in draft.
|
|
60
|
+
- `app_charts_apply` is immediate-live and does not publish; it resolves targets by `chart_id` first and then exact unique chart name.
|
|
61
|
+
- `portal_apply` uses replace semantics for sections; remove a section by omitting it from the next full sections list. `publish=false` only guarantees draft/base-info updates, and `chart_ref/view_ref` resolve by `id/key` first and exact unique name second.
|
|
62
|
+
- `app_get_charts` is the compact discovery path for current chart inventory; use it before `app_charts_apply` when you need exact `chart_id` values.
|
|
63
|
+
- `chart_get` returns one chart's base info and config only; public builder flows should treat data reads as user-side access, not builder config access.
|
|
64
|
+
- `portal_list` is the discovery path for builder-configurable portals.
|
|
65
|
+
- `portal_get` returns portal-level config detail plus a component inventory; it does not inline chart/view detail or user-side chart/view data.
|
|
66
|
+
- `view_get` returns one view's definition detail only; use `record_list` separately when you need rows from that view.
|
|
67
|
+
- `app_schema_apply` / `app_layout_apply` / `app_flow_apply` / `app_views_apply` now perform planning, normalization, and dependency checks internally; when prechecks block, read the returned blocking issues and `suggested_next_call` directly from the apply result.
|
|
68
|
+
- If you are unsure about a public builder tool's keys, aliases, presets, or minimal legal shape, call `builder_tool_contract` instead of guessing.
|
|
69
|
+
- For views, always write the canonical key `columns`. Do not emit `column_names`; treat `fields` only as a tolerated legacy alias, not the preferred shape.
|
|
70
|
+
- For flow presets, map natural language to canonical values before calling MCP:
|
|
71
|
+
- “默认审批/基础审批/普通审批” -> `basic_approval`
|
|
72
|
+
- “先填报再审批/提交后审批” -> `basic_fill_then_approve`
|
|
73
|
+
- Public flow building is intentionally limited to linear workflows:
|
|
74
|
+
- `start`
|
|
75
|
+
- `approve`
|
|
76
|
+
- `fill`
|
|
77
|
+
- `copy`
|
|
78
|
+
- `webhook`
|
|
79
|
+
- `end`
|
|
80
|
+
Do not generate `branch` or `condition` nodes in the public builder surface. The backend workflow route is not front-end stable for those node types.
|
|
81
|
+
- For first-time flow or view work in a session, read `builder_tool_contract` before planning so keys, aliases, presets, and minimal examples come from MCP instead of memory.
|
|
82
|
+
- For workflow assignees, prefer roles over explicit members:
|
|
83
|
+
- use `role_search` first
|
|
84
|
+
- use `member_search` only when the user explicitly names members or no stable role exists
|
|
85
|
+
- use `role_create` when the business owner wants a reusable directory role instead of hard-coded members
|
|
86
|
+
- On any `VALIDATION_ERROR`, inspect `suggested_next_call` first and prefer reusing the MCP-normalized arguments over re-guessing from the original natural language.
|
|
87
|
+
- 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.
|
|
88
|
+
|
|
89
|
+
Default policy:
|
|
90
|
+
|
|
91
|
+
- Creating or updating one app inside an existing package: resolve the package/app, read compact state, then apply schema/layout/flow/views patches explicitly.
|
|
92
|
+
- If package creation looks necessary or beneficial, ask the user to confirm before calling `package_create`.
|
|
93
|
+
- If the user describes a system/package with multiple forms or modules, do not start with `app_schema_apply` on the package name. Resolve or create the package first, then create each app separately.
|
|
94
|
+
|
|
95
|
+
## Standard Operating Order
|
|
96
|
+
|
|
97
|
+
Before any business tool:
|
|
98
|
+
|
|
99
|
+
1. Ensure auth exists
|
|
100
|
+
2. Ensure workspace is selected
|
|
101
|
+
3. Confirm whether the task is read-only or write-impacting
|
|
102
|
+
|
|
103
|
+
For builder work:
|
|
104
|
+
|
|
105
|
+
1. Resolve the target package with `package_resolve`; if resolution is ambiguous or you need a read-only fallback, use `package_list`. If you believe a new package should be created, ask the user to confirm before calling `package_create`.
|
|
106
|
+
2. Decide whether the target is one app or a multi-app package:
|
|
107
|
+
- one app: continue with `app_resolve`
|
|
108
|
+
- multi-app package/system: create or resolve the package, then create each app separately before adding relations
|
|
109
|
+
3. Resolve the target app with `app_resolve` if the request is an update. Use exactly one selector mode: `app_key`, or `app_name + package_tag_id`.
|
|
110
|
+
4. Read only the smallest config slice you need: `app_get`, `app_get_fields`, `app_get_layout`, `app_get_views`, `app_get_flow`, `app_get_charts`, `portal_get`.
|
|
111
|
+
5. Use `app_schema_apply` for create/upsert/remove field work. It publishes by default after the patch lands; noop schema requests do not publish.
|
|
112
|
+
6. If the app must belong to a package, use `package_attach_app` explicitly after schema work with `tag_id + app_key` unless readback already shows the target `tag_id`.
|
|
113
|
+
7. Use `app_layout_apply` only when the user is explicitly changing layout. Prefer the default `mode=merge`; use `mode=replace` only when you intend to place every field explicitly. It publishes by default after the patch lands; noop layout requests do not publish.
|
|
114
|
+
8. Use `app_flow_apply` after schema exists. It publishes by default; pass `publish=false` when you only want draft/precheck behavior.
|
|
115
|
+
9. Use `app_views_apply` when the user wants explicit table/card/board/gantt views. It publishes by default after the patch lands; noop view requests do not publish.
|
|
116
|
+
10. Use `app_publish_verify` only when the user explicitly wants final publish/live verification or you need an explicit verification pass.
|
|
117
|
+
11. If a write fails with `APP_EDIT_LOCKED`, stop normal writes. Only use `app_release_edit_lock_if_mine` when the failed result shows the lock owner is the current logged-in user.
|
|
118
|
+
|
|
119
|
+
For view work, keep the order strict:
|
|
120
|
+
|
|
121
|
+
1. `builder_tool_contract`
|
|
122
|
+
2. `app_get_fields`
|
|
123
|
+
3. `app_get_views`
|
|
124
|
+
4. `app_views_apply`
|
|
125
|
+
5. `app_get_views` again whenever `app_views_apply` returns `failed` or `partial_success`
|
|
126
|
+
|
|
127
|
+
For flow work, keep the order strict:
|
|
128
|
+
|
|
129
|
+
1. `builder_tool_contract`
|
|
130
|
+
2. `app_get_fields`
|
|
131
|
+
3. `app_get_flow`
|
|
132
|
+
4. `role_search` or `member_search` if assignees need to come from the directory
|
|
133
|
+
5. `role_create` if the user wants a reusable role and no suitable role exists yet
|
|
134
|
+
6. Start from a canonical preset when possible
|
|
135
|
+
7. Use patch-style edits to that skeleton instead of freehand full-graph generation
|
|
136
|
+
8. When patching a preset skeleton, reuse the preset node ids:
|
|
137
|
+
- `basic_approval` -> patch `approve_1`
|
|
138
|
+
- `basic_fill_then_approve` -> patch `fill_1` and `approve_1`
|
|
139
|
+
Do not invent a second approval/fill node id unless you are intentionally replacing the skeleton and removing the preset node.
|
|
140
|
+
9. Declare approver/fill/copy assignees explicitly:
|
|
141
|
+
- prefer `assignees.role_names`
|
|
142
|
+
- support `assignees.member_names` / `assignees.member_emails` / `assignees.member_uids`
|
|
143
|
+
10. When a node must edit specific fields, declare `permissions.editable_fields`
|
|
144
|
+
11. `app_flow_apply`
|
|
145
|
+
12. `app_get_flow` after apply whenever the user asked for verification or apply returns `partial_success`
|
|
146
|
+
13. Use `app_get_charts` before chart work whenever exact current `chart_id` values matter
|
|
147
|
+
14. Use `app_charts_apply` for QingBI chart creation and updates, not raw `qingbi_report_*` writes
|
|
148
|
+
15. Use `portal_get` before portal work whenever exact current portal config and section inventory matter
|
|
149
|
+
16. Use `portal_apply` for builder-side portal work; treat sections as a full replacement list
|
|
150
|
+
|
|
151
|
+
For additive work on existing systems:
|
|
152
|
+
|
|
153
|
+
1. Confirm the target package or existing apps
|
|
154
|
+
2. Avoid creating a new package unless the user explicitly wants a separate solution
|
|
155
|
+
3. Use ordinary low-level tools for incremental change
|
|
156
|
+
4. Re-verify the affected apps, views, workflows, or portal after modification
|
|
157
|
+
|
|
158
|
+
## Safe Usage Rules
|
|
159
|
+
|
|
160
|
+
- When using `package_name`, expect deterministic resolution only on a unique exact package name match; if multiple packages match, stop and resolve the ambiguity instead of guessing
|
|
161
|
+
- `app_schema_apply` is the only public patch tool allowed to create an app shell; `app_layout_apply`, `app_flow_apply`, and `app_views_apply` require an existing app.
|
|
162
|
+
- Prefer reading compact state plus `builder_tool_contract` before `*_apply`; apply already performs server-side normalization and returns blocking issues or the next executable call shape when needed.
|
|
163
|
+
- For abstract requests like “默认视图”, “基础审批流”, “灵活流程”, or “美观布局”, first translate the intent into a stable preset or explicit patch. Do not send those phrases to MCP unchanged.
|
|
164
|
+
- If the user asks for a business system or package that contains several forms, do not use the system/package name as `app_name` and do not try to store the child app names as text fields.
|
|
165
|
+
- For flexible workflow requests, split the work into two steps:
|
|
166
|
+
1. create a base skeleton with a preset
|
|
167
|
+
2. apply explicit business-specific changes as patchable nodes/transitions
|
|
168
|
+
- For preset-based flows, treat preset node ids as part of the public contract. Patch the skeleton nodes by the same ids instead of creating a parallel node with a new id and leaving the preset node unassigned.
|
|
169
|
+
- Approval, fill, and copy nodes must declare at least one assignee. Treat this as a hard requirement, not an optional detail.
|
|
170
|
+
- For workflow nodes, use the canonical public shape:
|
|
171
|
+
- `assignees.role_names`
|
|
172
|
+
- `assignees.member_names`
|
|
173
|
+
- `permissions.editable_fields`
|
|
174
|
+
- For layout work, keep the public section shape canonical:
|
|
175
|
+
- `title`
|
|
176
|
+
- `rows`
|
|
177
|
+
Do not invent top-level layout `columns`, and do not prefer `fields` or `field_ids` once `rows` is known.
|
|
178
|
+
- Translate natural language like “一行四个字段 / 四列布局 / 每行放四个” into `rows` matrices, not guessed layout parameters.
|
|
179
|
+
- If the same layout-shape `VALIDATION_ERROR` repeats twice, stop guessing and re-read `builder_tool_contract(app_layout_apply)` or the layout reference before trying again.
|
|
180
|
+
- Do not guess role ids or member ids. Resolve them from the directory first.
|
|
181
|
+
- `app_schema_apply` does not treat package attachment as success criteria; if package ownership matters, verify `tag_ids_after` and call `package_attach_app` explicitly.
|
|
182
|
+
- `package_attach_app` is the source of truth for package ownership; do not assume app creation or publish implicitly attaches the app.
|
|
183
|
+
- `relation` and `subtable` must be explicit; do not infer them from vague natural language.
|
|
184
|
+
- Another app is not a field. If two business objects should both have their own records, build two apps and connect them with relation fields.
|
|
185
|
+
- In `prod`, prefer explicit patch tools and avoid any speculative create flow.
|
|
186
|
+
- Never try to bypass collaborative edit locks. `app_release_edit_lock_if_mine` is only for the case where the lock owner is the current authenticated user.
|
|
187
|
+
|
|
188
|
+
## Response Interpretation
|
|
189
|
+
|
|
190
|
+
- low-level list totals from the backend may report `0` while rows are present; prefer summary or aggregate readbacks for final conclusions
|
|
191
|
+
- `app_publish_verify` is the publish source of truth.
|
|
192
|
+
- All public builder tools expose top-level `warnings`, `verification`, and `verified`. Read them before deciding whether a run is fully done.
|
|
193
|
+
- For read tools, `status=success` can still pair with `verified=false` when some optional readback is unavailable; in that case prefer `warnings` and `verification` over the bare status code.
|
|
194
|
+
- For `app_charts_apply`, `portal_apply`, and `app_publish_verify`, treat `success` as “write and verification completed” and `partial_success` as “write executed but verification is incomplete”.
|
|
195
|
+
- For `app_schema_apply`, multiple relation fields are a known high-risk backend area. If you see `RELATION_FIELD_LIMIT_RISK` or `verification.relation_field_limit_verified=false`, do not describe the schema as fully safe.
|
|
196
|
+
- For `app_layout_apply`, trust `verification.layout_verified` first and `verification.layout_summary_verified` second. `LAYOUT_SUMMARY_UNVERIFIED` means the raw form readback is more trustworthy than the compact summary.
|
|
197
|
+
- For `app_views_apply`, treat `verification.views_verified` and `verification.view_filters_verified` separately. A created view with unverified filters is not a finished business view.
|
|
198
|
+
- For `app_flow_apply`, treat only linear node structure as publicly supported. If you see `FLOW_NODE_TYPE_UNSUPPORTED`, redesign the workflow as a stable linear flow instead of retrying branch/condition nodes.
|
|
199
|
+
- If readback mismatches the UI, compare `request_route` and do not assume the builder hit the same `qf_version` as the browser
|
|
200
|
+
- Treat post-write readback as the source of truth, not just write status codes
|
|
201
|
+
- For views, a top-level `VIEW_APPLY_FAILED` does not prove all requested views failed. Read back the view list and verify which views actually landed.
|
|
202
|
+
- For views, “view exists” is not the same as “filters are active”. If `app_views_apply` returns `partial_success`, `views_verified=false`, or `details.filter_mismatches`, report the view as created but the filters as unverified until readback confirms them.
|
|
203
|
+
- If multiple views share the same name, do not guess which one to update. Read `view_key` from `app_get_views` and pass it explicitly in `upsert_views[]`.
|
|
204
|
+
- In final user-facing summaries, distinguish clearly between:
|
|
205
|
+
- contract is visible / canonical shape is known
|
|
206
|
+
- apply precheck succeeded
|
|
207
|
+
- apply landed and readback verified it
|
|
208
|
+
- base template/skeleton applied
|
|
209
|
+
- business-specific rules completed
|
|
210
|
+
- remaining gaps or follow-up patches
|
|
211
|
+
- Do not report “流程已满足业务需求” when only a preset skeleton has landed.
|
|
212
|
+
|
|
213
|
+
## Practical Patterns
|
|
214
|
+
|
|
215
|
+
- List packages: `package_list`
|
|
216
|
+
- Resolve one package: `package_resolve`
|
|
217
|
+
- Create one package: `package_create`
|
|
218
|
+
- Read one public tool contract: `builder_tool_contract`
|
|
219
|
+
- Resolve one app: `app_resolve`
|
|
220
|
+
- Read one app summary: `app_get`
|
|
221
|
+
- Read fields only: `app_get_fields`
|
|
222
|
+
- Read layout summary: `app_get_layout`
|
|
223
|
+
- Read views summary: `app_get_views`
|
|
224
|
+
- Read flow summary: `app_get_flow`
|
|
225
|
+
- Read chart summary: `app_get_charts`
|
|
226
|
+
- Read portal config: `portal_get`
|
|
227
|
+
- Search members for workflow assignees: `member_search`
|
|
228
|
+
- Search roles for workflow assignees: `role_search`
|
|
229
|
+
- Create reusable workflow role: `role_create`
|
|
230
|
+
- Add/update/remove fields: `app_schema_apply`
|
|
231
|
+
- Merge or replace layout: `app_layout_apply`
|
|
232
|
+
- Replace workflow: `app_flow_apply`
|
|
233
|
+
- Upsert/remove views: `app_views_apply`
|
|
234
|
+
- Upsert/remove/reorder QingBI charts: `app_charts_apply`
|
|
235
|
+
- Create or replace-update portal pages: `portal_apply`
|
|
236
|
+
- Attach one app to a package: `package_attach_app`
|
|
237
|
+
- Release your own stale edit lock: `app_release_edit_lock_if_mine`
|
|
238
|
+
- Publish and verify: `app_publish_verify` when you need a separate verification pass beyond the default auto-publish behavior in apply tools
|
|
239
|
+
|
|
240
|
+
Detailed playbooks:
|
|
241
|
+
|
|
242
|
+
- Environment switching: [references/environments.md](references/environments.md)
|
|
243
|
+
- Tool choice and sequencing: [references/tool-selection.md](references/tool-selection.md)
|
|
244
|
+
- Result semantics and gotchas: [references/gotchas.md](references/gotchas.md)
|
|
245
|
+
- Create one app in an existing package: [references/create-app.md](references/create-app.md)
|
|
246
|
+
- Update fields only: [references/update-schema.md](references/update-schema.md)
|
|
247
|
+
- Update layout only: [references/update-layout.md](references/update-layout.md)
|
|
248
|
+
- Update workflow only: [references/update-flow.md](references/update-flow.md)
|
|
249
|
+
- Workflow assignees and node permissions: [references/flow-actors-and-permissions.md](references/flow-actors-and-permissions.md)
|
|
250
|
+
- Update views only: [references/update-views.md](references/update-views.md)
|
|
251
|
+
- Standard end-to-end builder sequences: [references/solution-playbooks.md](references/solution-playbooks.md)
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Qingflow App Builder"
|
|
3
|
+
short_description: "Build and modify Qingflow apps and systems"
|
|
4
|
+
default_prompt: "Use $qingflow-app-builder to build or modify a Qingflow app or system safely, and verify environment routing and post-write readbacks when builder flows touch live data."
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Create App
|
|
2
|
+
|
|
3
|
+
Use this when the user wants one new app inside an existing package.
|
|
4
|
+
|
|
5
|
+
Do not use this playbook when the user is really asking for a system/package with multiple forms or modules. In that case:
|
|
6
|
+
|
|
7
|
+
1. resolve or create the package
|
|
8
|
+
2. create each app separately
|
|
9
|
+
3. attach each app to the package
|
|
10
|
+
4. add relation fields between apps
|
|
11
|
+
|
|
12
|
+
Hierarchy reminder:
|
|
13
|
+
|
|
14
|
+
- package -> app -> field -> relation
|
|
15
|
+
- another business object is another app, not a text field
|
|
16
|
+
|
|
17
|
+
If creating a brand new package would help, ask the user to confirm package creation first. After confirmation, call `package_create` before this sequence.
|
|
18
|
+
|
|
19
|
+
## Minimal sequence
|
|
20
|
+
|
|
21
|
+
1. `package_resolve`
|
|
22
|
+
2. `app_resolve`
|
|
23
|
+
3. `app_schema_apply`
|
|
24
|
+
4. `package_attach_app`
|
|
25
|
+
5. `app_publish_verify` only when the user asks for explicit final verification
|
|
26
|
+
|
|
27
|
+
## Multi-app systems are different
|
|
28
|
+
|
|
29
|
+
If the user says things like:
|
|
30
|
+
|
|
31
|
+
- “创建一个完整应用包”
|
|
32
|
+
- “包含项目、需求、任务、缺陷、团队这几个表单”
|
|
33
|
+
- “这些表单之间建立关联关系”
|
|
34
|
+
|
|
35
|
+
then do not treat that as one app.
|
|
36
|
+
|
|
37
|
+
Use this pattern instead:
|
|
38
|
+
|
|
39
|
+
1. `package_resolve` or `package_create`
|
|
40
|
+
2. for each app name, run `app_schema_apply -> package_attach_app`
|
|
41
|
+
3. once the apps exist, add `relation` fields between them
|
|
42
|
+
|
|
43
|
+
## Example
|
|
44
|
+
|
|
45
|
+
Create a new package only after the user confirms package creation:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"tool_name": "package_create",
|
|
50
|
+
"arguments": {
|
|
51
|
+
"profile": "default",
|
|
52
|
+
"package_name": "研发项目管理"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Resolve the package:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"tool_name": "package_resolve",
|
|
62
|
+
"arguments": {
|
|
63
|
+
"profile": "default",
|
|
64
|
+
"package_name": "测试应用包"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Apply schema for a new app:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"tool_name": "app_schema_apply",
|
|
74
|
+
"arguments": {
|
|
75
|
+
"profile": "default",
|
|
76
|
+
"app_name": "客户订单",
|
|
77
|
+
"package_tag_id": 1218950,
|
|
78
|
+
"create_if_missing": true,
|
|
79
|
+
"publish": true,
|
|
80
|
+
"add_fields": [
|
|
81
|
+
{"name": "订单编号", "type": "text", "required": true},
|
|
82
|
+
{"name": "客户名称", "type": "text", "required": true},
|
|
83
|
+
{"name": "订单金额", "type": "amount"},
|
|
84
|
+
{"name": "状态", "type": "single_select", "options": ["草稿", "进行中", "已完成"], "required": true}
|
|
85
|
+
],
|
|
86
|
+
"update_fields": [],
|
|
87
|
+
"remove_fields": []
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Attach explicitly if `tag_ids_after` does not yet contain the package:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"tool_name": "package_attach_app",
|
|
100
|
+
"arguments": {
|
|
101
|
+
"profile": "default",
|
|
102
|
+
"tag_id": 1218950,
|
|
103
|
+
"app_key": "APP_KEY_FROM_SCHEMA_APPLY"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Common failures
|
|
109
|
+
|
|
110
|
+
### `APP_NOT_FOUND`
|
|
111
|
+
|
|
112
|
+
Expected on create. Continue with `create_if_missing=true`.
|
|
113
|
+
|
|
114
|
+
### `CREATE_APP_ROUTE_NOT_FOUND`
|
|
115
|
+
|
|
116
|
+
The create route did not resolve in the current backend route context. Re-run `workspace_select`, then retry the same `app_schema_apply`.
|
|
117
|
+
|
|
118
|
+
### `PACKAGE_ATTACH_FAILED`
|
|
119
|
+
|
|
120
|
+
Do not retry schema creation. Re-run only `package_attach_app`, then verify with `app_get`.
|
|
121
|
+
|
|
122
|
+
### Hierarchy modeling mistake
|
|
123
|
+
|
|
124
|
+
If the user asked for several named forms/apps but the draft patch turns them into text fields inside one app, stop and remodel the task as:
|
|
125
|
+
|
|
126
|
+
- one package
|
|
127
|
+
- many apps
|
|
128
|
+
- relation fields between those apps
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Environment Switching
|
|
2
|
+
|
|
3
|
+
Use this reference before any builder-side write, repair, or verification flow.
|
|
4
|
+
|
|
5
|
+
## Step 1: Resolve the active environment
|
|
6
|
+
|
|
7
|
+
Decide explicitly whether the task targets:
|
|
8
|
+
|
|
9
|
+
- `test`: build validation, mock data, trial package creation, safe iteration
|
|
10
|
+
- `prod`: formal business system changes in the live environment
|
|
11
|
+
|
|
12
|
+
If the user did not specify an environment, default to `prod`.
|
|
13
|
+
|
|
14
|
+
## Test Environment
|
|
15
|
+
|
|
16
|
+
Use test for:
|
|
17
|
+
|
|
18
|
+
- first application of a new `SolutionSpec`
|
|
19
|
+
- trying `solution_build_all(..., verify=true)`
|
|
20
|
+
- package initialization and schema evolution experiments
|
|
21
|
+
- mock data creation, with at least `5` records per relevant entity unless the user asks for fewer
|
|
22
|
+
|
|
23
|
+
Builder behavior in test:
|
|
24
|
+
|
|
25
|
+
- `preflight` or `plan` is still preferred, but fast `apply` is acceptable when the user explicitly wants an end-to-end smoke test
|
|
26
|
+
- package creation is acceptable
|
|
27
|
+
- verify should read back apps, views, portal, navigation, and sample records
|
|
28
|
+
|
|
29
|
+
Known current test backend:
|
|
30
|
+
|
|
31
|
+
- use an explicitly provided non-production backend
|
|
32
|
+
|
|
33
|
+
## Production Environment
|
|
34
|
+
|
|
35
|
+
Use production for:
|
|
36
|
+
|
|
37
|
+
- changes to real business systems
|
|
38
|
+
- additive modifications to live packages and apps
|
|
39
|
+
- controlled rollout of approved solution specs
|
|
40
|
+
|
|
41
|
+
Builder behavior in prod:
|
|
42
|
+
|
|
43
|
+
- always identify the target package or app set before changing anything
|
|
44
|
+
- default to `preflight` or `plan` before any `apply`
|
|
45
|
+
- additive requirements should modify the existing package with ordinary tools by default
|
|
46
|
+
- if creating a new package seems necessary in prod, ask the user to confirm package creation first
|
|
47
|
+
- do not seed mock data unless the user explicitly approves it for production
|
|
48
|
+
- verify is mandatory after writes
|
|
49
|
+
|
|
50
|
+
Production guardrails:
|
|
51
|
+
|
|
52
|
+
- restate the target workspace and target package before any write
|
|
53
|
+
- call out whether the action creates, mutates, or deletes builder-side configuration
|
|
54
|
+
- if a safer read-only inspection can answer the request, do that first
|
|
55
|
+
|
|
56
|
+
## Reporting Rule
|
|
57
|
+
|
|
58
|
+
For builder work, always report:
|
|
59
|
+
|
|
60
|
+
- active environment
|
|
61
|
+
- target workspace
|
|
62
|
+
- whether the operation is `plan`, `apply`, `repair`, or `verify`
|
|
63
|
+
- whether it touches an existing package or creates a new one
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Flow Actors And Permissions
|
|
2
|
+
|
|
3
|
+
Use this when the workflow needs real assignees or node-level editable field permissions.
|
|
4
|
+
|
|
5
|
+
## Canonical policy
|
|
6
|
+
|
|
7
|
+
- Approval, fill, and copy nodes must declare at least one assignee.
|
|
8
|
+
- Prefer roles over explicit members.
|
|
9
|
+
- Resolve directory actors before calling `app_flow_apply`.
|
|
10
|
+
- Use canonical keys only:
|
|
11
|
+
- `assignees.role_names`
|
|
12
|
+
- `assignees.role_ids`
|
|
13
|
+
- `assignees.member_names`
|
|
14
|
+
- `assignees.member_emails`
|
|
15
|
+
- `assignees.member_uids`
|
|
16
|
+
- `permissions.editable_fields`
|
|
17
|
+
|
|
18
|
+
## Recommended order
|
|
19
|
+
|
|
20
|
+
1. `app_get_fields`
|
|
21
|
+
2. `app_get_flow`
|
|
22
|
+
3. `role_search`
|
|
23
|
+
4. `member_search` when the user explicitly names people
|
|
24
|
+
5. `role_create` when no reusable role exists and the user wants role-based routing
|
|
25
|
+
6. `app_flow_apply`
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
### Route an approval node to a reusable role
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"tool_name": "app_flow_apply",
|
|
34
|
+
"arguments": {
|
|
35
|
+
"profile": "default",
|
|
36
|
+
"app_key": "APP_123",
|
|
37
|
+
"preset": "basic_approval",
|
|
38
|
+
"nodes": [
|
|
39
|
+
{
|
|
40
|
+
"id": "approve_1",
|
|
41
|
+
"type": "approve",
|
|
42
|
+
"name": "部门审批",
|
|
43
|
+
"assignees": {
|
|
44
|
+
"role_names": ["项目经理"]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Route to explicit members when the user names people
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"tool_name": "app_flow_apply",
|
|
57
|
+
"arguments": {
|
|
58
|
+
"profile": "default",
|
|
59
|
+
"app_key": "APP_123",
|
|
60
|
+
"preset": "basic_approval",
|
|
61
|
+
"nodes": [
|
|
62
|
+
{
|
|
63
|
+
"id": "approve_1",
|
|
64
|
+
"type": "approve",
|
|
65
|
+
"name": "部门审批",
|
|
66
|
+
"assignees": {
|
|
67
|
+
"member_names": ["严琪东", "张三"]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Let one node edit selected fields only
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"tool_name": "app_flow_apply",
|
|
80
|
+
"arguments": {
|
|
81
|
+
"profile": "default",
|
|
82
|
+
"app_key": "APP_123",
|
|
83
|
+
"mode": "replace",
|
|
84
|
+
"publish": true,
|
|
85
|
+
"nodes": [
|
|
86
|
+
{"id": "start", "type": "start", "name": "发起"},
|
|
87
|
+
{
|
|
88
|
+
"id": "approve_1",
|
|
89
|
+
"type": "approve",
|
|
90
|
+
"name": "部门审批",
|
|
91
|
+
"assignees": {
|
|
92
|
+
"role_names": ["项目经理"]
|
|
93
|
+
},
|
|
94
|
+
"permissions": {
|
|
95
|
+
"editable_fields": ["状态", "审批意见", "项目负责人"]
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{"id": "end", "type": "end", "name": "结束"}
|
|
99
|
+
],
|
|
100
|
+
"transitions": [
|
|
101
|
+
{"from": "start", "to": "approve_1"},
|
|
102
|
+
{"from": "approve_1", "to": "end"}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Common recovery
|
|
109
|
+
|
|
110
|
+
### `ROLE_NOT_FOUND` / `AMBIGUOUS_ROLE`
|
|
111
|
+
|
|
112
|
+
- retry with `role_search`
|
|
113
|
+
- if the business wants a reusable route and no exact role exists, create one with `role_create`
|
|
114
|
+
|
|
115
|
+
### `MEMBER_NOT_FOUND` / `AMBIGUOUS_MEMBER`
|
|
116
|
+
|
|
117
|
+
- retry with `member_search`
|
|
118
|
+
- do not guess user ids
|
|
119
|
+
|
|
120
|
+
### `UNKNOWN_FLOW_FIELD`
|
|
121
|
+
|
|
122
|
+
- reread fields with `app_get_fields`
|
|
123
|
+
- only pass real current field names to `permissions.editable_fields`
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Builder Gotchas
|
|
2
|
+
|
|
3
|
+
## Auth and workspace
|
|
4
|
+
|
|
5
|
+
- `auth_*` success does not mean a workspace is selected
|
|
6
|
+
- Re-run `workspace_select` after auth changes or route changes
|
|
7
|
+
|
|
8
|
+
## Package ownership
|
|
9
|
+
|
|
10
|
+
- App creation and publish do not guarantee package attachment
|
|
11
|
+
- Treat `package_attach_app` as the source of truth for package ownership
|
|
12
|
+
- Check `tag_ids_after` after schema writes
|
|
13
|
+
|
|
14
|
+
## Package vs app vs field
|
|
15
|
+
|
|
16
|
+
- A package/system is not an app
|
|
17
|
+
- Another app is not a field
|
|
18
|
+
- If the user names multiple forms/modules that relate to each other, create multiple apps and connect them with relation fields
|
|
19
|
+
- Do not use child app names like “项目/需求/任务/缺陷/团队” as plain text fields inside one app
|
|
20
|
+
|
|
21
|
+
## Auto publish
|
|
22
|
+
|
|
23
|
+
- `app_schema_apply`, `app_layout_apply`, `app_flow_apply`, and `app_views_apply` publish by default
|
|
24
|
+
- Pass `publish=false` only when the user explicitly wants to leave changes in draft
|
|
25
|
+
- `app_publish_verify` is for explicit final verification, not the default next step after every write
|
|
26
|
+
|
|
27
|
+
## Readback scope
|
|
28
|
+
|
|
29
|
+
- Prefer summary reads over large raw payloads
|
|
30
|
+
- Use `app_get_fields` before schema or view work
|
|
31
|
+
- Use `app_get_layout` before layout work
|
|
32
|
+
- Use `app_get_flow` before workflow work
|
|
33
|
+
- Use `app_get_views` before view work
|
|
34
|
+
|
|
35
|
+
## Workflow dependencies
|
|
36
|
+
|
|
37
|
+
- Approval-style flows usually require an explicit status field
|
|
38
|
+
- Approval, fill, and copy nodes also require at least one assignee
|
|
39
|
+
- Prefer roles over explicit members unless the user explicitly names people
|
|
40
|
+
- Resolve assignees with `role_search` / `member_search` before flow apply
|
|
41
|
+
- Use `permissions.editable_fields` for node-level editable field permissions; do not guess field ids
|
|
42
|
+
- Preset node ids matter. When patching `basic_approval` or `basic_fill_then_approve`, reuse `approve_1` and `fill_1` unless you are explicitly replacing the skeleton.
|
|
43
|
+
- If `app_flow_apply` reports `FLOW_DEPENDENCY_MISSING`, fix schema first
|
|
44
|
+
- Do not switch to hidden `solution_*` tools from public builder flows
|
|
45
|
+
|
|
46
|
+
## Retry discipline
|
|
47
|
+
|
|
48
|
+
- If a write returns `partial_success`, read back before retrying
|
|
49
|
+
- Do not repeat create steps after `app_key` already exists
|
|
50
|
+
- For backend rejects, keep the retry narrow: retry only the failed tool, not the whole chain
|
|
51
|
+
- For `VALIDATION_ERROR`, do not keep guessing. Reuse `suggested_next_call`, `canonical_arguments`, `allowed_keys`, and `allowed_values` first.
|
|
52
|
+
- For layout `VALIDATION_ERROR`, also inspect `section_allowed_keys`, `section_aliases`, and `minimal_section_example`. If the same layout-shape error repeats twice, stop free-form retries and re-read `builder_tool_contract(app_layout_apply)`.
|
|
53
|
+
- For flow work, do not replay internal keys from old logs or plan outputs. Public builder calls should stay on:
|
|
54
|
+
- `assignees.role_ids` / `assignees.member_uids` / `assignees.member_emails`
|
|
55
|
+
- `permissions.editable_fields`
|
|
56
|
+
- For view work, treat `columns` as the only canonical public key. `app_get_views` and `app_views_apply` should all be read and written in that shape.
|
|
57
|
+
- For layout work, treat `title + rows` as the only canonical public section shape. `fields`, `field_ids`, and `columns` may appear in legacy/internal shapes, but they are not the preferred public write shape.
|
|
58
|
+
- A created view is not enough to claim a filter succeeded. When `app_views_apply` returns `partial_success`, `views_verified=false`, or `details.filter_mismatches`, treat the view as present but the filter as unverified.
|
|
59
|
+
- If duplicate view names exist, do not retry by name. Read the exact `view_key` and target that one.
|
|
60
|
+
- If a view or flow write fails, report the smallest next action:
|
|
61
|
+
- wrong key -> switch to canonical key
|
|
62
|
+
- unsupported preset -> switch to allowed canonical preset
|
|
63
|
+
- backend reject -> re-read summary and retry only the failed patch
|
|
64
|
+
- Do not translate abstract user phrases like “灵活流程” or “默认视图” directly into MCP arguments. First convert them to a preset or explicit patch plan.
|