@qingflow-tech/qingflow-cli 1.1.43 → 1.1.44-beta.1
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 +13 -6
- package/entry_point.py +1 -1
- package/npm/bin/qingflow.mjs +1 -2
- package/npm/lib/runtime.mjs +3 -7
- package/package.json +2 -2
- package/pyproject.toml +3 -4
- package/skills/qingflow-app-form/SKILL.md +66 -0
- package/skills/qingflow-app-form/agents/openai.yaml +4 -0
- package/skills/qingflow-cli/SKILL.md +8 -6
- package/skills/qingflow-cli/manifest.yaml +1 -1
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_APP_DELIVERY_WORKFLOW.md +4 -4
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_EXPLORATION_REPORT.md +1 -1
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_FIELD_DATA_TYPES.md +1 -1
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_SCHEMA_APPLY_FIELD_TYPES_AND_SCENARIOS.md +4 -4
- package/skills/qingflow-cli/reference/builder/10-build-single-app.md +5 -5
- package/skills/qingflow-cli/reference/builder/20-build-complete-system.md +14 -14
- package/skills/qingflow-cli/reference/builder/30-schema-fields.md +106 -103
- package/skills/qingflow-cli/reference/builder/40-layout.md +39 -31
- package/skills/qingflow-cli/reference/builder/README.md +9 -9
- package/skills/qingflow-cli/reference/builder/code-integrations/README.md +4 -2
- package/skills/qingflow-cli/reference/builder/code-integrations/code-block.md +2 -0
- package/skills/qingflow-cli/reference/builder/code-integrations/q-linker.md +2 -0
- package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +45 -38
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md +1 -1
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +1 -1
- package/skills/qingflow-cli/reference/examples/README.md +3 -3
- package/skills/qingflow-common/SKILL.md +47 -0
- package/skills/qingflow-common/agents/openai.yaml +4 -0
- package/src/qingflow_mcp/__main__.py +2 -3
- package/src/qingflow_mcp/app_form_compat.py +104 -0
- package/src/qingflow_mcp/app_form_validator.py +462 -0
- package/src/qingflow_mcp/builder_facade/app_form.py +4196 -0
- package/src/qingflow_mcp/builder_facade/app_form_schema.py +425 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/manifest.json +42 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/complete.json +2969 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/address.json +392 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/amount.json +236 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/attachment.json +425 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/code_block.json +318 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/data_relation.json +580 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/date.json +150 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/datetime.json +150 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/department.json +345 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/email.json +190 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/link.json +190 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/long_text.json +190 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/member.json +484 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/multi_select.json +214 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/number.json +236 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/phone.json +199 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/q_linker.json +412 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/relation.json +454 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_choice.json +214 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_select.json +214 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/subtable.json +1921 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/text.json +190 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/formula.json +1594 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/summary.json +718 -0
- package/src/qingflow_mcp/builder_facade/service.py +8 -4
- package/src/qingflow_mcp/cli/commands/builder.py +93 -28
- package/src/qingflow_mcp/cli/json_io.py +21 -2
- package/src/qingflow_mcp/cli/main.py +3 -39
- package/src/qingflow_mcp/public_surface.py +5 -2
- package/src/qingflow_mcp/response_trim.py +50 -0
- package/src/qingflow_mcp/server.py +24 -3
- package/src/qingflow_mcp/server_app_builder.py +44 -87
- package/src/qingflow_mcp/tools/ai_builder_tools.py +103 -100
- package/src/qingflow_mcp/tools/app_tools.py +46 -65
- package/src/qingflow_mcp/tools/record_tools.py +3 -3
- package/src/qingflow_mcp/version.py +2 -4
- package/docs/local-agent-install.md +0 -370
- package/skills/qingflow-mcp-setup/SKILL.md +0 -115
- package/skills/qingflow-mcp-setup/agents/openai.yaml +0 -4
- package/skills/qingflow-mcp-setup/references/claude-desktop.md +0 -34
- package/skills/qingflow-mcp-setup/references/environments.md +0 -62
- package/skills/qingflow-mcp-setup/references/generic-stdio.md +0 -32
- package/skills/qingflow-mcp-setup/scripts/check_local_server.sh +0 -38
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Builder 应用交付重流程 SOP:分组 → 应用定位 → 读场 → 改场 → 发布校验
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
本文是历史低层交付备忘,不是当前表单写入 SOP。稳定 CLI 公开入口仍为 `qingflow builder` / `qingflow build`,但表单字段、分组、布局和设置必须使用 `qingflow --json builder app-form schema/get/validate/apply`,应用删除使用 `qingflow --json builder app delete --app-key APP_KEY`;本文件中的 `app_schema_apply` / `app_layout_apply` / `builder schema apply` / `builder layout apply` 只用于识别旧载荷和迁移,不得直接调用。
|
|
4
4
|
|
|
5
5
|
> **权限**:应用基础信息(`app_name` / 图标 / 可见性)、表单、流程、自定义按钮本体、应用级关联资源池走 **应用搭建 / EditAppAuth**;视图更新/删除、按钮的视图位置配置(`view_configs`)和视图内关联资源展示配置走 **视图管理 / ViewManagementAuth**(后端 `beingViewManageStatus`;未开启高级应用权限时等价回落到 DataManageAuth);**新建视图**额外需要 **DataManageAuth**;报表走 **数据管理 / DataManageAuth**。失败码常见 **40002 / 40161 / 编辑锁** 等,见主技能与 **ADMIN** 速查。
|
|
6
6
|
|
|
7
|
-
>
|
|
8
|
-
> `qingflow --json builder contract --tool-name <
|
|
7
|
+
> **契约**:当前表单契约固定通过 `qingflow --json builder app-form schema` 获取;其它公开 `app_*_apply` 仅是 `builder contract --tool-name` 的参数值,**不是可执行 CLI 子命令**。其 **`allowed_keys` / `allowed_values` / `execution_notes` / 示例** 以在线契约为准,命令:
|
|
8
|
+
> `qingflow --json builder contract --tool-name <app_flow_apply|app_views_apply|app_custom_buttons_apply|app_associated_resources_apply|app_publish_verify>`
|
|
9
9
|
>
|
|
10
10
|
> **CLI 文件载荷注意**:契约示例里可能出现 `"profile": "default"`,那是请求上下文示例;使用 CLI 的 `--*-file` 时不要把 `profile` 写进 JSON 文件。需要指定账号上下文时用根级参数:`qingflow --profile default ...`。
|
|
11
11
|
>
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
| D | **`app_get` / `app_get_fields`** | `qingflow --json builder app get --app-key <APP_KEY>` / `qingflow --json builder app get --app-key <APP_KEY> fields` | 默认 `app_get` 是应用地图,含字段摘要、视图、图表、自定义按钮和关联资源池;`fields` 只读表单可搭建字段 |
|
|
28
28
|
| D | **`app_read_layout_summary`** | `qingflow --json builder app get --app-key <APP_KEY> layout` | 读 **布局**(段落、`rows` 字段名矩阵、`unplaced_fields`) |
|
|
29
29
|
| D | **`app_read_flow_summary`** | `qingflow --json builder app get --app-key <APP_KEY> flow` | 读 **流程**是否启用、节点摘要(公开面能力有限) |
|
|
30
|
-
| E |
|
|
31
|
-
| F |
|
|
30
|
+
| E | **AppForm** | `qingflow --json builder app-form validate --schema-version VERSION --file DECLARATION.json` -> `qingflow --json builder app-form apply --file DECLARATION.json` | 完整 AppForm:字段、分组、行、设置和应用创建/更新 |
|
|
31
|
+
| F | — | 由 AppForm 的 `body` 一并维护 | 表单段落 / 行 / 单元格随完整声明提交 |
|
|
32
32
|
| G | **`app_flow_apply`** | `qingflow builder flow apply …` | **线性流程** 节点与转移(见契约限制) |
|
|
33
33
|
| G′(维护) | **`app_custom_buttons_apply`** | `qingflow builder button apply …` | 仅用于用户明确要求维护已有独立按钮:样式/图标、跨视图复用、删除按钮本体或批量重排 |
|
|
34
34
|
| G″ | **`app_associated_resources_apply`** | `qingflow builder associated-resource apply …` | 管理应用级关联视图/报表池,并配置视图详情侧边栏展示 |
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
这些不是独立流程,而是读、写、改三个动作的多资源形态:
|
|
42
42
|
|
|
43
43
|
- **批量读**:读多个应用时优先用 `--app-keys`,例如 `builder app get --app-keys a,b fields`、`builder app get --app-keys a,b views`、`builder button get --app-keys a,b`、`builder associated-resource get --app-keys a,b`、`builder publish verify --app-keys a,b`。读结果同时看成功项和 `errors[]`,不要因单个应用失败否定全批。
|
|
44
|
-
-
|
|
44
|
+
- **批量写**:视图、按钮、关联资源和报表按各自资源契约使用对应的批量文件;应用表单不走 `apps-file`,而是每个应用独立提交完整 AppForm 声明。
|
|
45
45
|
- **局部改**:只改已存在资源的少量参数时用对应 patch 文件;`patch_*` 内只写目标定位字段和 `set/unset`,不要用不完整 `upsert_*` 伪装局部更新。
|
|
46
46
|
|
|
47
47
|
---
|
|
@@ -102,7 +102,7 @@ qingflow --json builder package get --package-id <package_id>
|
|
|
102
102
|
|
|
103
103
|
---
|
|
104
104
|
|
|
105
|
-
## 3.
|
|
105
|
+
## 3. 应用定位与 AppForm 创建
|
|
106
106
|
|
|
107
107
|
### 3.1 `app_resolve`(CLI)
|
|
108
108
|
|
|
@@ -118,9 +118,11 @@ qingflow --json builder app resolve \
|
|
|
118
118
|
|
|
119
119
|
- **勿混用**:`--app-key` 与(`--app-name` 或 `--package-id`)**不能同时出现**;只能二选一模式(见 `builder.py` 校验)。
|
|
120
120
|
|
|
121
|
-
### 3.2
|
|
121
|
+
### 3.2 单应用新建(历史 `app_schema_apply` 迁移说明)
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
当前新建和更新请使用 `qingflow --json builder app-form schema/get/validate/apply`;下方旧命令仅用于迁移脚本识别,不能执行。
|
|
124
|
+
|
|
125
|
+
历史脚本可能先读取图标候选;当前 AppForm 新建同样先读取并固定合法图标和颜色:
|
|
124
126
|
|
|
125
127
|
```bash
|
|
126
128
|
qingflow --json builder icon catalog
|
|
@@ -139,23 +141,27 @@ qingflow builder schema apply \
|
|
|
139
141
|
...
|
|
140
142
|
```
|
|
141
143
|
|
|
144
|
+
上面的 `builder schema apply` 示例是 retired 命令,当前 CLI parser 不接受;这里只保留参数形状供迁移脚本定位。
|
|
145
|
+
|
|
142
146
|
- **`--icon` / `--color`**:取值以 `builder contract --tool-name app_schema_apply` / 当前 CLI 契约候选为准;不要自造 `sales-*`、`crm-*` 等业务语义 key。契约未返回候选值时省略该参数,不要猜测写入。
|
|
143
147
|
|
|
144
148
|
- **单应用创建模式要件**(与契约一致):**`package_id` + `app_name`**(或 CLI 的 app-title 映射到 app_name)。
|
|
145
149
|
- **图标必填**:创建应用必须显式传合法的 **`icon + color`**;不要用 `template`。CLI 只校验候选,不根据应用名称自动猜图标。多应用批量创建时,每个新应用应使用不同 `icon`。
|
|
146
|
-
-
|
|
150
|
+
- **数据标题必填**:旧载荷使用 `as_data_title` / `as_data_cover`;当前 AppForm 对应 `dataTitle` / `dataCover`,并要求最终表单只有一个顶层标题字段。
|
|
147
151
|
- **编辑模式**:**仅** **`--app-key`**(可选改名 `--app-name`),**不要**与 `package_id` 混用。
|
|
148
152
|
|
|
149
|
-
### 3.3
|
|
153
|
+
### 3.3 多应用一次性新建(历史 multi-app 迁移说明)
|
|
150
154
|
|
|
151
|
-
|
|
155
|
+
本节下方的 `--apps-file` 示例是旧 CLI 载荷,仅用于识别/迁移历史脚本;当前完整系统应逐个创建 AppForm,记录返回的 `appKey` 后再绑定关系。
|
|
156
|
+
|
|
157
|
+
旧版本允许用一个 `apps-file` 同批创建多个业务对象。当前版本不再公开该入口;完整系统应先分别创建无关系 AppForm,记录每个返回的 `appKey`,再用完整 AppForm 声明补充关系字段。以下内容只用于识别和迁移旧脚本:
|
|
152
158
|
|
|
153
159
|
```bash
|
|
154
160
|
qingflow builder schema apply \
|
|
155
161
|
--apps-file tmp/apps.json
|
|
156
162
|
```
|
|
157
163
|
|
|
158
|
-
`apps.json`
|
|
164
|
+
`apps.json` 中的 `package_id`、`client_key`、`app_name`、`add_fields` 和 `target_app_ref` 都是旧 snake_case 载荷键,不得改作当前 AppForm 示例:
|
|
159
165
|
|
|
160
166
|
```json
|
|
161
167
|
{
|
|
@@ -195,8 +201,8 @@ qingflow builder schema apply \
|
|
|
195
201
|
- 如果返回 `MULTI_APP_STATIC_VALIDATION_FAILED`,读取 `details.issues[]` 的 `path/error_code/fix_hint` 修 payload;这是写入前失败,通常可以修正后重试,不需要 readback。
|
|
196
202
|
- 多应用 schema apply 不做事务回滚;如果部分失败,只补失败的 `apps[].row_number`,不要整批重复提交。
|
|
197
203
|
- 这个模式只负责应用壳与字段;视图、按钮、关联资源、报表仍拿返回的 `app_key` 继续走各自 apply 工具。
|
|
198
|
-
-
|
|
199
|
-
-
|
|
204
|
+
- `target_app_ref`、`as_data_title`、`display_field` 等只属于旧载荷。迁移时将关系改写为 AppForm `config.targetAppKey`、`config.displayField`、`config.visibleFields`,并使用已确认的真实 app key。
|
|
205
|
+
- 历史 schema adapter 写入后可读 `details.relation_readback_matrix[]`:逐项核对旧 `target_app_key`、`relation_mode`、`display_field`、`visible_fields`。迁移到当前 AppForm 后,改为读取 draft/published form 的 `config.targetAppKey`、`config.relationMode`、`config.displayField`、`config.visibleFields`,不要提交旧 `update_fields` patch。
|
|
200
206
|
- 一个应用可以包含多个 `relation` 字段;不要因为 relation 数量超过 1 就降级成文本。若真实写入失败或 relation readback mismatch,只按实际错误和 `details.relation_repair_plan[]` 做最小修复。
|
|
201
207
|
- 完整系统遇到超时、`partial_success`、`write_executed=true`、`safe_to_retry=false` 或 readback 不完整时,先按 §3.4 读回,不要直接拆成单应用创建。
|
|
202
208
|
|
|
@@ -221,7 +227,7 @@ qingflow builder schema apply \
|
|
|
221
227
|
重试/修复限制:
|
|
222
228
|
|
|
223
229
|
- 继续使用原始 `app_name` 与业务命名。重名冲突表示需要读回/更新/询问用户,不是创建 `V2` 的理由。
|
|
224
|
-
-
|
|
230
|
+
- 迁移到当前 AppForm 后,不再继续补发 `client_key + target_app_ref`;先确认每个实际 `appKey`,再提交完整声明和 `config.targetAppKey`。
|
|
225
231
|
- 若 readback 证明主应用已存在但部分 relation 缺失,修 relation 前先说明数据影响:是否会清空已有值、是否需要迁移、是否可安全重试。
|
|
226
232
|
- 如果已有包内已经存在相似应用,先决定“复用/更新/新建缺失应用/询问用户”,不要用相似重名或后缀绕开。
|
|
227
233
|
|
|
@@ -251,11 +257,13 @@ qingflow --json builder app get --app-key "<APP_KEY>" flow
|
|
|
251
257
|
|
|
252
258
|
---
|
|
253
259
|
|
|
254
|
-
## 5.
|
|
260
|
+
## 5. 改场三口(历史 schema/layout 迁移说明 + 当前 flow)
|
|
261
|
+
|
|
262
|
+
`app_schema_apply` / `app_layout_apply` 已从公开 MCP/CLI surface 移除。下方 schema/layout 命令只用于迁移旧脚本;当前表单和布局必须使用 `qingflow --json builder app-form schema/get/validate/apply`。
|
|
255
263
|
|
|
256
|
-
### 5.1
|
|
264
|
+
### 5.1 历史字段载荷:`builder schema apply`(仅迁移识别)
|
|
257
265
|
|
|
258
|
-
|
|
266
|
+
以下示例是 retired `add_fields` 载荷,不能执行;当前字段新增请回到 AppForm 完整声明。
|
|
259
267
|
|
|
260
268
|
```bash
|
|
261
269
|
qingflow builder schema apply \
|
|
@@ -266,7 +274,7 @@ qingflow builder schema apply \
|
|
|
266
274
|
(路径以 `qingflow-cli/` 技能根目录为基准;执行时可解析为该技能目录下的实际文件。)
|
|
267
275
|
|
|
268
276
|
- **`name`** 须为当前应用内 **唯一** 的控件显示名;若报重名,改 **`示例搭建_CLI单行`** 后再执行。
|
|
269
|
-
-
|
|
277
|
+
- 本文件只记录旧 `app_schema_apply` 的 `add_fields` 形状,供迁移脚本识别;当前新建和字段维护均回到完整 AppForm 声明。
|
|
270
278
|
|
|
271
279
|
```bash
|
|
272
280
|
qingflow builder schema apply \
|
|
@@ -278,11 +286,11 @@ qingflow builder schema apply \
|
|
|
278
286
|
```
|
|
279
287
|
|
|
280
288
|
- **`--publish` / `--no-publish`**:默认发布;`--no-publish` 仅草稿/预检语义(见 `server_app_builder` 总述:**schema/layout/views/flow** 的 noop 与发布关系以契约为准)。
|
|
281
|
-
-
|
|
282
|
-
-
|
|
289
|
+
- **文件体形状**:旧契约的顶层 **`add_fields` / `update_fields` / `remove_fields`** 数组;当前 CLI 不接受该形状。
|
|
290
|
+
- **标题/封面**:旧字段标记 `as_data_title` / `as_data_cover` 迁移为 AppForm 的 `dataTitle` / `dataCover`。
|
|
283
291
|
- **本仓实测**(`ead8ims5i401`,`--no-publish`,`name` 改为未存在过的 **`CLI搭建探针字段_可删`**):`field_diff.added` 成功;同一 **`name`** 不可重复添加,后续请改用 **[schema_add_fields_minimal.example.json](../../examples/schema/schema_add_fields_minimal.example.json)** 内模板名或自改唯一名。
|
|
284
292
|
|
|
285
|
-
### 5.2
|
|
293
|
+
### 5.2 历史布局载荷:`builder layout apply`(仅迁移识别,不可执行)
|
|
286
294
|
|
|
287
295
|
```bash
|
|
288
296
|
qingflow builder layout apply \
|
|
@@ -292,14 +300,14 @@ qingflow builder layout apply \
|
|
|
292
300
|
--sections-file tmp/sections.json
|
|
293
301
|
```
|
|
294
302
|
|
|
295
|
-
- **`mode
|
|
303
|
+
- **`mode`**:旧载荷中的 `merge`(默认)或 `replace`;当前 AppForm 不使用该局部模式,必须提交完整 `spec.body`。
|
|
296
304
|
- **`sections` JSON**:数组,元素形状见契约 **`minimal_example`**:`type: paragraph`、`paragraph_id`、`title`、`rows: [[列标题…], …]`,单元格值为 **字段显示名 `name`**(与 `app_get_fields` 一致)。
|
|
297
305
|
|
|
298
306
|
### 5.3 流程:`builder flow apply`
|
|
299
307
|
|
|
300
308
|
流程前置条件:
|
|
301
309
|
|
|
302
|
-
- 审批 / 填写 /
|
|
310
|
+
- 审批 / 填写 / 抄送类流程需要一个显式业务状态字段;当前 AppForm 应在 schema 阶段先建 `single_select` 字段并设置 `config.options`,例如 `状态`、`处理状态`、`审批状态`、`工单状态` 或 `流程阶段`。历史 schema adapter 里的 `select` 仅用于迁移识别。
|
|
303
311
|
- 不要创建平台流程系统字段:`当前流程状态`、`当前处理人`、`当前处理节点`、`流程标题`。这些只能由平台维护。
|
|
304
312
|
- 如果返回 `FLOW_DEPENDENCY_MISSING`,先执行返回的 `suggested_next_call` 补业务状态字段,再 `builder app get fields` 回读,然后重跑 flow apply;不要跳过流程后报告“流程完成”。
|
|
305
313
|
|
|
@@ -314,9 +322,9 @@ qingflow builder flow apply \
|
|
|
314
322
|
|
|
315
323
|
---
|
|
316
324
|
|
|
317
|
-
## 6.
|
|
325
|
+
## 6. 字段类型迁移对照(旧 `app_schema_apply` 载荷)
|
|
318
326
|
|
|
319
|
-
|
|
327
|
+
以下内容只帮助迁移旧载荷;当前字段类型、camelCase 配置和必填项以固定版本的 `qingflow --json builder app-form schema` 返回结果为准。
|
|
320
328
|
|
|
321
329
|
智能体可优先写更自然的字段类型,工具会在写入前归一化;读回仍显示 canonical 类型:
|
|
322
330
|
|
|
@@ -335,31 +343,30 @@ qingflow builder flow apply \
|
|
|
335
343
|
| **`date`** | 同上。 |
|
|
336
344
|
| **`datetime`** | 同上。 |
|
|
337
345
|
| **`member`** | **`name`**、**`required`**;成员选择器,无额外 scope 键(与 **department** 不同)。 |
|
|
338
|
-
| **`department`** | **`department_scope
|
|
339
|
-
| **`single_select`** / **`multi_select`** |
|
|
346
|
+
| **`department`** | 旧载荷使用 **`department_scope`**;当前 AppForm 使用 `config.departmentScope`,具体形状以 pinned schema 为准。 |
|
|
347
|
+
| **`single_select`** / **`multi_select`** | 当前 AppForm 使用 `config.options` 字符串数组;对象数组和裸 `options` 仅属于旧兼容载荷。 |
|
|
340
348
|
| **`phone`** / **`email`** | 标准校验类字段,**`name` + required**。 |
|
|
341
349
|
| **`address`** | 地址复合字段。 |
|
|
342
350
|
| **`attachment`** | 附件。 |
|
|
343
351
|
| **`boolean`** | 是否。 |
|
|
344
|
-
| **`relation`** |
|
|
345
|
-
| **`subtable`** |
|
|
346
|
-
| **`q_linker`** |
|
|
347
|
-
| **`code_block`** |
|
|
352
|
+
| **`relation`** | 旧载荷使用 `target_app_key` / `target_app_ref`;当前 AppForm 使用 `config.targetAppKey`、`config.relationMode`、`config.displayField`、`config.visibleFields`。 |
|
|
353
|
+
| **`subtable`** | 当前 AppForm 使用 `subfields[]` 及 Schema 返回的 camelCase 配置;旧 `subfield_updates` 只作迁移线索。 |
|
|
354
|
+
| **`q_linker`** | 当前 AppForm 使用 `config.qLinkerBinding`,其 `outputs[].targetField` 必须按字段 Schema 配置。 |
|
|
355
|
+
| **`code_block`** | 当前 AppForm 使用 `config.codeBlockBinding`,其 `outputs[].targetField` 必须按字段 Schema 配置。 |
|
|
348
356
|
|
|
349
357
|
### 6.1 数据标题与数据封面
|
|
350
358
|
|
|
351
|
-
- `as_data_title
|
|
352
|
-
- `as_data_cover: true`:配置应用数据封面。可选,且只能用于一个顶层 `attachment` 字段。
|
|
359
|
+
- 旧载荷的 `as_data_title` / `as_data_cover` 分别迁移为 AppForm 字段的 `dataTitle` / `dataCover`。最终表单必须有且仅有一个顶层可读标题字段;封面只能用于一个顶层 `attachment` 字段。
|
|
353
360
|
- 子表子字段不能作为标题或封面;多标题、多封面、非附件封面都会在写入前阻断。
|
|
354
361
|
- 未显式标记封面时保留/不创建封面;未能形成唯一标题时视为配置错误,不要声称应用已完整创建。
|
|
355
362
|
|
|
356
|
-
|
|
363
|
+
**迁移提示**:旧契约中的 `aliases`、`field.type_id` 和 snake_case 配置不能替代当前 AppForm Schema。主路径以 pinned schema 的 camelCase 字段和类型详情为准。
|
|
357
364
|
|
|
358
365
|
**`update_fields` 项**:**`selector`**:`que_id` 或 `field_id` 或 **`name`**;**`set`**:允许子集(**`name` / `required` / `description` / `options` / `department_scope` / … / `subfield_updates`**)。
|
|
359
366
|
|
|
360
367
|
**`remove_fields` 项**:**`que_id` / `field_id` / `name`** 之一。
|
|
361
368
|
|
|
362
|
-
|
|
369
|
+
**当前 21 种字段类型与 canonical 形状**:见 **[30-schema-fields.md](../30-schema-fields.md)**,以 pinned AppForm Schema 为准。下面的 `add_fields` 文件只是历史字段能力探针,不是正式新建应用主模板:[schema_apply_add_fields_all_types.json](../../examples/schema/schema_apply_add_fields_all_types.json)。
|
|
363
370
|
|
|
364
371
|
---
|
|
365
372
|
|
|
@@ -501,7 +508,7 @@ qingflow builder publish verify \
|
|
|
501
508
|
## 10. 交叉引用
|
|
502
509
|
|
|
503
510
|
- **最小 `add_fields` 示例**:[schema_add_fields_minimal.example.json](../../examples/schema/schema_add_fields_minimal.example.json)
|
|
504
|
-
-
|
|
511
|
+
- **历史字段 type 一次性 `add_fields` 探针(非当前主路径)**:[schema_apply_add_fields_all_types.json](../../examples/schema/schema_apply_add_fields_all_types.json)
|
|
505
512
|
- **类型与场景总表**:[30-schema-fields.md](../30-schema-fields.md)
|
|
506
513
|
- [SKILL.md](../../../SKILL.md):`builder` 命令边界、**ADMIN** 指向。
|
|
507
514
|
- [QINGFLOW_CLI_FIELD_DATA_TYPES.md](../../core/QINGFLOW_CLI_FIELD_DATA_TYPES.md):成员侧 **记录读写** 的 `kind` / 值形态(与 **搭建 `type`** 名称不同系,但可对照理解业务)。
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
| 入口 | 当前定位 |
|
|
53
53
|
| --- | --- |
|
|
54
54
|
| `builder app get` | 应用地图;轻量返回字段摘要、视图、图表、自定义按钮、关联资源池 |
|
|
55
|
-
| `builder schema
|
|
55
|
+
| `builder app-form schema/get/validate/apply` | 当前表单/字段/布局/应用设置入口;固定 AppForm schema 版本,完整声明写入并保留现有 IDs;旧 `builder schema apply` / `builder layout apply` 仅为已移除的内部兼容适配器 |
|
|
56
56
|
| `builder views apply` | 业务视图;固定筛选写 `filters`,前端查询栏写 `query_conditions` |
|
|
57
57
|
| `builder button apply` | 自定义按钮默认路径;新增数据按钮用 `field_mappings/default_values`,绑定位置用 `header/detail/list` |
|
|
58
58
|
| `builder associated-resource apply` | 应用级关联视图/报表池 + 视图展示配置;报表来源用 `report_source`,不让智能体填写后端 raw source |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **用途**:说明 **`record schema …`** 的 **`fields[]`**、**`record list` / `record get` / `record access`** 行内值、以及 **insert/update 写入 payload** 的常见对应关系;并单独说明 **选项联动、关联记录、引用填充、公式/系统题、AI 与受限类型** 等在 CLI 下的表现与处置。
|
|
4
4
|
> **依据**:当前 CLI 在 **`--json`** 下会对 **schema** 响应做 **裁剪**:通常只保留本节列出的键;**`kind`** 由内部写入类别归并而来(见下表)。**`que_type` 等若未出现在输出中**,以 **`kind` + 实跑预检** 为准。
|
|
5
|
-
> **关联**:写入值细节与成员/部门见 **[QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md](../record/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md)**;更新流程见 **[QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md](../record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md)**;只读见 **[QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md](./QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md)**;**搭建侧**
|
|
5
|
+
> **关联**:写入值细节与成员/部门见 **[QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md](../record/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md)**;更新流程见 **[QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md](../record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md)**;只读见 **[QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md](./QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md)**;**搭建侧** AppForm 的 `type`(与本文 `kind` 命名体系不同)及其 CLI 命令见 **[30-schema-fields.md](../builder/30-schema-fields.md)**;主技能 **[../SKILL.md](../../SKILL.md)**。
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -4,9 +4,9 @@ Use these files as copyable bases after reading the matching resource document.
|
|
|
4
4
|
|
|
5
5
|
| Resource | Main example | Notes |
|
|
6
6
|
|----------|--------------|-------|
|
|
7
|
-
|
|
|
8
|
-
|
|
|
9
|
-
| Existing-app layout | [layout/layout_sections_full.example.json](./layout/layout_sections_full.example.json) |
|
|
7
|
+
| Historical single-app schema probe | [schema/schema_single_app_form_standard.example.json](./schema/schema_single_app_form_standard.example.json) | Retired `--form-file` shape; use `builder app-form schema/get/validate/apply` for current declarations. |
|
|
8
|
+
| Historical multi-app schema probe | [schema/schema_multi_app_form_relation_layout.example.json](./schema/schema_multi_app_form_relation_layout.example.json) | Retired `--apps-file` shape; current systems create independent AppForms and then bind confirmed app keys. |
|
|
9
|
+
| Existing-app layout probe | [layout/layout_sections_full.example.json](./layout/layout_sections_full.example.json) | Historical layout-patch shape; current new and existing forms use the complete AppForm `spec.body`. |
|
|
10
10
|
| Views | [views/views_upsert_table_minimal.example.json](./views/views_upsert_table_minimal.example.json), [views/views_batch_full.example.json](./views/views_batch_full.example.json) | `views[]` shape with filters, query panel, view-bound buttons, batch upsert/patch/remove. |
|
|
11
11
|
| Charts | [charts/charts_upsert_dashboard_starter.example.json](./charts/charts_upsert_dashboard_starter.example.json) | Standalone chart apply; portal usually creates missing charts inline. |
|
|
12
12
|
| Portal | [portal/portal_sections_standard_workbench.example.json](./portal/portal_sections_standard_workbench.example.json) | Standard workbench with inline QingBI charts and data views. |
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qingflow-common
|
|
3
|
+
description: Route Qingflow work through the shared public concepts and choose the matching CLI or MCP package. Use when comparing Qingflow CLI and MCP capabilities, selecting an execution surface, or handing work between record, task, form, workflow, and builder skills.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Qingflow Common Concepts
|
|
7
|
+
|
|
8
|
+
Treat CLI and MCP as two invocation surfaces for the same Qingflow public contract. Choose the surface that is installed in the current runtime, then keep the same business workflow and declaration shape unless that operation is explicitly surface-specific.
|
|
9
|
+
|
|
10
|
+
## Choose A Surface
|
|
11
|
+
|
|
12
|
+
| Available runtime | Use | Best fit |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| Terminal, script, CI, or a local file workflow | Qingflow CLI | Repeatable commands and JSON files |
|
|
15
|
+
| Agent has `qingflow-mcp` tools | Qingflow MCP | Records, tasks, packages, forms, views, workflows, portals, and builder configuration |
|
|
16
|
+
|
|
17
|
+
Do not require both surfaces. If only one is installed, complete the workflow on that surface. Do not expose a CLI-only command as an MCP tool, or vice versa.
|
|
18
|
+
|
|
19
|
+
## Shared Concepts
|
|
20
|
+
|
|
21
|
+
- **AppForm** is the versioned declarative definition for an application form: app metadata, fields, sections, layout, settings, and field configuration. The same JSON declaration is used by CLI and Qingflow MCP.
|
|
22
|
+
- **Record** is runtime data written to an existing app. Use the record schema before an insert, update, import, or analysis workflow.
|
|
23
|
+
- **Task** is a workflow work item. Prefer task operations for approval, transfer, rollback, and assignee actions.
|
|
24
|
+
- **Builder resource** is package, app, view, chart, portal, navigation, or workflow configuration. It is separate from record data.
|
|
25
|
+
- **Schema version** is part of the public contract. Pin it for one AppForm or workflow operation and do not combine values from different versions.
|
|
26
|
+
|
|
27
|
+
## Invocation Mapping
|
|
28
|
+
|
|
29
|
+
| Business operation | CLI | MCP |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| Form schema/read/apply/delete | `qingflow --json builder app-form ...` / `builder app delete` | `app_form_schema`, `app_form_get`, `app_form_apply`, `app_delete` |
|
|
32
|
+
| AppForm static validation | `qingflow --json builder app-form validate --file ...` | Performed inside `app_form_apply`; no separate tool |
|
|
33
|
+
| Record and task work | `qingflow --json record ...` / `task ...` | Qingflow MCP record and task tools |
|
|
34
|
+
| Package, view, portal, chart, workflow | `qingflow --json builder ...` | Qingflow MCP configuration tools |
|
|
35
|
+
|
|
36
|
+
The operation names and payload schemas are defined by the public surface. Use the current Schema or tool input schema as the source of truth, not a legacy command name or backend payload.
|
|
37
|
+
|
|
38
|
+
## Package Boundaries
|
|
39
|
+
|
|
40
|
+
- `@qingflow-tech/qingflow-cli` packages CLI execution guidance and CLI-supported workflows.
|
|
41
|
+
- `@qingflow-tech/qingflow-mcp` packages every MCP Skill and exposes one unified MCP service. Record operations and system configuration are task routes in this service, not package or server choices.
|
|
42
|
+
|
|
43
|
+
Each package includes this common Skill. The CLI package installs its CLI guidance; the MCP package installs every MCP domain Skill. The source of every packaged Skill is `qingflow-support/mcp-server/skills/`.
|
|
44
|
+
|
|
45
|
+
## Route Next
|
|
46
|
+
|
|
47
|
+
Use the installed package's relevant domain Skill. In the unified MCP package, select the Skill by the requested work, not by an assumed user or builder server role. Do not link to or invoke a domain Skill that the current package did not install.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"""Entry point for running qingflow_mcp as a module.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
entrypoints can still start the builder server explicitly.
|
|
3
|
+
Start the unified Qingflow MCP surface.
|
|
5
4
|
"""
|
|
6
|
-
from qingflow_mcp.
|
|
5
|
+
from qingflow_mcp.server import main
|
|
7
6
|
|
|
8
7
|
if __name__ == "__main__":
|
|
9
8
|
main()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from .builder_facade.app_form_schema import AppFormContractError
|
|
7
|
+
from .json_types import JSONObject
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
TYPE_ALIASES = {
|
|
11
|
+
"multiline": "long_text",
|
|
12
|
+
"textarea": "long_text",
|
|
13
|
+
"radio": "single_choice",
|
|
14
|
+
"boolean": "single_choice",
|
|
15
|
+
"select": "single_select",
|
|
16
|
+
"dropdown": "single_select",
|
|
17
|
+
"checkbox": "multi_select",
|
|
18
|
+
"multi_choice": "multi_select",
|
|
19
|
+
"url": "link",
|
|
20
|
+
"hyperlink": "link",
|
|
21
|
+
"reference": "relation",
|
|
22
|
+
"quote": "relation",
|
|
23
|
+
}
|
|
24
|
+
FIELD_CONFIG_ALIASES = {
|
|
25
|
+
"options": "options",
|
|
26
|
+
"department_scope": "departmentScope",
|
|
27
|
+
"target_app_key": "targetAppKey",
|
|
28
|
+
"relation_mode": "relationMode",
|
|
29
|
+
"display_field": "displayField",
|
|
30
|
+
"visible_fields": "visibleFields",
|
|
31
|
+
"q_linker_binding": "qLinkerBinding",
|
|
32
|
+
"code_block_binding": "codeBlockBinding",
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def normalize_app_form_declaration(payload: JSONObject) -> tuple[JSONObject, list[JSONObject]]:
|
|
37
|
+
"""Normalize supported v1alpha1 compatibility aliases before Schema validation."""
|
|
38
|
+
result = deepcopy(payload)
|
|
39
|
+
warnings: list[JSONObject] = []
|
|
40
|
+
|
|
41
|
+
def visit(field: JSONObject, path: str) -> None:
|
|
42
|
+
raw_type = str(field.get("questionType") or field.get("type") or "").strip()
|
|
43
|
+
canonical_type = TYPE_ALIASES.get(raw_type, raw_type)
|
|
44
|
+
if canonical_type:
|
|
45
|
+
field["questionType"] = canonical_type
|
|
46
|
+
if "type" in field:
|
|
47
|
+
if "questionType" in field and str(field.get("type") or "").strip() != raw_type:
|
|
48
|
+
raise AppFormContractError("INVALID_SPEC", "conflicting aliases: type and questionType", path=path)
|
|
49
|
+
field.pop("type", None)
|
|
50
|
+
if canonical_type != raw_type and raw_type == "boolean":
|
|
51
|
+
warnings.append({"code": "LEGACY_BOOLEAN_NORMALIZED", "path": f"{path}/type"})
|
|
52
|
+
|
|
53
|
+
for old, new in (
|
|
54
|
+
("required", "beingRequired"),
|
|
55
|
+
("description", "questionDescription"),
|
|
56
|
+
("default_type", "defaultType"),
|
|
57
|
+
("default_value", "defaultValue"),
|
|
58
|
+
("question_description", "questionDescription"),
|
|
59
|
+
("question_type", "questionType"),
|
|
60
|
+
("being_required", "beingRequired"),
|
|
61
|
+
):
|
|
62
|
+
if old not in field:
|
|
63
|
+
continue
|
|
64
|
+
if new in field:
|
|
65
|
+
raise AppFormContractError("INVALID_SPEC", f"conflicting aliases: {old} and {new}", path=path)
|
|
66
|
+
field[new] = field.pop(old)
|
|
67
|
+
|
|
68
|
+
config = field.get("config")
|
|
69
|
+
if config is None:
|
|
70
|
+
config = {}
|
|
71
|
+
if not isinstance(config, dict):
|
|
72
|
+
return
|
|
73
|
+
for old, new in FIELD_CONFIG_ALIASES.items():
|
|
74
|
+
if old not in field:
|
|
75
|
+
continue
|
|
76
|
+
if new in config:
|
|
77
|
+
raise AppFormContractError("INVALID_SPEC", f"conflicting aliases: {old} and config.{new}", path=path)
|
|
78
|
+
config[new] = field.pop(old)
|
|
79
|
+
if raw_type == "boolean" and "options" not in config:
|
|
80
|
+
config["options"] = ["是", "否"]
|
|
81
|
+
if config:
|
|
82
|
+
field["config"] = config
|
|
83
|
+
|
|
84
|
+
if "fields" in field:
|
|
85
|
+
if "subfields" in field:
|
|
86
|
+
raise AppFormContractError("INVALID_SPEC", "conflicting aliases: fields and subfields", path=path)
|
|
87
|
+
field["subfields"] = field.pop("fields")
|
|
88
|
+
children = field.get("subfields")
|
|
89
|
+
for index, child in enumerate(children if isinstance(children, list) else []):
|
|
90
|
+
if isinstance(child, dict):
|
|
91
|
+
visit(child, f"{path}/subfields/{index}")
|
|
92
|
+
|
|
93
|
+
spec = result.get("spec")
|
|
94
|
+
for block_index, block in enumerate(spec.get("body") or [] if isinstance(spec, dict) else []):
|
|
95
|
+
if not isinstance(block, dict):
|
|
96
|
+
continue
|
|
97
|
+
rows = [block] if block.get("kind") == "row" else block.get("rows") or []
|
|
98
|
+
for row_index, row in enumerate(rows):
|
|
99
|
+
if not isinstance(row, dict):
|
|
100
|
+
continue
|
|
101
|
+
for field_index, field in enumerate(row.get("fields") or []):
|
|
102
|
+
if isinstance(field, dict):
|
|
103
|
+
visit(field, f"/spec/body/{block_index}/rows/{row_index}/fields/{field_index}")
|
|
104
|
+
return result, warnings
|