@qingflow-tech/qingflow-cli 1.1.43-beta.1 → 1.1.43-beta.3
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 +12 -5
- package/entry_point.py +1 -1
- package/npm/bin/qingflow.mjs +1 -2
- package/npm/lib/runtime.mjs +3 -7
- package/package.json +1 -2
- package/pyproject.toml +1 -3
- package/skills/qingflow-app-form/SKILL.md +63 -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 +98 -101
- 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 +6 -1
- package/src/qingflow_mcp/builder_facade/app_form.py +547 -18
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/complete.json +1321 -178
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/address.json +268 -7
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/amount.json +115 -10
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/attachment.json +304 -7
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/code_block.json +23 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/data_relation.json +23 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/date.json +23 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/datetime.json +23 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/department.json +145 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/email.json +69 -10
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/link.json +69 -10
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/long_text.json +69 -10
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/member.json +360 -7
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/multi_select.json +71 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/number.json +115 -10
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/phone.json +78 -10
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/q_linker.json +23 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/relation.json +249 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_choice.json +71 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_select.json +71 -4
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/subtable.json +1041 -20
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/text.json +69 -10
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/summary.json +23 -0
- package/src/qingflow_mcp/response_trim.py +41 -1
- package/src/qingflow_mcp/server.py +24 -3
- package/src/qingflow_mcp/server_app_builder.py +1 -1
- 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,21 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$defs": {
|
|
3
|
-
"EmptyConfig": {
|
|
4
|
-
"additionalProperties": false,
|
|
5
|
-
"description": "该字段类型没有特殊配置。",
|
|
6
|
-
"type": "object"
|
|
7
|
-
},
|
|
8
3
|
"FieldCommon": {
|
|
9
4
|
"description": "顶层业务字段的公共属性;字段类型由 TopField 的判别分支定义。",
|
|
10
5
|
"properties": {
|
|
11
|
-
"dataCover": {
|
|
12
|
-
"description": "是否作为数据封面;仅顶层附件字段可设为 true。",
|
|
13
|
-
"type": "boolean"
|
|
14
|
-
},
|
|
15
6
|
"dataTitle": {
|
|
16
7
|
"description": "是否作为数据标题;整个 body 最多且必须按规则存在一个。",
|
|
17
8
|
"type": "boolean"
|
|
18
9
|
},
|
|
10
|
+
"defaultType": {
|
|
11
|
+
"default": 1,
|
|
12
|
+
"description": "默认值类型;1 表示静态值,2 表示关联/绑定值,3 表示公式值。",
|
|
13
|
+
"enum": [
|
|
14
|
+
1,
|
|
15
|
+
2,
|
|
16
|
+
3
|
|
17
|
+
],
|
|
18
|
+
"type": "integer"
|
|
19
|
+
},
|
|
20
|
+
"defaultValue": {
|
|
21
|
+
"$ref": "#/$defs/ScalarDefaultValue",
|
|
22
|
+
"description": "普通字段的标量默认值;表格、地址、附件、引用等结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
|
|
23
|
+
},
|
|
19
24
|
"description": {
|
|
20
25
|
"description": "字段说明;null 或空字符串表示清空。",
|
|
21
26
|
"type": [
|
|
@@ -48,6 +53,60 @@
|
|
|
48
53
|
"name"
|
|
49
54
|
],
|
|
50
55
|
"type": "object"
|
|
56
|
+
},
|
|
57
|
+
"ScalarDefaultValue": {
|
|
58
|
+
"description": "不包含对象或数组的普通字段默认值。",
|
|
59
|
+
"type": [
|
|
60
|
+
"null",
|
|
61
|
+
"boolean",
|
|
62
|
+
"number",
|
|
63
|
+
"string"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"TextConfig": {
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"description": "文字类字段的长度限制;省略表示保留当前值。",
|
|
69
|
+
"properties": {
|
|
70
|
+
"canScan": {
|
|
71
|
+
"description": "是否允许扫码输入。",
|
|
72
|
+
"type": [
|
|
73
|
+
"boolean",
|
|
74
|
+
"null"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
"maxWordCount": {
|
|
78
|
+
"description": "最多字数;null 表示清除限制。",
|
|
79
|
+
"minimum": 0,
|
|
80
|
+
"type": [
|
|
81
|
+
"integer",
|
|
82
|
+
"null"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"minWordCount": {
|
|
86
|
+
"description": "最少字数;null 表示清除限制。",
|
|
87
|
+
"minimum": 0,
|
|
88
|
+
"type": [
|
|
89
|
+
"integer",
|
|
90
|
+
"null"
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
"noRepeat": {
|
|
94
|
+
"description": "是否禁止重复值。",
|
|
95
|
+
"type": [
|
|
96
|
+
"boolean",
|
|
97
|
+
"null"
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"scanType": {
|
|
101
|
+
"description": "扫码类型 ID。",
|
|
102
|
+
"minimum": 0,
|
|
103
|
+
"type": [
|
|
104
|
+
"integer",
|
|
105
|
+
"null"
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"type": "object"
|
|
51
110
|
}
|
|
52
111
|
},
|
|
53
112
|
"$id": "https://builder.qingflow.com/schemas/app-form-apply/v1alpha1/fields/text.json",
|
|
@@ -59,7 +118,7 @@
|
|
|
59
118
|
{
|
|
60
119
|
"properties": {
|
|
61
120
|
"config": {
|
|
62
|
-
"$ref": "#/$defs/
|
|
121
|
+
"$ref": "#/$defs/TextConfig"
|
|
63
122
|
},
|
|
64
123
|
"type": {
|
|
65
124
|
"const": "text"
|
|
@@ -170,6 +170,20 @@
|
|
|
170
170
|
"dataTitle": {
|
|
171
171
|
"type": "boolean"
|
|
172
172
|
},
|
|
173
|
+
"defaultType": {
|
|
174
|
+
"default": 1,
|
|
175
|
+
"description": "默认值类型;1 表示静态值,2 表示关联/绑定值,3 表示公式值。",
|
|
176
|
+
"enum": [
|
|
177
|
+
1,
|
|
178
|
+
2,
|
|
179
|
+
3
|
|
180
|
+
],
|
|
181
|
+
"type": "integer"
|
|
182
|
+
},
|
|
183
|
+
"defaultValue": {
|
|
184
|
+
"$ref": "#/$defs/ScalarDefaultValue",
|
|
185
|
+
"description": "普通字段的标量默认值;结构化默认值必须放在具体字段 config.defaultValues。显式 null 表示清除默认值。"
|
|
186
|
+
},
|
|
173
187
|
"description": {
|
|
174
188
|
"type": [
|
|
175
189
|
"string",
|
|
@@ -252,6 +266,15 @@
|
|
|
252
266
|
],
|
|
253
267
|
"type": "object"
|
|
254
268
|
},
|
|
269
|
+
"ScalarDefaultValue": {
|
|
270
|
+
"description": "不包含对象或数组的普通字段默认值。",
|
|
271
|
+
"type": [
|
|
272
|
+
"null",
|
|
273
|
+
"boolean",
|
|
274
|
+
"number",
|
|
275
|
+
"string"
|
|
276
|
+
]
|
|
277
|
+
},
|
|
255
278
|
"SectionBlock": {
|
|
256
279
|
"additionalProperties": false,
|
|
257
280
|
"description": "段落布局容器;不是业务字段,必须独占一个根级块。",
|
|
@@ -55,6 +55,8 @@ SUCCESS_POLICY_BY_TOOL: dict[str, TransformFn] = {}
|
|
|
55
55
|
def trim_public_response(tool_name: str | None, payload: dict[str, Any]) -> dict[str, Any]:
|
|
56
56
|
if not isinstance(payload, dict):
|
|
57
57
|
return payload
|
|
58
|
+
if tool_name == "builder:app_form_apply" and str(payload.get("status") or "").lower() == "partial_success":
|
|
59
|
+
return trim_success_response(tool_name, payload)
|
|
58
60
|
if _looks_like_failure_payload(payload):
|
|
59
61
|
status = str(payload.get("status") or "").lower()
|
|
60
62
|
if _is_executed_nonfatal_payload(payload) or (
|
|
@@ -1086,6 +1088,44 @@ def _trim_builder_list_like(payload: JSONObject) -> None:
|
|
|
1086
1088
|
_trim_builder_envelope(payload)
|
|
1087
1089
|
|
|
1088
1090
|
|
|
1091
|
+
def _trim_app_form_apply(payload: JSONObject) -> None:
|
|
1092
|
+
details = payload.get("details")
|
|
1093
|
+
details_diff = deepcopy(details.get("diff")) if isinstance(details, dict) and isinstance(details.get("diff"), dict) else None
|
|
1094
|
+
if isinstance(details, dict):
|
|
1095
|
+
_drop_deep_keys(details, {"transportError"})
|
|
1096
|
+
_trim_builder_envelope(payload)
|
|
1097
|
+
_trim_form_diff(payload)
|
|
1098
|
+
if details_diff is not None:
|
|
1099
|
+
payload.setdefault("details", {})["diff"] = _summarize_form_diff(details_diff)
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
def _trim_form_diff(payload: JSONObject) -> None:
|
|
1103
|
+
diff = payload.get("diff")
|
|
1104
|
+
if isinstance(diff, dict):
|
|
1105
|
+
payload["diff"] = _summarize_form_diff(diff)
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
def _summarize_form_diff(diff: dict[str, Any]) -> dict[str, Any]:
|
|
1109
|
+
summary: dict[str, Any] = {}
|
|
1110
|
+
for key in ("added", "updated", "removed"):
|
|
1111
|
+
items = diff.get(key)
|
|
1112
|
+
if not isinstance(items, list):
|
|
1113
|
+
continue
|
|
1114
|
+
names = []
|
|
1115
|
+
for item in items:
|
|
1116
|
+
if isinstance(item, str):
|
|
1117
|
+
names.append(item)
|
|
1118
|
+
elif isinstance(item, dict):
|
|
1119
|
+
name = item.get("name") or item.get("queTitle")
|
|
1120
|
+
if name:
|
|
1121
|
+
names.append(name)
|
|
1122
|
+
summary[key] = names
|
|
1123
|
+
for key in ("layoutChanged", "configChanged"):
|
|
1124
|
+
if key in diff:
|
|
1125
|
+
summary[key] = bool(diff[key])
|
|
1126
|
+
return summary
|
|
1127
|
+
|
|
1128
|
+
|
|
1089
1129
|
def _register_policy(domains: tuple[str, ...], names: tuple[str, ...], transform: TransformFn) -> None:
|
|
1090
1130
|
for domain in domains:
|
|
1091
1131
|
for name in names:
|
|
@@ -1192,7 +1232,6 @@ _register_policy(
|
|
|
1192
1232
|
"app_resolve",
|
|
1193
1233
|
"app_form_schema",
|
|
1194
1234
|
"app_form_get",
|
|
1195
|
-
"app_form_apply",
|
|
1196
1235
|
"app_delete",
|
|
1197
1236
|
"button_style_catalog_get",
|
|
1198
1237
|
"app_custom_buttons_apply",
|
|
@@ -1218,3 +1257,4 @@ _register_policy(
|
|
|
1218
1257
|
),
|
|
1219
1258
|
_trim_builder_list_like,
|
|
1220
1259
|
)
|
|
1260
|
+
_register_policy((BUILDER_DOMAIN,), ("app_form_apply",), _trim_app_form_apply)
|
|
@@ -26,12 +26,32 @@ from .tools.workflow_tools import WorkflowTools
|
|
|
26
26
|
from .tools.workspace_tools import WorkspaceTools
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
def _register_missing_builder_tools(server: FastMCP) -> None:
|
|
30
|
+
"""Add current high-level builder tools to the unified MCP without duplicate names."""
|
|
31
|
+
from .server_app_builder import build_builder_server
|
|
32
|
+
|
|
33
|
+
builder_server = build_builder_server()
|
|
34
|
+
registered = server._tool_manager._tools
|
|
35
|
+
for tool in builder_server._tool_manager._tools.values():
|
|
36
|
+
if tool.name in registered:
|
|
37
|
+
continue
|
|
38
|
+
server.add_tool(
|
|
39
|
+
tool.fn,
|
|
40
|
+
name=tool.name,
|
|
41
|
+
title=tool.title,
|
|
42
|
+
description=tool.description,
|
|
43
|
+
annotations=tool.annotations,
|
|
44
|
+
icons=tool.icons,
|
|
45
|
+
meta=tool.meta,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
29
49
|
def build_server() -> FastMCP:
|
|
30
50
|
today = date.today()
|
|
31
51
|
current_year = today.year
|
|
32
52
|
server = FastMCP(
|
|
33
53
|
"Qingflow MCP",
|
|
34
|
-
instructions=f"""Use this server for Qingflow operational workflows. Current date: `{today.isoformat()}`.
|
|
54
|
+
instructions=f"""Use this unified server for Qingflow operational and builder workflows. Current date: `{today.isoformat()}`.
|
|
35
55
|
|
|
36
56
|
## Authentication
|
|
37
57
|
|
|
@@ -203,9 +223,9 @@ Normalize relative dates before building DSL.
|
|
|
203
223
|
|
|
204
224
|
Default to `prod` unless the user explicitly specifies `test`.
|
|
205
225
|
|
|
206
|
-
##
|
|
226
|
+
## Builder Path
|
|
207
227
|
|
|
208
|
-
|
|
228
|
+
Use the public builder tools for package, AppForm, workflow, view, chart, portal, and application configuration work. Pin the AppForm Schema version, preserve complete form declarations and existing IDs from draft reads, and use `app_form_apply` for reconciliation. Do not fall back to legacy raw builder write routes.
|
|
209
229
|
|
|
210
230
|
## Feedback Path
|
|
211
231
|
|
|
@@ -235,6 +255,7 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
235
255
|
WorkflowTools(sessions, backend).register(server)
|
|
236
256
|
ViewTools(sessions, backend).register(server)
|
|
237
257
|
SolutionTools(sessions, backend).register(server)
|
|
258
|
+
_register_missing_builder_tools(server)
|
|
238
259
|
return server
|
|
239
260
|
|
|
240
261
|
|
|
@@ -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,
|
|
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. "
|
|
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. "
|
|
@@ -11895,7 +11895,7 @@ class RecordTools(ToolBase):
|
|
|
11895
11895
|
raise RecordInputError(
|
|
11896
11896
|
message=f"field '{field.que_title}' uses unsupported nested subtable writes",
|
|
11897
11897
|
error_code="UNSUPPORTED_WRITE_FORMAT",
|
|
11898
|
-
fix_hint="Nested subtable writes are not supported
|
|
11898
|
+
fix_hint="Nested subtable writes are not supported by the public record tools.",
|
|
11899
11899
|
details={"location": location, "field": _field_ref_payload(field), "expected_format": _write_format_for_field(field), "received_value": item},
|
|
11900
11900
|
)
|
|
11901
11901
|
self._raise_if_verify_unsupported_write_field(field, item, location=location)
|
|
@@ -11960,7 +11960,7 @@ class RecordTools(ToolBase):
|
|
|
11960
11960
|
raise RecordInputError(
|
|
11961
11961
|
message=f"field '{field.que_title}' uses unsupported nested subtable writes",
|
|
11962
11962
|
error_code="UNSUPPORTED_WRITE_FORMAT",
|
|
11963
|
-
fix_hint="Nested subtable writes are not supported
|
|
11963
|
+
fix_hint="Nested subtable writes are not supported by the public record tools.",
|
|
11964
11964
|
details={"location": location, "field": _field_ref_payload(field), "expected_format": _write_format_for_field(field), "received_value": raw_value},
|
|
11965
11965
|
)
|
|
11966
11966
|
self._raise_if_verify_unsupported_write_field(field, raw_value, location=location)
|
|
@@ -21150,7 +21150,7 @@ def _subtable_cell_ref_payload(
|
|
|
21150
21150
|
|
|
21151
21151
|
def _unsupported_write_reason(que_type: int | None) -> str:
|
|
21152
21152
|
if que_type == 14:
|
|
21153
|
-
return "time range fields require a backend-specific native payload shape that
|
|
21153
|
+
return "time range fields require a backend-specific native payload shape that public record tools do not build yet"
|
|
21154
21154
|
if que_type == 34:
|
|
21155
21155
|
return "image recognition fields are runtime AI fields and direct writes are not reliably persisted"
|
|
21156
21156
|
if que_type == 35:
|
|
@@ -57,11 +57,9 @@ def _find_package_root() -> Path | None:
|
|
|
57
57
|
if version and name in {
|
|
58
58
|
"qingflow-mcp-workspace",
|
|
59
59
|
"@qingflow-tech/qingflow-cli",
|
|
60
|
-
"@qingflow-tech/qingflow-
|
|
61
|
-
"@qingflow-tech/qingflow-app-builder-mcp",
|
|
60
|
+
"@qingflow-tech/qingflow-mcp",
|
|
62
61
|
"@josephyan/qingflow-cli",
|
|
63
|
-
"@josephyan/qingflow-
|
|
64
|
-
"@josephyan/qingflow-app-builder-mcp",
|
|
62
|
+
"@josephyan/qingflow-mcp",
|
|
65
63
|
}:
|
|
66
64
|
return parent
|
|
67
65
|
return None
|