@qingflow-tech/qingflow-app-user-mcp 1.0.40 → 1.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/docs/local-agent-install.md +4 -4
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/skills/qingflow-app-user/SKILL.md +5 -3
- package/skills/qingflow-mcp-setup/SKILL.md +2 -0
- package/skills/qingflow-record-analysis/SKILL.md +3 -1
- package/skills/qingflow-record-delete/SKILL.md +2 -0
- package/skills/qingflow-record-import/SKILL.md +29 -0
- package/skills/qingflow-record-insert/SKILL.md +24 -1
- package/skills/qingflow-record-update/SKILL.md +3 -0
- package/skills/qingflow-task-ops/SKILL.md +2 -0
- package/src/qingflow_mcp/builder_facade/models.py +183 -0
- package/src/qingflow_mcp/builder_facade/service.py +823 -75
- package/src/qingflow_mcp/cli/commands/builder.py +80 -6
- package/src/qingflow_mcp/cli/formatters.py +1 -0
- package/src/qingflow_mcp/cli/main.py +2 -0
- package/src/qingflow_mcp/response_trim.py +6 -4
- package/src/qingflow_mcp/tools/ai_builder_tools.py +388 -17
- package/src/qingflow_mcp/tools/record_tools.py +28 -2
- package/skills/qingflow-app-builder/SKILL.md +0 -280
- package/skills/qingflow-app-builder/agents/openai.yaml +0 -4
- package/skills/qingflow-app-builder/references/create-app.md +0 -160
- package/skills/qingflow-app-builder/references/environments.md +0 -63
- package/skills/qingflow-app-builder/references/flow-actors-and-permissions.md +0 -123
- package/skills/qingflow-app-builder/references/gotchas.md +0 -107
- package/skills/qingflow-app-builder/references/match-rules.md +0 -129
- package/skills/qingflow-app-builder/references/public-surface-sync.md +0 -75
- package/skills/qingflow-app-builder/references/solution-playbooks.md +0 -52
- package/skills/qingflow-app-builder/references/tool-selection.md +0 -106
- package/skills/qingflow-app-builder/references/update-flow.md +0 -158
- package/skills/qingflow-app-builder/references/update-layout.md +0 -68
- package/skills/qingflow-app-builder/references/update-schema.md +0 -75
- package/skills/qingflow-app-builder/references/update-views.md +0 -286
- package/skills/qingflow-app-builder-code-integrations/SKILL.md +0 -137
- package/skills/qingflow-app-builder-code-integrations/agents/openai.yaml +0 -4
- package/skills/qingflow-app-builder-code-integrations/references/code-block.md +0 -66
- package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +0 -77
|
@@ -4037,7 +4037,11 @@ class RecordTools(ToolBase):
|
|
|
4037
4037
|
"field_id": field_id,
|
|
4038
4038
|
"error_code": error_code,
|
|
4039
4039
|
"message": self._record_write_semantic_error_message(error_code, error.get("message")),
|
|
4040
|
-
"next_action": self._record_write_next_action_for_error(
|
|
4040
|
+
"next_action": self._record_write_next_action_for_error(
|
|
4041
|
+
error_code,
|
|
4042
|
+
expected_format=expected_format,
|
|
4043
|
+
field_payload=field_payload,
|
|
4044
|
+
),
|
|
4041
4045
|
}
|
|
4042
4046
|
if expected_format is not None:
|
|
4043
4047
|
payload["expected_format"] = expected_format
|
|
@@ -4148,8 +4152,30 @@ class RecordTools(ToolBase):
|
|
|
4148
4152
|
return _normalize_optional_text(fallback) or "字段值格式不正确。"
|
|
4149
4153
|
return _normalize_optional_text(fallback) or "字段写入失败。"
|
|
4150
4154
|
|
|
4151
|
-
def _record_write_next_action_for_error(
|
|
4155
|
+
def _record_write_next_action_for_error(
|
|
4156
|
+
self,
|
|
4157
|
+
error_code: str,
|
|
4158
|
+
*,
|
|
4159
|
+
expected_format: JSONObject | None = None,
|
|
4160
|
+
field_payload: JSONObject | None = None,
|
|
4161
|
+
) -> str:
|
|
4152
4162
|
"""执行内部辅助逻辑。"""
|
|
4163
|
+
kind = _normalize_optional_text((expected_format or {}).get("kind"))
|
|
4164
|
+
field_title = (
|
|
4165
|
+
_normalize_optional_text((field_payload or {}).get("que_title"))
|
|
4166
|
+
or _normalize_optional_text((field_payload or {}).get("title"))
|
|
4167
|
+
or "该字段"
|
|
4168
|
+
)
|
|
4169
|
+
if kind == "member_list":
|
|
4170
|
+
return f"{field_title} 需要有效成员;用唯一姓名/邮箱/id,歧义时先调用 record_member_candidates 后只重试本行。"
|
|
4171
|
+
if kind == "department_list":
|
|
4172
|
+
return f"{field_title} 需要有效部门;用候选范围内的部门名/id/object,歧义或不确定时先调用 record_department_candidates 后只重试本行。"
|
|
4173
|
+
if kind == "relation_record":
|
|
4174
|
+
return f"{field_title} 需要关联记录;优先改用目标记录 record_id/apply_id,或使用可唯一命中的显示文本后只重试本行。"
|
|
4175
|
+
if kind == "attachment_list":
|
|
4176
|
+
return f"{field_title} 需要附件值;先用 file_upload_local 上传文件,再写返回的 value/url 后只重试本行。"
|
|
4177
|
+
if kind in {"single_select", "multi_select"}:
|
|
4178
|
+
return f"{field_title} 需要选项值;使用 schema options 中的标签或 option id,修正后只重试本行。"
|
|
4153
4179
|
if error_code == "MISSING_REQUIRED_FIELD":
|
|
4154
4180
|
return "补充该字段后只重试本行。"
|
|
4155
4181
|
if error_code in {"FIELD_NOT_FOUND", "AMBIGUOUS_FIELD"}:
|
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: qingflow-app-builder
|
|
3
|
-
description: Build, configure, and modify Qingflow apps and systems using the current Wingent Momo runtime MCP session. 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 is for the current **public builder surface**, not for legacy low-level builder writes.
|
|
13
|
-
In Wingent Momo runtime, trust the injected MCP session, credentials, workspace, and route context until a tool explicitly reports otherwise.
|
|
14
|
-
|
|
15
|
-
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`.
|
|
16
|
-
|
|
17
|
-
Before choosing a route, skim the shared maintenance baseline: [public-surface-sync.md](references/public-surface-sync.md).
|
|
18
|
-
|
|
19
|
-
## Current Public Mental Model
|
|
20
|
-
|
|
21
|
-
Model builder requests in four layers and keep them separate:
|
|
22
|
-
|
|
23
|
-
- `package`: the app bundle or solution container
|
|
24
|
-
- `app`: one form/app inside that package
|
|
25
|
-
- `field`: one field inside one app
|
|
26
|
-
- `relation`: a field that links one app to another app
|
|
27
|
-
|
|
28
|
-
Default modeling rules:
|
|
29
|
-
|
|
30
|
-
- One business object -> one app
|
|
31
|
-
- Attributes of that object -> fields inside that app
|
|
32
|
-
- Another business object -> a separate app, not a text field
|
|
33
|
-
- Cross-object links -> relation fields, not text fields
|
|
34
|
-
|
|
35
|
-
## Route First
|
|
36
|
-
|
|
37
|
-
Before any builder write, classify the request:
|
|
38
|
-
|
|
39
|
-
- **Complete system / app package**: the user asks for a system, package, workspace module set, or several related forms/apps. Use `package_apply` for the package, then one `app_schema_apply(package_id=..., apps=[...])` for the app shells and fields. Do not squeeze several business objects into one app.
|
|
40
|
-
- **Single app**: the user names one form/app or gives one `app_key`. Use `app_resolve`/`app_get`, then `app_schema_apply` and the app-scoped apply tools.
|
|
41
|
-
- **Record/user operation**: the user wants to add, edit, delete, approve, or analyze data. Route to the record/task skills instead of builder tools.
|
|
42
|
-
|
|
43
|
-
For complete systems, `apps[]` should use stable `client_key` values. Same-call relation fields may use `target_app_ref` for a client key or `target_app` for another app name. Prefer `target_app_ref` when names may collide. Create the related apps with one multi-app schema apply; do not create each app separately just to collect app keys and then patch relations afterward.
|
|
44
|
-
|
|
45
|
-
Builder schema inputs should follow agent-intuitive semantics:
|
|
46
|
-
|
|
47
|
-
- primary icon syntax is `icon + color`, for example `icon: "table", color: "blue"`; `icon_name/icon_color`, `icon_config`, and `icon: {name, color}` are compatibility aliases only
|
|
48
|
-
- `single_select` / `multi_select` options may be strings or objects such as `{label, value}`; tools normalize to option labels
|
|
49
|
-
- relation fields need a target plus `display_field` and `visible_fields`
|
|
50
|
-
- do not create built-in system fields as form fields: `数据ID`, `编号`, `申请人`, `申请时间`, `创建人`, `创建时间`, `提交人`, `提交时间`, `更新时间`, `更新人`, `当前流程状态`, `当前处理人`, `当前处理节点`, `流程标题`. They are platform-generated; only reference supported system fields where a tool explicitly says so, such as button `source_field: "数据ID"`
|
|
51
|
-
|
|
52
|
-
## Public Tools You Should Think In
|
|
53
|
-
|
|
54
|
-
- Package: `package_get`, `package_apply`
|
|
55
|
-
- App reads: `app_resolve`, `app_get`, `app_get_fields`, `app_get_layout`, `app_get_views`, `app_get_flow`, `app_get_charts`
|
|
56
|
-
- Builder reads: `portal_list`, `portal_get`, `view_get`, `chart_get`, `builder_tool_contract`
|
|
57
|
-
- Directory: `member_search`, `role_search`, `role_create`
|
|
58
|
-
- Writes: `app_schema_apply`, `app_layout_apply`, `app_flow_apply`, `app_views_apply`, `app_custom_buttons_apply`, `app_associated_resources_apply`, `app_charts_apply`, `portal_apply`, `app_release_edit_lock_if_mine`
|
|
59
|
-
- Verification: `app_publish_verify`
|
|
60
|
-
- Cross-cutting escalation: `feedback_submit` after explicit user confirmation when the public builder surface still cannot satisfy the user's need
|
|
61
|
-
|
|
62
|
-
Treat these as the official surface. Do not default to `package_create`, `package_attach_app`, raw `portal_*` writes, or raw `qingbi_report_*` writes.
|
|
63
|
-
|
|
64
|
-
## Current Public Defaults
|
|
65
|
-
|
|
66
|
-
- Package work:
|
|
67
|
-
- use `package_get(package_id=...)` to read one known package
|
|
68
|
-
- use `package_apply(...)` for package creation, rename, icon, visibility, grouping, ordering, and app/portal layout
|
|
69
|
-
- Multi-app schema work:
|
|
70
|
-
- use one `app_schema_apply(package_id=..., apps=[...])` / CLI `builder schema apply --apps-file` when creating several apps in one package
|
|
71
|
-
- every `apps[]` item should carry its own `client_key`, `app_name`, `icon`, `color`, and `add_fields`
|
|
72
|
-
- same-call relation fields may use `target_app_ref` to point at another `apps[].client_key`, or `target_app` to point at another `apps[].app_name`
|
|
73
|
-
- App base permissions:
|
|
74
|
-
- trust `app_get.editability.can_edit_app_base` for app base-info writes like app name, icon, and visibility
|
|
75
|
-
- `can_edit_form` only means schema/form-route capability; it no longer implies app base-info write capability
|
|
76
|
-
- Partial update rule:
|
|
77
|
-
- for existing views, custom buttons, associated resources, and charts, prefer `patch_views` / `patch_buttons` / `patch_resources` / `patch_charts`
|
|
78
|
-
- each patch item uses the object's real selector field (`view_key` / `button_id` / `associated_item_id` / `chart_id`, or unique name where supported) plus `set` and optional `unset`; do not send a literal `selector` key for these tools
|
|
79
|
-
- use `upsert_*` for creation or full target configuration; do not send a partial `upsert_*` and expect the backend to merge missing required fields
|
|
80
|
-
- Portal work:
|
|
81
|
-
- `portal_apply` is the public write path
|
|
82
|
-
- in edit mode, omitting `sections` means “preserve existing layout and update base info only”
|
|
83
|
-
- supplying `sections` means full replace semantics for sections
|
|
84
|
-
- Chart work:
|
|
85
|
-
- `app_charts_apply` is the public write path for app-source QingBI report bodies/configs; it creates/updates reports with `dataSourceType=qingflow`
|
|
86
|
-
- dataset BI reports are not created or edited by `app_charts_apply` yet; create them in QingBI first, then attach the existing report with `app_associated_resources_apply` and `report_source="dataset"`
|
|
87
|
-
- it does not attach the report to the Qingflow app associated-resource display; use `app_associated_resources_apply` for that
|
|
88
|
-
- supported `chart_type` values include legacy public aliases `target`, `table` and QingBI types such as `summary`, `columnar`, `area`, `stacked_area`, `funnel`, `waterfall`, `gauge`, `heatmap`, `histogram`, `treemap`, `radar`, `stacked_bar`, `stacked_column`, `scatter`, `ring`, `rose`, `dualaxes`, `map`, and `timeline`
|
|
89
|
-
- chart `filters` use the unified fixed-filter DSL: `field_name + operator + value/values`; the tool compiles them to QingBI string judge types
|
|
90
|
-
- use `patch_charts` for changing a chart name, visibility, filters, or one config fragment on an existing chart
|
|
91
|
-
- `visibility` is a public capability and should be treated as a base-only permission update
|
|
92
|
-
- do not model chart visibility changes as raw config rewrites
|
|
93
|
-
- Button work:
|
|
94
|
-
- `app_custom_buttons_apply` is the public write path for custom button bodies and view placement
|
|
95
|
-
- use `patch_buttons` for changing a single existing button parameter such as URL, text, icon, style, or add-data mapping
|
|
96
|
-
- for add-data buttons, use `trigger_add_data_config.target_app_key + field_mappings/default_values`; do not handwrite raw `que_relation`
|
|
97
|
-
- use `field_mappings` for dynamic current-record values, including system fields such as `数据ID` (`field_id=-17`) and `编号` (`field_id=0`)
|
|
98
|
-
- to prefill a target relation field with the current source record, map `{"source_field": "数据ID", "target_field": "目标引用字段"}`; use `default_values` only for static constants
|
|
99
|
-
- if field type compatibility is unclear, read [references/match-rules.md](references/match-rules.md)
|
|
100
|
-
- bind buttons to views through `view_configs[].buttons[]`; default to `placement`: `header` or `detail`
|
|
101
|
-
- builder `view_configs[].view_key` uses the raw key from `app_get.views[].view_key`, without a `custom:` prefix
|
|
102
|
-
- `buttons` is required in merge mode; do not send a view config with only `view_key`
|
|
103
|
-
- `view_configs[].mode` defaults to `merge`; use `mode: "replace"` or an explicit empty `buttons: []` to clear a view's custom button bindings
|
|
104
|
-
- `placement=list` configures row/list buttons and maps to the backend `INSIDE` button position
|
|
105
|
-
- advanced bindings may use `button_limit`, `button_formula`, `button_formula_type`, and `print_tpls` only when visibility or print-template behavior is required
|
|
106
|
-
- Associated resources:
|
|
107
|
-
- `app_associated_resources_apply` is the public write path for the Qingflow app-level associated report/view pool and per-view display config
|
|
108
|
-
- it attaches existing BI reports/views for in-app display; it does not create or edit QingBI report bodies/configs, including dataset reports
|
|
109
|
-
- use `patch_resources` for changing match rules or other existing associated-resource parameters; the tool preserves backend-required raw fields internally
|
|
110
|
-
- `associated_item_id` is the backend internal associated-resource id; for `view_configs`, `remove_associated_item_ids`, and `reorder_associated_item_ids`, you may pass `associated_item_id` or an existing resource's `chart_id`/`chart_key`/`view_key`, and the tool resolves it to the internal id
|
|
111
|
-
- before creating a resource, check `app_get.associated_resources` for the same `target_app_key + view_key/chart_key`; if it already exists, use `patch_resources` with that `associated_item_id`
|
|
112
|
-
- `client_key` is only a same-call reference for `view_configs[].associated_item_refs`; it is not saved and cannot deduplicate later calls
|
|
113
|
-
- do not pass backend raw `sourceType`; view resources infer the internal Qingflow view source, report/chart resources default to BI app reports, and existing dataset reports use `report_source="dataset"`
|
|
114
|
-
- use `match_mappings` for associated view/report filters; dynamic context matches use `source_field`, static filters use `value`; do not handwrite raw `matchRules`
|
|
115
|
-
- if field type compatibility is unclear, read [references/match-rules.md](references/match-rules.md)
|
|
116
|
-
- Views and flows:
|
|
117
|
-
- stay on `app_views_apply` / `app_flow_apply`
|
|
118
|
-
- use `patch_views` for existing-view parameter changes such as `query_conditions`, `filters`, `columns`, or visibility
|
|
119
|
-
- builder view writes use raw `view_key` values from `app_get.views`; `custom:<viewKey>` is a record-data `view_id` form, not a builder `view_key`
|
|
120
|
-
- do not create platform default/system views named `全部数据`, `我的数据`, `我发起的`, `待办`, `已办`, or `抄送`; they are built in. New views must use business-specific names. To change a built-in view, patch by its existing raw `view_key`
|
|
121
|
-
- use `builder_tool_contract` whenever the minimal legal shape is unclear
|
|
122
|
-
- keep view `filters` and `query_conditions` separate: `filters` use `field_name + operator + value/values` and are fixed saved filters; `query_conditions` configure the frontend query panel fields and only take effect after users enter query values
|
|
123
|
-
- new views default the associated report/view display area to visible with `limit_type="all"`; existing views preserve their current associated-resource display unless `associated_resources` is explicitly patched
|
|
124
|
-
- configure associated reports/views through `app_associated_resources_apply`, not through `app_views_apply`
|
|
125
|
-
|
|
126
|
-
## Standard Operating Order
|
|
127
|
-
|
|
128
|
-
1. Trust the current MCP/session when it is already injected by the runtime; only run auth/workspace recovery after a tool explicitly reports an auth, credential, or workspace error
|
|
129
|
-
2. Confirm whether the task is read-only or write-impacting
|
|
130
|
-
3. Classify the build scope:
|
|
131
|
-
- complete system/package -> `package_apply` or `package_get`, then one `app_schema_apply(package_id=..., apps=[...])`
|
|
132
|
-
- single app -> `app_resolve` / `app_get`, then app-scoped apply tools
|
|
133
|
-
- record/task/data request -> leave builder and use the matching record/task skill
|
|
134
|
-
4. Resolve the smallest stable target:
|
|
135
|
-
- app-scoped work -> `app_resolve`
|
|
136
|
-
- package-scoped work with known id -> `package_get`
|
|
137
|
-
- portal inventory -> `portal_list`
|
|
138
|
-
5. Read only the smallest config slice needed:
|
|
139
|
-
- app map -> `app_get` (default entry; includes compact views, charts, custom buttons, and associated resource pool)
|
|
140
|
-
- fields -> `app_get_fields`
|
|
141
|
-
- layout -> `app_get_layout`
|
|
142
|
-
- views -> `app_get_views` only when the app_get compact list is not enough
|
|
143
|
-
- flow -> `app_get_flow`
|
|
144
|
-
- charts -> `app_get_charts` only when the app_get compact list is not enough
|
|
145
|
-
- portal -> `portal_get`
|
|
146
|
-
6. If the public shape is unclear, call `builder_tool_contract`
|
|
147
|
-
7. Apply the smallest patch tool that fits:
|
|
148
|
-
- fields -> `app_schema_apply`
|
|
149
|
-
- layout -> `app_layout_apply`
|
|
150
|
-
- flow -> `app_flow_apply`
|
|
151
|
-
- existing views -> `app_views_apply.patch_views`; new/full views -> `app_views_apply.upsert_views`
|
|
152
|
-
- existing buttons -> `app_custom_buttons_apply.patch_buttons`; new/full buttons -> `app_custom_buttons_apply.upsert_buttons`
|
|
153
|
-
- existing associated resources -> `app_associated_resources_apply.patch_resources`; new/full resources -> `app_associated_resources_apply.upsert_resources`
|
|
154
|
-
- existing charts -> `app_charts_apply.patch_charts`; new/full charts -> `app_charts_apply.upsert_charts`
|
|
155
|
-
- portal -> `portal_apply`
|
|
156
|
-
- package metadata/layout -> `package_apply`
|
|
157
|
-
8. Use `app_publish_verify` only when the user explicitly wants final publish/live verification or you need a dedicated verification pass
|
|
158
|
-
|
|
159
|
-
## Safe Usage Rules
|
|
160
|
-
|
|
161
|
-
- Do not guess package identity from a loose name. Public package work assumes a known `package_id`, or an explicit create/update intent through `package_apply`.
|
|
162
|
-
- Do not perform routine auth probes before every builder action in runtime contexts with injected MCP credentials; recover auth only after an actual auth/workspace failure.
|
|
163
|
-
- If `package_id` is unknown, derive it from related app/portal readback when possible; otherwise ask the user instead of falling back to hidden package lookup tools.
|
|
164
|
-
- Do not use `package_create` or `package_attach_app` as a public default path. If they still appear in low-level code, treat them as internal/legacy implementation details.
|
|
165
|
-
- Do not use raw `portal_*` writes or raw `qingbi_report_*` writes as the default builder strategy.
|
|
166
|
-
- `app_schema_apply`, `app_layout_apply`, `app_flow_apply`, and `app_views_apply` publish by default; `app_custom_buttons_apply` and `app_associated_resources_apply` publish after at least one write succeeds and do not accept a draft-only `publish` parameter; `app_charts_apply` is immediate-live without publish.
|
|
167
|
-
- When creating or updating fields, configure the app data title/cover directly in field JSON: `as_data_title: true` is required on exactly one readable top-level title field; `as_data_cover: true` is optional and only valid on one top-level `attachment` field.
|
|
168
|
-
- Do not add platform system fields to `add_fields`; if the user asks for record id, number, applicant, creation/update time, or workflow status, use the built-in data/list/readback fields instead of creating duplicate controls.
|
|
169
|
-
- If the same validation error repeats twice, stop guessing and re-read `builder_tool_contract`.
|
|
170
|
-
- For workflow assignees, prefer `role_search` over explicit members unless the user explicitly wants named members.
|
|
171
|
-
- Public flow building is still intentionally limited to stable linear workflows. If a requirement sounds like branches/conditions, explain the limitation instead of freehanding unsupported graph shapes.
|
|
172
|
-
- Respect collaborative edit locks. Only use `app_release_edit_lock_if_mine` when the lock owner is the current authenticated user.
|
|
173
|
-
- If the supported builder surface is still awkward or blocked after reasonable use, summarize the gap, ask whether to submit feedback, and call `feedback_submit` only after explicit user confirmation.
|
|
174
|
-
|
|
175
|
-
## Response Interpretation
|
|
176
|
-
|
|
177
|
-
- All builder apply/write tools return a standard UI envelope in addition to legacy fields:
|
|
178
|
-
`schema_version`, `operation`, `summary`, and `resources[]`.
|
|
179
|
-
- For UI cards or quick narration, read `resources[]` first. Each resource has `resource_type`, `operation`, `status`, `id`, `key`, `name`, typed `ids`, and `parent`.
|
|
180
|
-
- Use legacy fields such as `field_diff`, `views_diff`, `chart_results`, `created/updated/removed`, and `verification` only for compatibility and troubleshooting.
|
|
181
|
-
- Treat post-write readback as the source of truth, not just write status codes.
|
|
182
|
-
- `success` means write and verification completed; `partial_success` means the write landed but verification is incomplete.
|
|
183
|
-
- For portals, distinguish clearly between:
|
|
184
|
-
- base-info-only update with layout preserved
|
|
185
|
-
- full sections replace
|
|
186
|
-
- For object apply tools, distinguish clearly between:
|
|
187
|
-
- `patch_*`: public partial parameter replacement; the tool hydrates current config and full-saves internally
|
|
188
|
-
- `upsert_*`: create or full target configuration; omitted fields may mean default/clear depending on that object
|
|
189
|
-
- For charts, distinguish clearly between:
|
|
190
|
-
- base / visibility change
|
|
191
|
-
- real chart-config change
|
|
192
|
-
- For app permissions, report `can_edit_app_base` separately from `can_edit_form / can_edit_flow / can_edit_views / can_edit_charts`.
|
|
193
|
-
|
|
194
|
-
## Practical Patterns
|
|
195
|
-
|
|
196
|
-
- Read one package: `package_get`
|
|
197
|
-
- Create or update one package: `package_apply`
|
|
198
|
-
- Resolve one app: `app_resolve`
|
|
199
|
-
- Read one app map: `app_get`
|
|
200
|
-
- Read fields only: `app_get_fields`
|
|
201
|
-
- Read layout summary: `app_get_layout`
|
|
202
|
-
- Read views summary: `app_get_views`
|
|
203
|
-
- Read flow summary: `app_get_flow`
|
|
204
|
-
- Read chart summary: `app_get_charts`
|
|
205
|
-
- Read portal config: `portal_get`
|
|
206
|
-
- Search members or roles: `member_search`, `role_search`
|
|
207
|
-
- Create reusable role: `role_create`
|
|
208
|
-
- Add/update/remove fields: `app_schema_apply`
|
|
209
|
-
- Merge or replace layout: `app_layout_apply`
|
|
210
|
-
- Replace workflow: `app_flow_apply`
|
|
211
|
-
- Upsert/patch/remove views: `app_views_apply`
|
|
212
|
-
- Upsert/patch/remove custom buttons and bind them to header/detail view positions: `app_custom_buttons_apply`
|
|
213
|
-
- Upsert/patch/remove app associated reports/views and per-view display: `app_associated_resources_apply`
|
|
214
|
-
- Upsert/patch/remove/reorder charts: `app_charts_apply`
|
|
215
|
-
- Create or update portal pages: `portal_apply`
|
|
216
|
-
- Release your own stale edit lock: `app_release_edit_lock_if_mine`
|
|
217
|
-
- Final publish verification: `app_publish_verify`
|
|
218
|
-
|
|
219
|
-
## Button Pattern
|
|
220
|
-
|
|
221
|
-
Use `app_custom_buttons_apply` for the whole custom-button path: button body, add-data mapping, default values, and placement.
|
|
222
|
-
|
|
223
|
-
```json
|
|
224
|
-
{
|
|
225
|
-
"tool_name": "app_custom_buttons_apply",
|
|
226
|
-
"arguments": {
|
|
227
|
-
"app_key": "EMPLOYEE_APP",
|
|
228
|
-
"upsert_buttons": [
|
|
229
|
-
{
|
|
230
|
-
"client_key": "add_worklog",
|
|
231
|
-
"button_text": "快捷添加工时",
|
|
232
|
-
"style_preset": "primary_blue",
|
|
233
|
-
"button_icon": "ex-plus-circle",
|
|
234
|
-
"trigger_action": "addData",
|
|
235
|
-
"trigger_add_data_config": {
|
|
236
|
-
"target_app_key": "WORKLOG_APP",
|
|
237
|
-
"field_mappings": [
|
|
238
|
-
{"source_field": "数据ID", "target_field": "关联员工"},
|
|
239
|
-
{"source_field": "员工名称", "target_field": "员工姓名"},
|
|
240
|
-
{"source_field": "所属部门", "target_field": "部门名称"}
|
|
241
|
-
],
|
|
242
|
-
"default_values": {
|
|
243
|
-
"工时类型": "日常工作",
|
|
244
|
-
"状态": "待提交"
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
],
|
|
249
|
-
"remove_buttons": [],
|
|
250
|
-
"view_configs": [
|
|
251
|
-
{
|
|
252
|
-
"view_key": "EMPLOYEE_VIEW",
|
|
253
|
-
"mode": "merge",
|
|
254
|
-
"buttons": [
|
|
255
|
-
{"button_ref": "add_worklog", "placement": "detail", "primary": true}
|
|
256
|
-
]
|
|
257
|
-
}
|
|
258
|
-
]
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
`button_ref` may be a same-call `client_key` or an existing `button_id`. Supported placements are `header`, `detail`, and `list`; `list` maps to the backend `INSIDE` row/list button position.
|
|
264
|
-
|
|
265
|
-
For add-data buttons that create a child record linked back to the current record, map `source_field: "数据ID"` to the target relation field. Do not use raw `que_relation` unless maintaining an existing backend config.
|
|
266
|
-
|
|
267
|
-
## Resources
|
|
268
|
-
|
|
269
|
-
- Shared public-surface baseline: [public-surface-sync.md](references/public-surface-sync.md)
|
|
270
|
-
- Environment switching: [references/environments.md](references/environments.md)
|
|
271
|
-
- Tool choice and sequencing: [references/tool-selection.md](references/tool-selection.md)
|
|
272
|
-
- Field matching rules: [references/match-rules.md](references/match-rules.md)
|
|
273
|
-
- Result semantics and gotchas: [references/gotchas.md](references/gotchas.md)
|
|
274
|
-
- Create one app in an existing package: [references/create-app.md](references/create-app.md)
|
|
275
|
-
- Update fields only: [references/update-schema.md](references/update-schema.md)
|
|
276
|
-
- Update layout only: [references/update-layout.md](references/update-layout.md)
|
|
277
|
-
- Update workflow only: [references/update-flow.md](references/update-flow.md)
|
|
278
|
-
- Workflow assignees and node permissions: [references/flow-actors-and-permissions.md](references/flow-actors-and-permissions.md)
|
|
279
|
-
- Update views only: [references/update-views.md](references/update-views.md)
|
|
280
|
-
- Standard end-to-end builder sequences: [references/solution-playbooks.md](references/solution-playbooks.md)
|
|
@@ -1,4 +0,0 @@
|
|
|
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."
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
# Create App
|
|
2
|
-
|
|
3
|
-
Use this when the user wants one new app inside an existing package.
|
|
4
|
-
This playbook follows the current public builder surface, not legacy package helper tools.
|
|
5
|
-
|
|
6
|
-
Do not use this playbook when the user is really asking for a system/package with multiple forms or modules. In that case:
|
|
7
|
-
|
|
8
|
-
1. read or create the package through `package_get` / `package_apply`
|
|
9
|
-
2. create the related apps in one `app_schema_apply(package_id=..., apps=[...])` call
|
|
10
|
-
3. keep package ownership on the public `package_id` path instead of a separate attach step
|
|
11
|
-
4. add same-call relation fields with `target_app_ref` when one new app references another new app
|
|
12
|
-
5. choose explicit non-template `icon + color` for each new package/app
|
|
13
|
-
|
|
14
|
-
Hierarchy reminder:
|
|
15
|
-
|
|
16
|
-
- package -> app -> field -> relation
|
|
17
|
-
- another business object is another app, not a text field
|
|
18
|
-
|
|
19
|
-
If creating a brand new package would help, ask the user to confirm package creation first. After confirmation, create it through `package_apply(create_if_missing=true, package_name=...)`.
|
|
20
|
-
|
|
21
|
-
## Minimal sequence
|
|
22
|
-
|
|
23
|
-
1. `package_get` if `package_id` is already known; otherwise derive the package from related readback or ask the user for the id
|
|
24
|
-
2. `app_resolve`
|
|
25
|
-
3. `app_schema_apply`
|
|
26
|
-
4. `app_publish_verify` only when the user asks for explicit final verification
|
|
27
|
-
|
|
28
|
-
## Multi-app systems are different
|
|
29
|
-
|
|
30
|
-
If the user says things like:
|
|
31
|
-
|
|
32
|
-
- “创建一个完整应用包”
|
|
33
|
-
- “包含项目、需求、任务、缺陷、团队这几个表单”
|
|
34
|
-
- “这些表单之间建立关联关系”
|
|
35
|
-
|
|
36
|
-
then do not treat that as one app.
|
|
37
|
-
|
|
38
|
-
Use this pattern instead:
|
|
39
|
-
|
|
40
|
-
1. `package_get` or `package_apply(create_if_missing=true, package_name=...)`
|
|
41
|
-
2. for a multi-app system, run one `app_schema_apply` with `package_id` and `apps[]`
|
|
42
|
-
3. use `apps[].client_key` plus relation field `target_app_ref` when one new app references another new app
|
|
43
|
-
|
|
44
|
-
## Example
|
|
45
|
-
|
|
46
|
-
When designing fields, do not add platform system fields such as `数据ID`, `编号`, `申请人`, `申请时间`, `创建人`, `创建时间`, `提交人`, `提交时间`, `更新时间`, `更新人`, `当前流程状态`, `当前处理人`, `当前处理节点`, or `流程标题`. Qingflow provides them automatically; create only business fields.
|
|
47
|
-
|
|
48
|
-
Create a new package only after the user confirms package creation:
|
|
49
|
-
|
|
50
|
-
```json
|
|
51
|
-
{
|
|
52
|
-
"tool_name": "package_apply",
|
|
53
|
-
"arguments": {
|
|
54
|
-
"profile": "default",
|
|
55
|
-
"package_name": "研发项目管理",
|
|
56
|
-
"create_if_missing": true,
|
|
57
|
-
"icon": "briefcase",
|
|
58
|
-
"color": "azure"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Read the package when `package_id` is already known:
|
|
64
|
-
|
|
65
|
-
```json
|
|
66
|
-
{
|
|
67
|
-
"tool_name": "package_get",
|
|
68
|
-
"arguments": {
|
|
69
|
-
"profile": "default",
|
|
70
|
-
"package_id": 1218950
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Apply schema for a new app:
|
|
76
|
-
|
|
77
|
-
```json
|
|
78
|
-
{
|
|
79
|
-
"tool_name": "app_schema_apply",
|
|
80
|
-
"arguments": {
|
|
81
|
-
"profile": "default",
|
|
82
|
-
"app_name": "客户订单",
|
|
83
|
-
"package_id": 1218950,
|
|
84
|
-
"icon": "delivery-box-1",
|
|
85
|
-
"color": "emerald",
|
|
86
|
-
"create_if_missing": true,
|
|
87
|
-
"publish": true,
|
|
88
|
-
"add_fields": [
|
|
89
|
-
{"name": "订单编号", "type": "text", "required": true, "as_data_title": true},
|
|
90
|
-
{"name": "客户名称", "type": "text", "required": true},
|
|
91
|
-
{"name": "订单封面", "type": "attachment", "as_data_cover": true},
|
|
92
|
-
{"name": "订单金额", "type": "amount"},
|
|
93
|
-
{"name": "状态", "type": "single_select", "options": [{"label": "草稿"}, {"label": "进行中"}, {"label": "已完成"}], "required": true}
|
|
94
|
-
],
|
|
95
|
-
"update_fields": [],
|
|
96
|
-
"remove_fields": []
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Apply schema for multiple apps in one call:
|
|
102
|
-
|
|
103
|
-
```json
|
|
104
|
-
{
|
|
105
|
-
"tool_name": "app_schema_apply",
|
|
106
|
-
"arguments": {
|
|
107
|
-
"profile": "default",
|
|
108
|
-
"package_id": 1218950,
|
|
109
|
-
"create_if_missing": true,
|
|
110
|
-
"publish": true,
|
|
111
|
-
"apps": [
|
|
112
|
-
{
|
|
113
|
-
"client_key": "customer",
|
|
114
|
-
"app_name": "客户",
|
|
115
|
-
"icon": "business-personalcard",
|
|
116
|
-
"color": "emerald",
|
|
117
|
-
"add_fields": [
|
|
118
|
-
{"name": "客户名称", "type": "text", "required": true, "as_data_title": true}
|
|
119
|
-
]
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
"client_key": "order",
|
|
123
|
-
"app_name": "订单",
|
|
124
|
-
"icon": "delivery-box-1",
|
|
125
|
-
"color": "blue",
|
|
126
|
-
"add_fields": [
|
|
127
|
-
{"name": "订单编号", "type": "text", "required": true, "as_data_title": true},
|
|
128
|
-
{
|
|
129
|
-
"name": "关联客户",
|
|
130
|
-
"type": "relation",
|
|
131
|
-
"target_app_ref": "customer",
|
|
132
|
-
"display_field": {"name": "客户名称"},
|
|
133
|
-
"visible_fields": [{"name": "客户名称"}]
|
|
134
|
-
}
|
|
135
|
-
]
|
|
136
|
-
}
|
|
137
|
-
]
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Data title is required: mark exactly one top-level field with `as_data_title: true`. Data cover is optional and only valid on a top-level `attachment` field.
|
|
143
|
-
|
|
144
|
-
## Common failures
|
|
145
|
-
|
|
146
|
-
### `APP_NOT_FOUND`
|
|
147
|
-
|
|
148
|
-
Expected on create. Continue with `create_if_missing=true`.
|
|
149
|
-
|
|
150
|
-
### `CREATE_APP_ROUTE_NOT_FOUND`
|
|
151
|
-
|
|
152
|
-
The create route did not resolve in the current backend route context. In Wingent Momo runtime, first retry the same `app_schema_apply` after confirming the injected session is still active. Only run `workspace_select` if a business tool explicitly reports a missing or wrong workspace.
|
|
153
|
-
|
|
154
|
-
### Hierarchy modeling mistake
|
|
155
|
-
|
|
156
|
-
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:
|
|
157
|
-
|
|
158
|
-
- one package
|
|
159
|
-
- many apps
|
|
160
|
-
- relation fields between those apps
|
|
@@ -1,63 +0,0 @@
|
|
|
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 builder apply flows end-to-end with readback verification, or `solution_install` when the user is installing an existing packaged solution
|
|
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
|