@qingflow-tech/qingflow-cli 1.1.43-beta.3 → 1.1.43-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +3 -3
  2. package/package.json +1 -1
  3. package/pyproject.toml +1 -1
  4. package/skills/qingflow-app-form/SKILL.md +7 -5
  5. package/skills/qingflow-cli/reference/builder/30-schema-fields.md +14 -13
  6. package/src/qingflow_mcp/app_form_compat.py +11 -27
  7. package/src/qingflow_mcp/app_form_validator.py +201 -35
  8. package/src/qingflow_mcp/builder_facade/app_form.py +762 -148
  9. package/src/qingflow_mcp/builder_facade/app_form_schema.py +114 -3
  10. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/complete.json +310 -245
  11. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/address.json +82 -27
  12. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/amount.json +85 -32
  13. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/attachment.json +82 -30
  14. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/code_block.json +113 -37
  15. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/data_relation.json +87 -64
  16. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/date.json +82 -27
  17. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/datetime.json +82 -27
  18. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/department.json +83 -28
  19. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/email.json +82 -27
  20. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/link.json +82 -27
  21. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/long_text.json +82 -27
  22. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/member.json +83 -28
  23. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/multi_select.json +82 -27
  24. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/number.json +85 -32
  25. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/phone.json +82 -27
  26. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/q_linker.json +95 -40
  27. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/relation.json +100 -28
  28. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_choice.json +82 -27
  29. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_select.json +82 -27
  30. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/subtable.json +212 -117
  31. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/text.json +82 -27
  32. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/summary.json +143 -161
  33. package/src/qingflow_mcp/builder_facade/service.py +3 -2
  34. package/src/qingflow_mcp/response_trim.py +2 -0
  35. package/src/qingflow_mcp/server_app_builder.py +2 -2
@@ -1,15 +1,71 @@
1
1
  {
2
2
  "$defs": {
3
3
  "FieldCommon": {
4
+ "allOf": [
5
+ {
6
+ "if": {
7
+ "properties": {
8
+ "defaultType": {
9
+ "const": 2
10
+ }
11
+ },
12
+ "required": [
13
+ "defaultType"
14
+ ]
15
+ },
16
+ "then": {
17
+ "properties": {
18
+ "defaultValue": {
19
+ "type": "null"
20
+ }
21
+ }
22
+ }
23
+ },
24
+ {
25
+ "if": {
26
+ "properties": {
27
+ "defaultType": {
28
+ "const": 3
29
+ }
30
+ },
31
+ "required": [
32
+ "defaultType"
33
+ ]
34
+ },
35
+ "then": {
36
+ "properties": {
37
+ "defaultValue": {
38
+ "minLength": 1,
39
+ "type": [
40
+ "string",
41
+ "null"
42
+ ]
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ],
48
+ "anyOf": [
49
+ {
50
+ "required": [
51
+ "queId"
52
+ ]
53
+ },
54
+ {
55
+ "required": [
56
+ "name"
57
+ ]
58
+ }
59
+ ],
4
60
  "description": "顶层业务字段的公共属性;字段类型由 TopField 的判别分支定义。",
5
61
  "properties": {
6
- "dataTitle": {
7
- "description": "是否作为数据标题;整个 body 最多且必须按规则存在一个。",
62
+ "beingRequired": {
63
+ "description": "该字段是否必填;缺失时保留已有字段当前值。",
8
64
  "type": "boolean"
9
65
  },
10
66
  "defaultType": {
11
67
  "default": 1,
12
- "description": "默认值类型;1 表示静态值,2 表示关联/绑定值,3 表示公式值。",
68
+ "description": "默认值类型,与 defaultValue 联动;1 表示静态值,2 表示关联/绑定值且 defaultValue 只能省略或为 null,3 表示公式值且提供 defaultValue 时必须为非空公式文本。省略 defaultType 但提供 defaultValue 时按 1 处理。",
13
69
  "enum": [
14
70
  1,
15
71
  2,
@@ -19,47 +75,46 @@
19
75
  },
20
76
  "defaultValue": {
21
77
  "$ref": "#/$defs/ScalarDefaultValue",
22
- "description": "普通字段的标量默认值;表格、地址、附件、引用等结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
23
- },
24
- "description": {
25
- "description": "字段说明;null 或空字符串表示清空。",
26
- "type": [
27
- "string",
28
- "null"
29
- ]
78
+ "description": "普通字段的默认值;后端 queDefaultValue 为字符串,因此数字等字面量也必须以字符串传入。defaultType 为 1 时表示静态文本,为 3 时表示公式文本,为 2 时不携带字面量默认值。表格、地址、附件、引用等结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
30
79
  },
31
80
  "name": {
32
- "description": "字段展示名称;同一父级内唯一,不单独作为字段身份。",
81
+ "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略;同一父级内唯一。",
33
82
  "minLength": 1,
34
83
  "type": "string"
35
84
  },
36
85
  "queId": {
37
- "description": "已有字段的后端 ID;get 返回,新增字段省略。",
86
+ "description": "已有字段的后端 ID;更新时用于精确定位并复用,新增字段通常省略。",
38
87
  "minimum": 1,
39
88
  "type": "integer"
40
89
  },
41
- "required": {
42
- "description": "是否必填;缺失时保留已有字段当前值。",
43
- "type": "boolean"
90
+ "questionDescription": {
91
+ "description": "字段说明;null 或空字符串表示清空。",
92
+ "type": [
93
+ "string",
94
+ "null"
95
+ ]
96
+ },
97
+ "questionType": {
98
+ "description": "字段类型;具体可用值由当前字段详情 Schema 的判别分支约束。",
99
+ "type": "string"
44
100
  },
45
101
  "width": {
46
- "description": "字段在所在行的宽度百分比;同一行要么全部提供且合计 100,要么全部省略。",
47
- "maximum": 100,
48
- "minimum": 1,
102
+ "description": "字段在所在行的宽度百分比;只能选择 25、50、75 或 100。",
103
+ "enum": [
104
+ 25,
105
+ 50,
106
+ 75,
107
+ 100
108
+ ],
49
109
  "type": "integer"
50
110
  }
51
111
  },
52
- "required": [
53
- "name"
54
- ],
55
112
  "type": "object"
56
113
  },
57
114
  "ScalarDefaultValue": {
58
- "description": "不包含对象或数组的普通字段默认值。",
115
+ "description": "后端 queDefaultValue 支持的普通字段默认值;非空值必须是字符串,显式 null 表示清除默认值。数字和布尔值应先转换为字符串,对象和数组必须使用字段专用默认值配置。需要配置结构化默认值时,通过 AppForm Schema 查询能力传入当前 schema_version,并将字段的 questionType 作为 field_type 获取该字段类型的详细 Schema,再按其中的字段专用 config 定义填写。",
59
116
  "type": [
60
117
  "null",
61
- "boolean",
62
- "number",
63
118
  "string"
64
119
  ]
65
120
  },
@@ -120,12 +175,12 @@
120
175
  "config": {
121
176
  "$ref": "#/$defs/TextConfig"
122
177
  },
123
- "type": {
178
+ "questionType": {
124
179
  "const": "text"
125
180
  }
126
181
  },
127
182
  "required": [
128
- "type"
183
+ "questionType"
129
184
  ]
130
185
  }
131
186
  ],
@@ -2,8 +2,15 @@
2
2
  "$defs": {
3
3
  "AppFormSpec": {
4
4
  "additionalProperties": false,
5
- "description": "表单基础配置与字段布局目标态;除 body 外,缺失属性表示保留当前值。",
5
+ "description": "表单基础配置与字段布局目标态;除 body 外,缺失属性表示保留当前值。应用内所有 q_linker 和 code_block 字段的 outputs[].targetField 必须全局唯一,同一实际字段只能被一个输出映射写入。多个生产方需要回写时,请选择不同目标字段或合并为一个生产方。",
6
6
  "properties": {
7
+ "appDescription": {
8
+ "description": "应用描述;null 或空字符串表示清空。",
9
+ "type": [
10
+ "string",
11
+ "null"
12
+ ]
13
+ },
7
14
  "appName": {
8
15
  "description": "应用名称;缺失时保留当前名称。",
9
16
  "minLength": 1,
@@ -18,46 +25,33 @@
18
25
  },
19
26
  "body": {
20
27
  "$ref": "#/$defs/Body",
21
- "description": "业务字段与布局的完整目标态;缺失字段或段落表示删除。"
28
+ "description": "业务字段与布局的完整目标态;缺失字段或段落表示删除。应用内所有 Q-Linker 和代码块的 outputs[].targetField 不得重复选择同一实际字段。"
22
29
  },
23
- "color": {
24
- "description": "新应用图标颜色;仅创建分支允许,必须来自 workspace icon color catalog。",
25
- "minLength": 1,
26
- "type": "string"
27
- },
28
- "description": {
29
- "description": "应用描述;null 或空字符串表示清空。",
30
- "type": [
31
- "string",
32
- "null"
30
+ "dataCoverField": {
31
+ "description": "数据封面字段选择器;指定每条数据的封面附件来源。仅允许选择顶层 attachment 字段;null 表示清除数据封面。",
32
+ "oneOf": [
33
+ {
34
+ "type": "null"
35
+ },
36
+ {
37
+ "$ref": "#/$defs/FieldSelector"
38
+ }
33
39
  ]
34
40
  },
35
- "icon": {
36
- "description": "新应用图标;仅创建分支允许,必须来自 workspace icon catalog 且不得为 template。",
37
- "minLength": 1,
38
- "type": "string"
39
- },
40
- "serialNumber": {
41
- "$ref": "#/$defs/SerialNumber",
42
- "description": "应用编号规则;支持默认编号或自定义组件编号。"
43
- },
44
- "style": {
45
- "description": "应用样式;对象内缺失属性保留当前值,null 表示清除全部自定义样式。",
41
+ "dataTitleField": {
42
+ "description": "数据标题字段选择器;指定每条数据的主显示标题来源。创建非空 body 时必填,更新时省略表示保留当前选择;显式提供时必须唯一定位一个顶层字段,仅 body 为空时允许 null。",
46
43
  "oneOf": [
47
44
  {
48
- "$ref": "#/$defs/Style"
45
+ "type": "null"
49
46
  },
50
47
  {
51
- "type": "null"
48
+ "$ref": "#/$defs/FieldSelector"
52
49
  }
53
50
  ]
54
51
  },
55
- "theme": {
56
- "description": "应用主题 ID;null 表示清除自定义主题。",
57
- "type": [
58
- "integer",
59
- "null"
60
- ]
52
+ "serialNumber": {
53
+ "$ref": "#/$defs/SerialNumber",
54
+ "description": "应用编号规则;支持默认编号或自定义组件编号。"
61
55
  }
62
56
  },
63
57
  "required": [
@@ -142,7 +136,7 @@
142
136
  ]
143
137
  }
144
138
  ],
145
- "description": "跨字段引用选择器;至少提供 queId 或 name,两者同时提供时必须指向同一字段。",
139
+ "description": "字段选择器;用于定位应用的数据标题、数据封面、自定义编号取值来源或其他配置引用的字段。至少提供 queId 或 name,两者同时提供时必须指向同一字段。",
146
140
  "properties": {
147
141
  "name": {
148
142
  "description": "字段名称;仅在当前作用域内唯一时可用于解析。",
@@ -159,20 +153,74 @@
159
153
  },
160
154
  "FieldSummary": {
161
155
  "additionalProperties": false,
162
- "properties": {
163
- "config": {
164
- "description": "调用对应 field_type 的详细 Schema 后生成。",
165
- "type": "object"
156
+ "allOf": [
157
+ {
158
+ "if": {
159
+ "properties": {
160
+ "defaultType": {
161
+ "const": 2
162
+ }
163
+ },
164
+ "required": [
165
+ "defaultType"
166
+ ]
167
+ },
168
+ "then": {
169
+ "properties": {
170
+ "defaultValue": {
171
+ "type": "null"
172
+ }
173
+ }
174
+ }
166
175
  },
167
- "dataCover": {
168
- "type": "boolean"
176
+ {
177
+ "if": {
178
+ "properties": {
179
+ "defaultType": {
180
+ "const": 3
181
+ }
182
+ },
183
+ "required": [
184
+ "defaultType"
185
+ ]
186
+ },
187
+ "then": {
188
+ "properties": {
189
+ "defaultValue": {
190
+ "minLength": 1,
191
+ "type": [
192
+ "string",
193
+ "null"
194
+ ]
195
+ }
196
+ }
197
+ }
198
+ }
199
+ ],
200
+ "anyOf": [
201
+ {
202
+ "required": [
203
+ "queId"
204
+ ]
169
205
  },
170
- "dataTitle": {
206
+ {
207
+ "required": [
208
+ "name"
209
+ ]
210
+ }
211
+ ],
212
+ "properties": {
213
+ "beingRequired": {
214
+ "description": "该字段是否必填;缺失时更新保留当前值。",
171
215
  "type": "boolean"
172
216
  },
217
+ "config": {
218
+ "description": "调用对应 questionType 的详细 Schema 后生成;q_linker 和 code_block 的 outputs[].targetField 还必须遵守应用级全局唯一规则。",
219
+ "type": "object"
220
+ },
173
221
  "defaultType": {
174
222
  "default": 1,
175
- "description": "默认值类型;1 表示静态值,2 表示关联/绑定值,3 表示公式值。",
223
+ "description": "默认值类型,与 defaultValue 联动;1 表示静态值,2 表示关联/绑定值且 defaultValue 只能省略或为 null,3 表示公式值且提供 defaultValue 时必须为非空公式文本。省略 defaultType 但提供 defaultValue 时按 1 处理。",
176
224
  "enum": [
177
225
  1,
178
226
  2,
@@ -182,42 +230,46 @@
182
230
  },
183
231
  "defaultValue": {
184
232
  "$ref": "#/$defs/ScalarDefaultValue",
185
- "description": "普通字段的标量默认值;结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
186
- },
187
- "description": {
188
- "type": [
189
- "string",
190
- "null"
191
- ]
233
+ "description": "普通字段的默认值;后端 queDefaultValue 为字符串,因此数字等字面量也必须以字符串传入。defaultType 为 1 时表示静态文本,为 3 时表示公式文本,为 2 时不携带字面量默认值。结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
192
234
  },
193
235
  "name": {
236
+ "description": "字段展示名称;新增字段必填,已有字段可在携带 queId 时省略。",
194
237
  "minLength": 1,
195
238
  "type": "string"
196
239
  },
197
240
  "queId": {
241
+ "description": "已有字段的后端 ID;更新时用于精确定位并复用,新增字段通常省略。",
198
242
  "minimum": 1,
199
243
  "type": "integer"
200
244
  },
201
- "required": {
202
- "type": "boolean"
245
+ "questionDescription": {
246
+ "description": "字段说明;null 或空字符串表示清空。",
247
+ "type": [
248
+ "string",
249
+ "null"
250
+ ]
251
+ },
252
+ "questionType": {
253
+ "description": "字段类型;必须来自 x-qingflow-supported-field-types。",
254
+ "type": "string"
203
255
  },
204
256
  "subfields": {
205
257
  "description": "仅 subtable 使用;详情见 subtable Schema。",
206
258
  "type": "array"
207
259
  },
208
- "type": {
209
- "description": "必须来自 x-qingflow-supported-field-types。",
210
- "type": "string"
211
- },
212
260
  "width": {
213
- "maximum": 100,
214
- "minimum": 1,
261
+ "description": "字段在所在行的宽度百分比;只能选择 25、50、75 或 100。",
262
+ "enum": [
263
+ 25,
264
+ 50,
265
+ 75,
266
+ 100
267
+ ],
215
268
  "type": "integer"
216
269
  }
217
270
  },
218
271
  "required": [
219
- "name",
220
- "type"
272
+ "questionType"
221
273
  ],
222
274
  "type": "object"
223
275
  },
@@ -267,11 +319,9 @@
267
319
  "type": "object"
268
320
  },
269
321
  "ScalarDefaultValue": {
270
- "description": "不包含对象或数组的普通字段默认值。",
322
+ "description": "后端 queDefaultValue 支持的普通字段默认值;非空值必须是字符串,显式 null 表示清除默认值。数字和布尔值应先转换为字符串,对象和数组必须使用字段专用默认值配置。需要配置结构化默认值时,通过 AppForm Schema 查询能力传入当前 schema_version,并将字段的 questionType 作为 field_type 获取该字段类型的详细 Schema,再按其中的字段专用 config 定义填写。",
271
323
  "type": [
272
324
  "null",
273
- "boolean",
274
- "number",
275
325
  "string"
276
326
  ]
277
327
  },
@@ -450,7 +500,7 @@
450
500
  },
451
501
  "field": {
452
502
  "$ref": "#/$defs/FieldSelector",
453
- "description": "取值来源字段。"
503
+ "description": "自定义编号中参与拼接的取值来源字段。"
454
504
  },
455
505
  "id": {
456
506
  "minimum": 1,
@@ -521,82 +571,15 @@
521
571
  }
522
572
  ]
523
573
  },
524
- "Style": {
525
- "additionalProperties": false,
526
- "description": "表单背景和头部视觉样式;颜色使用 CSS 颜色字符串。",
527
- "properties": {
528
- "bgColor": {
529
- "description": "表单背景色;null 表示清除。",
530
- "type": [
531
- "string",
532
- "null"
533
- ]
534
- },
535
- "bgImage": {
536
- "description": "表单背景图片 URL;null 表示清除。",
537
- "type": [
538
- "string",
539
- "null"
540
- ]
541
- },
542
- "fontColor": {
543
- "description": "表单头部字体颜色;null 表示清除。",
544
- "type": [
545
- "string",
546
- "null"
547
- ]
548
- },
549
- "headerColor": {
550
- "description": "表单头部背景色;null 表示清除。",
551
- "type": [
552
- "string",
553
- "null"
554
- ]
555
- },
556
- "headerImage": {
557
- "description": "表单头图 URL;null 表示清除。",
558
- "type": [
559
- "string",
560
- "null"
561
- ]
562
- },
563
- "opacity": {
564
- "description": "背景透明度,取值 0 到 1;null 表示清除。",
565
- "maximum": 1,
566
- "minimum": 0,
567
- "type": [
568
- "number",
569
- "null"
570
- ]
571
- }
572
- },
573
- "type": "object"
574
- },
575
- "TopField": {}
574
+ "TopField": {
575
+ "$ref": "#/$defs/FieldSummary"
576
+ }
576
577
  },
577
578
  "$id": "https://builder.qingflow.com/schemas/app-form-apply/v1alpha1/summary.json",
578
579
  "$schema": "https://json-schema.org/draft/2020-12/schema",
579
580
  "additionalProperties": false,
580
581
  "oneOf": [
581
582
  {
582
- "properties": {
583
- "spec": {
584
- "not": {
585
- "anyOf": [
586
- {
587
- "required": [
588
- "icon"
589
- ]
590
- },
591
- {
592
- "required": [
593
- "color"
594
- ]
595
- }
596
- ]
597
- }
598
- }
599
- },
600
583
  "required": [
601
584
  "appKey"
602
585
  ]
@@ -610,9 +593,7 @@
610
593
  "properties": {
611
594
  "spec": {
612
595
  "required": [
613
- "appName",
614
- "icon",
615
- "color"
596
+ "appName"
616
597
  ]
617
598
  }
618
599
  },
@@ -637,7 +618,15 @@
637
618
  },
638
619
  "spec": {
639
620
  "additionalProperties": false,
621
+ "description": "应用表单目标态;应用内所有 q_linker 和 code_block 字段的 outputs[].targetField 必须全局唯一,同一实际字段只能被一个输出映射写入。多个生产方需要回写时,请选择不同目标字段或合并为一个生产方。",
640
622
  "properties": {
623
+ "appDescription": {
624
+ "description": "应用描述;null 或空字符串表示清空。",
625
+ "type": [
626
+ "string",
627
+ "null"
628
+ ]
629
+ },
641
630
  "appName": {
642
631
  "minLength": 1,
643
632
  "type": "string"
@@ -650,7 +639,7 @@
650
639
  "type": "array"
651
640
  },
652
641
  "body": {
653
- "description": "业务字段与布局完整目标态;缺失业务字段表示删除。",
642
+ "description": "业务字段与布局完整目标态;缺失业务字段表示删除。应用内所有 Q-Linker 和代码块的 outputs[].targetField 不得重复选择同一实际字段。",
654
643
  "items": {
655
644
  "oneOf": [
656
645
  {
@@ -663,38 +652,31 @@
663
652
  },
664
653
  "type": "array"
665
654
  },
666
- "color": {
667
- "description": "仅创建时使用;必须来自 workspace icon color catalog。",
668
- "minLength": 1,
669
- "type": "string"
670
- },
671
- "description": {
672
- "type": [
673
- "string",
674
- "null"
655
+ "dataCoverField": {
656
+ "description": "数据封面字段选择器;指定每条数据的封面附件来源。仅允许选择顶层 attachment 字段;null 表示清除数据封面。",
657
+ "oneOf": [
658
+ {
659
+ "type": "null"
660
+ },
661
+ {
662
+ "$ref": "#/$defs/FieldSelector"
663
+ }
675
664
  ]
676
665
  },
677
- "icon": {
678
- "description": "仅创建时使用;必须来自 workspace icon catalog 且不得为 template。",
679
- "minLength": 1,
680
- "type": "string"
666
+ "dataTitleField": {
667
+ "description": "数据标题字段选择器;指定每条数据的主显示标题来源。创建非空 body 时必填,更新时省略表示保留当前选择;显式提供时必须唯一定位一个顶层字段,仅 body 为空时允许 null。",
668
+ "oneOf": [
669
+ {
670
+ "type": "null"
671
+ },
672
+ {
673
+ "$ref": "#/$defs/FieldSelector"
674
+ }
675
+ ]
681
676
  },
682
677
  "serialNumber": {
683
678
  "description": "default 或 custom 编号配置。",
684
679
  "type": "object"
685
- },
686
- "style": {
687
- "description": "应用样式;详细属性为 bgImage/bgColor/opacity/headerImage/headerColor/fontColor。",
688
- "type": [
689
- "object",
690
- "null"
691
- ]
692
- },
693
- "theme": {
694
- "type": [
695
- "integer",
696
- "null"
697
- ]
698
680
  }
699
681
  },
700
682
  "required": [
@@ -22718,6 +22718,7 @@ def _compile_q_linker_binding_fields(
22718
22718
  "target_field_name": target_field.get("name"),
22719
22719
  "target_field_ref": target_ref,
22720
22720
  "alias": output_item.get("alias_name"),
22721
+ "alias_id": _coerce_positive_int(output_item.get("alias_id")),
22721
22722
  }
22722
22723
  )
22723
22724
 
@@ -22790,7 +22791,7 @@ def _materialize_q_linker_question_relations(
22790
22791
  "queId": source_ref,
22791
22792
  "queTitle": source_field.get("name"),
22792
22793
  "qlinkerAlias": relation.get("alias"),
22793
- "aliasId": None,
22794
+ "aliasId": _coerce_positive_int(relation.get("alias_id")),
22794
22795
  },
22795
22796
  "matchRuleType": 1,
22796
22797
  "matchRules": [],
@@ -24007,7 +24008,7 @@ def _normalize_formula_defaults_for_save(value: Any) -> None:
24007
24008
  return
24008
24009
  if not isinstance(value, dict):
24009
24010
  return
24010
- if _coerce_any_int(value.get("queDefaultType")) == DEFAULT_TYPE_FORMULA and value.get("queDefaultValue"):
24011
+ if value.get("queDefaultValue"):
24011
24012
  value["queDefaultValue"] = _encode_formula_for_backend_save(value.get("queDefaultValue"))
24012
24013
  for key in ("subQuestions", "innerQuestions"):
24013
24014
  nested = value.get(key)
@@ -85,6 +85,8 @@ def trim_success_response(tool_name: str | None, payload: dict[str, Any]) -> dic
85
85
  drop_keys = COMMON_SUCCESS_DROP_TOP - {"output_profile"}
86
86
  if tool_name in {"user:record_insert", "user:record_update", "user:record_delete"} and payload.get("ok") is False:
87
87
  drop_keys = drop_keys - {"ok"}
88
+ if tool_name == "builder:app_form_apply" and payload.get("mustReadCurrentStateBeforeRepair") is True:
89
+ drop_keys = drop_keys - {"suggested_next_call"}
88
90
  _drop_top_keys(trimmed, drop_keys)
89
91
  transformer = SUCCESS_POLICY_BY_TOOL.get(tool_name or "")
90
92
  if transformer is not None:
@@ -36,7 +36,7 @@ def build_builder_server() -> FastMCP:
36
36
  "Use builder_tool_contract when you need a machine-readable contract, aliases, allowed enums, or a minimal valid example for a public builder tool. "
37
37
  "Use solution_install when the user explicitly wants to install a packaged solution/template by solution_key, optionally copying bundled demo data. "
38
38
  "Use package_list to find visible app packages by keyword and package_get to read package detail before editing; if creating or updating an app package may be appropriate, use package_apply with explicit user intent; otherwise use app_resolve to locate app resources, "
39
- "Use workspace_icon_catalog_get before creating app packages, apps, or portals when supported icon/color candidates are needed; new workspace resources require explicit non-template icon + color, and the CLI validates choices without inferring business defaults. "
39
+ "Use workspace_icon_catalog_get before creating app packages or portals when supported icon/color candidates are needed; those resources require explicit non-template icon + color. AppForm-created apps derive a stable default icon and color from spec.appName. "
40
40
  "app_form_schema plus app_form_get for versioned form work, using being_draft=true only for editing and the published default for relation or record consumers; use app_get as the default non-form app map read, then app_get_fields/app_repair_code_blocks/app_get_layout/app_get_views/app_get_flow/app_get_charts/portal_list/portal_get/view_get/chart_get for focused compatibility or non-form reads, "
41
41
  "member_search/role_search/role_create when workflow assignees must come from the directory or role catalog, preferring roles over explicit members unless the user explicitly names members, "
42
42
  "then app_form_apply for complete app form targets, explicit app_delete for application deletion, and app_flow_apply/app_views_apply/app_associated_resources_apply/app_charts_apply/portal_apply/portal_delete for non-form patches. app_custom_buttons_apply is maintenance-only for explicit standalone button work outside normal view design. These apply/delete tools perform validation, normalization, writes, and readback verification where applicable. AppForm publishes only after a draft change or when the published form lags behind; views noop requests skip publish, app_custom_buttons_apply and app_associated_resources_apply publish after at least one write succeeds and expose no draft-only parameter, charts are immediate-live without publish and resolve targets by chart_id first then exact unique chart name, portal updates use replace semantics only when sections are supplied and edit-mode base-info-only updates may omit sections, portal delete separates DELETE execution from readback verification, portal pc layout is a 24-column grid and mobile is a 6-column grid so omit position or use layout_preset when unsure, publish=false only guarantees draft/base-info updates for tools that still expose that parameter, and flow should use publish=false whenever you only want draft/precheck behavior. "
@@ -44,7 +44,7 @@ def build_builder_server() -> FastMCP:
44
44
  "For existing object parameter replacement, prefer patch_views, patch_buttons, patch_resources, and patch_charts with set/unset; the tool reads current config and full-saves internally, while upsert_* is for creation or full target configuration and should not be used as an incomplete partial update. "
45
45
  "For builder delete/remove apply results, separate delete execution from readback verification: after DELETE is sent, resources expose delete_executed, readback_status, and safe_to_retry_delete=false. If readback_status is unavailable or still_exists, do not blindly repeat the delete; confirm later with app_get/view_get/chart_get or the relevant apply readback. Views/buttons use single-item readback; associated resources use one app-level resource-pool readback because there is no confirmed single-item GET. "
46
46
  "For builder write/apply results, separate write execution from final readback verification: status=partial_success with write_executed=true and safe_to_retry=false means the write was sent or succeeded, while final readback, publish verification, or metadata confirmation is pending or permission-restricted. Report it as written but unverified; do not repeat the same write blindly. "
47
- "For app_form_apply, pin the version from app_form_schema, preserve the complete body and existing IDs from a draft get, and use dataTitle/dataCover on canonical fields; App Builder MCP validates the declaration inside app_form_apply, while the CLI route has a separate static validate command. Exactly one top-level dataTitle is required for a non-empty body, while dataCover is optional and must be a top-level attachment field. A root appKey means update and may include packageId; no appKey means create and requires packageId plus spec.appName, spec.icon, and spec.color selected from workspace_icon_catalog_get, with template forbidden. "
47
+ "For app_form_apply, pin the version from app_form_schema, preserve the complete body and existing IDs from a draft get, and configure data display through app-level spec.dataTitleField/spec.dataCoverField selectors rather than booleans on fields; App Builder MCP validates the declaration inside app_form_apply, while the CLI route has a separate static validate command. dataTitleField must resolve to exactly one top-level field for a non-empty body, while dataCoverField is optional and must resolve to a top-level attachment field. A root appKey means update and may include packageId; no appKey means create and requires packageId plus spec.appName. AppForm does not accept spec.icon or spec.color; creation derives a stable default icon and color from spec.appName. "
48
48
  "For app_views_apply, keep fixed saved filters in filters and configure the frontend query panel separately with query_conditions; query_conditions.rows is a matrix of field names compiled to backend queryCondition queIds. New views default associated report/view display to visible with limit_type=all; existing views preserve their current associated display unless associated_resources is explicitly patched. View writes use ViewManagementAuth (beingViewManageStatus), falling back to DataManageAuth when advanced app permissions are not enabled. "
49
49
  "For ordinary business buttons, declare them on the target view with app_views_apply.views[].action_buttons; app_views_apply writes the view first, then creates/binds the button. Use app_custom_buttons_apply only when the user explicitly asks to maintain existing standalone buttons outside view design, such as custom style/icon changes, cross-view reuse, deleting button bodies, bulk binding reorder, or exact qRobot/wings config. Button body writes require EditAppAuth; view_configs placement writes require ViewManagementAuth, matching the backend viewConfig route. For addData buttons, prefer action_buttons.target_app_key + field_mappings/default_values on the view path; do not ask agents to write raw que_relation unless maintaining a legacy config. field_mappings.source_field accepts source schema fields and supported system fields: 数据ID/row_record_id/apply_id/_id means current record id (-17), 编号/record_number means visible record number (0). To fill a target relation with the current record, map {'source_field': '数据ID', 'target_field': '目标引用字段'}; default_values is only for static constants. View button bindings merge by default; standalone view_configs are only for explicit maintenance. Builder view_key arguments are raw keys from app_get.views[].view_key and must not be prefixed with custom:. "
50
50
  "For BI reports, keep report-body development separate from Qingflow in-app display: use app_charts_apply to create, update, remove, or reorder app-source QingBI chart bodies/configs with dataSourceType=qingflow; chart dimension/metric/filter/query fields must come from app_get_fields.chart_fields, not record schema or form-only fields; dataset BI reports are not created or edited by app_charts_apply yet and should be created in QingBI first, then attached with app_associated_resources_apply using report_source=dataset. "