@josephyan/qingflow-app-builder-mcp 0.2.0-beta.49 → 0.2.0-beta.50

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.
@@ -25,6 +25,7 @@ from ..builder_facade.models import (
25
25
  LayoutSectionPatch,
26
26
  PortalApplyRequest,
27
27
  PublicFieldType,
28
+ PublicRelationMode,
28
29
  PublicChartType,
29
30
  PublicViewType,
30
31
  SchemaPlanRequest,
@@ -1596,9 +1597,17 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
1596
1597
  "field.label": "field.name",
1597
1598
  "field.fields": "field.subfields",
1598
1599
  "field.type_id": "field.type",
1600
+ "field.relationMode": "field.relation_mode",
1601
+ "field.selection_mode": "field.relation_mode",
1602
+ "field.selectionMode": "field.relation_mode",
1603
+ "field.multiple": "field.relation_mode",
1604
+ "field.allow_multiple": "field.relation_mode",
1605
+ "field.optional_data_num": "field.relation_mode",
1606
+ "field.optionalDataNum": "field.relation_mode",
1599
1607
  },
1600
1608
  "allowed_values": {
1601
1609
  "field.type": [member.value for member in PublicFieldType],
1610
+ "field.relation_mode": [member.value for member in PublicRelationMode],
1602
1611
  "field_type_ids": sorted(FIELD_TYPE_ID_ALIASES.keys()),
1603
1612
  },
1604
1613
  "minimal_example": {
@@ -1610,6 +1619,22 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
1610
1619
  "update_fields": [],
1611
1620
  "remove_fields": [],
1612
1621
  },
1622
+ "relation_example": {
1623
+ "profile": "default",
1624
+ "app_key": "APP_ITERATION",
1625
+ "add_fields": [
1626
+ {
1627
+ "name": "需求反馈引用",
1628
+ "type": "relation",
1629
+ "target_app_key": "APP_FEEDBACK",
1630
+ "relation_mode": "multiple",
1631
+ "display_field": {"name": "反馈标题"},
1632
+ "visible_fields": [{"name": "反馈标题"}, {"name": "优先级判断"}],
1633
+ }
1634
+ ],
1635
+ "update_fields": [],
1636
+ "remove_fields": [],
1637
+ },
1613
1638
  },
1614
1639
  "app_schema_apply": {
1615
1640
  "allowed_keys": ["app_key", "package_tag_id", "app_name", "create_if_missing", "publish", "add_fields", "update_fields", "remove_fields"],
@@ -1620,14 +1645,23 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
1620
1645
  "field.label": "field.name",
1621
1646
  "field.fields": "field.subfields",
1622
1647
  "field.type_id": "field.type",
1648
+ "field.relationMode": "field.relation_mode",
1649
+ "field.selection_mode": "field.relation_mode",
1650
+ "field.selectionMode": "field.relation_mode",
1651
+ "field.multiple": "field.relation_mode",
1652
+ "field.allow_multiple": "field.relation_mode",
1653
+ "field.optional_data_num": "field.relation_mode",
1654
+ "field.optionalDataNum": "field.relation_mode",
1623
1655
  },
1624
1656
  "allowed_values": {
1625
1657
  "field.type": [member.value for member in PublicFieldType],
1658
+ "field.relation_mode": [member.value for member in PublicRelationMode],
1626
1659
  "field_type_ids": sorted(FIELD_TYPE_ID_ALIASES.keys()),
1627
1660
  },
1628
1661
  "execution_notes": [
1629
1662
  "multiple relation fields are backend-risky; read verification.relation_field_limit_verified and warnings before declaring the schema stable",
1630
1663
  "backend 49614 is normalized to MULTIPLE_RELATION_FIELDS_UNSUPPORTED with a workaround message",
1664
+ "relation_mode=multiple maps to referenceConfig.optionalDataNum=0",
1631
1665
  ],
1632
1666
  "minimal_example": {
1633
1667
  "profile": "default",
@@ -1639,6 +1673,23 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
1639
1673
  "update_fields": [],
1640
1674
  "remove_fields": [],
1641
1675
  },
1676
+ "relation_example": {
1677
+ "profile": "default",
1678
+ "app_key": "APP_ITERATION",
1679
+ "publish": True,
1680
+ "add_fields": [
1681
+ {
1682
+ "name": "需求反馈引用",
1683
+ "type": "relation",
1684
+ "target_app_key": "APP_FEEDBACK",
1685
+ "relation_mode": "multiple",
1686
+ "display_field": {"name": "反馈标题"},
1687
+ "visible_fields": [{"name": "反馈标题"}, {"name": "优先级判断"}],
1688
+ }
1689
+ ],
1690
+ "update_fields": [],
1691
+ "remove_fields": [],
1692
+ },
1642
1693
  },
1643
1694
  "app_layout_plan": {
1644
1695
  "allowed_keys": ["app_key", "mode", "sections", "preset"],
@@ -268,6 +268,42 @@ class AppTools(ToolBase):
268
268
 
269
269
  return self._run(profile, runner)
270
270
 
271
+ def app_get_apply_base_info(self, *, profile: str, app_key: str, list_type: int) -> JSONObject:
272
+ self._require_app_key(app_key)
273
+ if not isinstance(list_type, int) or isinstance(list_type, bool) or list_type <= 0:
274
+ raise_tool_error(QingflowApiError.config_error("list_type must be a positive integer"))
275
+
276
+ def runner(session_profile, context):
277
+ result = self.backend.request("GET", context, f"/app/{app_key}/apply/baseInfo", params={"type": list_type})
278
+ return {
279
+ "profile": profile,
280
+ "ws_id": session_profile.selected_ws_id,
281
+ "app_key": app_key,
282
+ "list_type": list_type,
283
+ "result": result,
284
+ }
285
+
286
+ return self._run(profile, runner)
287
+
288
+ def app_update_apply_config(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
289
+ self._require_app_key(app_key)
290
+ body = self._require_dict(payload)
291
+
292
+ def runner(session_profile, context):
293
+ result = self.backend.request("POST", context, f"/app/{app_key}/apply/config", json_body=body)
294
+ return self._attach_human_review_notice(
295
+ {
296
+ "profile": profile,
297
+ "ws_id": session_profile.selected_ws_id,
298
+ "app_key": app_key,
299
+ "result": result,
300
+ },
301
+ operation="update",
302
+ target="app apply list configuration",
303
+ )
304
+
305
+ return self._run(profile, runner)
306
+
271
307
  def app_update_form_schema(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
272
308
  self._require_app_key(app_key)
273
309
  body = self._require_dict(payload)
@@ -149,7 +149,7 @@ class CodeBlockTools(RecordTools):
149
149
  run_result = self.backend.request(
150
150
  "POST",
151
151
  context,
152
- f"/app/{app_key}/codeBlock/working",
152
+ f"/data/{app_key}/codeBlock/working",
153
153
  json_body=run_body,
154
154
  )
155
155
  alias_results = _normalize_code_block_alias_results(run_result)
@@ -173,8 +173,22 @@ class CodeBlockTools(RecordTools):
173
173
  }
174
174
  if workflow_node_id is not None:
175
175
  relation_body["auditNodeId"] = workflow_node_id
176
- relation_result = self.backend.request("POST", context, "/que/actuator", json_body=relation_body)
177
- relation_items = _relation_result_items(relation_result)
176
+ relation_route = "/data/que/actuator"
177
+ try:
178
+ relation_result = self.backend.request("POST", context, relation_route, json_body=relation_body)
179
+ relation_items = _relation_result_items(relation_result)
180
+ except QingflowApiError as exc:
181
+ if exc.http_status != 404:
182
+ raise
183
+ relation_route = "/que/actuator"
184
+ relation_result = self.backend.request("POST", context, relation_route, json_body=relation_body)
185
+ relation_items = _relation_result_items(relation_result)
186
+ if not relation_items:
187
+ # Keep compatibility with legacy runtime deployments and lightweight test doubles
188
+ # that still stub the older relation-calculation route only.
189
+ relation_route = "/que/actuator"
190
+ relation_result = self.backend.request("POST", context, relation_route, json_body=relation_body)
191
+ relation_items = _relation_result_items(relation_result)
178
192
  relation_errors = _relation_result_errors(relation_items)
179
193
  calculated_answers = _relation_result_answers(relation_items)
180
194
  write_result: JSONObject | None = None
@@ -256,6 +270,7 @@ class CodeBlockTools(RecordTools):
256
270
  if normalized_output_profile == "verbose":
257
271
  response["debug"] = {
258
272
  "run_body": run_body,
273
+ "relation_route": relation_route if relation_target_fields else None,
259
274
  "relation_result": relation_result,
260
275
  "calculated_answers": calculated_answers,
261
276
  "merged_answers": merged_answers,