@qingflow-tech/qingflow-app-builder-mcp 1.0.5 → 1.0.7
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 -2
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/skills/qingflow-app-builder/SKILL.md +68 -6
- package/skills/qingflow-app-builder/references/create-app.md +4 -1
- package/skills/qingflow-app-builder/references/gotchas.md +13 -1
- package/skills/qingflow-app-builder/references/tool-selection.md +3 -1
- package/skills/qingflow-app-builder/references/update-schema.md +6 -2
- package/skills/qingflow-app-builder/references/update-views.md +126 -5
- package/src/qingflow_mcp/builder_facade/models.py +269 -2
- package/src/qingflow_mcp/builder_facade/service.py +3549 -172
- package/src/qingflow_mcp/cli/commands/builder.py +39 -26
- package/src/qingflow_mcp/cli/commands/record.py +19 -1
- package/src/qingflow_mcp/public_surface.py +2 -5
- package/src/qingflow_mcp/response_trim.py +65 -7
- package/src/qingflow_mcp/server.py +4 -3
- package/src/qingflow_mcp/server_app_builder.py +33 -20
- package/src/qingflow_mcp/server_app_user.py +4 -3
- package/src/qingflow_mcp/tools/ai_builder_tools.py +395 -117
- package/src/qingflow_mcp/tools/record_tools.py +622 -56
|
@@ -17,7 +17,9 @@ from ..config import DEFAULT_PROFILE
|
|
|
17
17
|
from ..errors import QingflowApiError
|
|
18
18
|
from ..json_types import JSONObject
|
|
19
19
|
from ..builder_facade.models import (
|
|
20
|
+
AssociatedResourcesApplyRequest,
|
|
20
21
|
ChartApplyRequest,
|
|
22
|
+
CustomButtonsApplyRequest,
|
|
21
23
|
CustomButtonPatch,
|
|
22
24
|
FIELD_TYPE_ID_ALIASES,
|
|
23
25
|
FieldPatch,
|
|
@@ -32,6 +34,7 @@ from ..builder_facade.models import (
|
|
|
32
34
|
LayoutPreset,
|
|
33
35
|
LayoutSectionPatch,
|
|
34
36
|
PortalApplyRequest,
|
|
37
|
+
PublicButtonPlacement,
|
|
35
38
|
PublicButtonTriggerAction,
|
|
36
39
|
PublicFieldType,
|
|
37
40
|
PublicRelationMode,
|
|
@@ -220,33 +223,38 @@ class AiBuilderTools(ToolBase):
|
|
|
220
223
|
return self.button_style_catalog_get(profile=profile)
|
|
221
224
|
|
|
222
225
|
@mcp.tool()
|
|
223
|
-
def
|
|
224
|
-
return self.app_custom_button_list(profile=profile, app_key=app_key)
|
|
225
|
-
|
|
226
|
-
@mcp.tool()
|
|
227
|
-
def app_custom_button_get(profile: str = DEFAULT_PROFILE, app_key: str = "", button_id: int = 0) -> JSONObject:
|
|
228
|
-
return self.app_custom_button_get(profile=profile, app_key=app_key, button_id=button_id)
|
|
229
|
-
|
|
230
|
-
@mcp.tool()
|
|
231
|
-
def app_custom_button_create(
|
|
226
|
+
def app_custom_buttons_apply(
|
|
232
227
|
profile: str = DEFAULT_PROFILE,
|
|
233
228
|
app_key: str = "",
|
|
234
|
-
|
|
229
|
+
upsert_buttons: list[JSONObject] | None = None,
|
|
230
|
+
remove_buttons: list[JSONObject] | None = None,
|
|
231
|
+
view_configs: list[JSONObject] | None = None,
|
|
235
232
|
) -> JSONObject:
|
|
236
|
-
return self.
|
|
233
|
+
return self.app_custom_buttons_apply(
|
|
234
|
+
profile=profile,
|
|
235
|
+
app_key=app_key,
|
|
236
|
+
upsert_buttons=upsert_buttons or [],
|
|
237
|
+
remove_buttons=remove_buttons or [],
|
|
238
|
+
view_configs=view_configs or [],
|
|
239
|
+
)
|
|
237
240
|
|
|
238
241
|
@mcp.tool()
|
|
239
|
-
def
|
|
242
|
+
def app_associated_resources_apply(
|
|
240
243
|
profile: str = DEFAULT_PROFILE,
|
|
241
244
|
app_key: str = "",
|
|
242
|
-
|
|
243
|
-
|
|
245
|
+
upsert_resources: list[JSONObject] | None = None,
|
|
246
|
+
remove_associated_item_ids: list[int] | None = None,
|
|
247
|
+
reorder_associated_item_ids: list[int] | None = None,
|
|
248
|
+
view_configs: list[JSONObject] | None = None,
|
|
244
249
|
) -> JSONObject:
|
|
245
|
-
return self.
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
+
return self.app_associated_resources_apply(
|
|
251
|
+
profile=profile,
|
|
252
|
+
app_key=app_key,
|
|
253
|
+
upsert_resources=upsert_resources or [],
|
|
254
|
+
remove_associated_item_ids=remove_associated_item_ids or [],
|
|
255
|
+
reorder_associated_item_ids=reorder_associated_item_ids or [],
|
|
256
|
+
view_configs=view_configs or [],
|
|
257
|
+
)
|
|
250
258
|
|
|
251
259
|
@mcp.tool()
|
|
252
260
|
def app_get(profile: str = DEFAULT_PROFILE, app_key: str = "") -> JSONObject:
|
|
@@ -867,6 +875,115 @@ class AiBuilderTools(ToolBase):
|
|
|
867
875
|
suggested_next_call={"tool_name": "button_style_catalog_get", "arguments": {"profile": profile}},
|
|
868
876
|
)
|
|
869
877
|
|
|
878
|
+
@tool_cn_name("应用按钮声明式应用")
|
|
879
|
+
def app_custom_buttons_apply(
|
|
880
|
+
self,
|
|
881
|
+
*,
|
|
882
|
+
profile: str,
|
|
883
|
+
app_key: str,
|
|
884
|
+
upsert_buttons: list[JSONObject],
|
|
885
|
+
remove_buttons: list[JSONObject],
|
|
886
|
+
view_configs: list[JSONObject] | None = None,
|
|
887
|
+
) -> JSONObject:
|
|
888
|
+
"""执行应用按钮 apply 逻辑。"""
|
|
889
|
+
raw_request = {
|
|
890
|
+
"app_key": app_key,
|
|
891
|
+
"upsert_buttons": upsert_buttons,
|
|
892
|
+
"remove_buttons": remove_buttons,
|
|
893
|
+
"view_configs": view_configs or [],
|
|
894
|
+
}
|
|
895
|
+
try:
|
|
896
|
+
request = CustomButtonsApplyRequest.model_validate(raw_request)
|
|
897
|
+
except ValidationError as exc:
|
|
898
|
+
return _validation_failure(
|
|
899
|
+
str(exc),
|
|
900
|
+
tool_name="app_custom_buttons_apply",
|
|
901
|
+
exc=exc,
|
|
902
|
+
suggested_next_call={
|
|
903
|
+
"tool_name": "app_custom_buttons_apply",
|
|
904
|
+
"arguments": {
|
|
905
|
+
"profile": profile,
|
|
906
|
+
"app_key": app_key or "APP_KEY",
|
|
907
|
+
"upsert_buttons": [
|
|
908
|
+
{
|
|
909
|
+
"button_text": "同步客户",
|
|
910
|
+
"style_preset": "primary_blue",
|
|
911
|
+
"button_icon": "ex-switch",
|
|
912
|
+
"trigger_action": "link",
|
|
913
|
+
"trigger_link_url": "https://example.com",
|
|
914
|
+
}
|
|
915
|
+
],
|
|
916
|
+
"remove_buttons": [],
|
|
917
|
+
"view_configs": [],
|
|
918
|
+
},
|
|
919
|
+
},
|
|
920
|
+
)
|
|
921
|
+
normalized_args = request.model_dump(mode="json")
|
|
922
|
+
return _safe_tool_call(
|
|
923
|
+
lambda: self._facade.app_custom_buttons_apply(profile=profile, request=request),
|
|
924
|
+
error_code="CUSTOM_BUTTONS_APPLY_FAILED",
|
|
925
|
+
normalized_args=normalized_args,
|
|
926
|
+
suggested_next_call={"tool_name": "app_custom_buttons_apply", "arguments": {"profile": profile, **normalized_args}},
|
|
927
|
+
)
|
|
928
|
+
|
|
929
|
+
@tool_cn_name("应用关联资源声明式应用")
|
|
930
|
+
def app_associated_resources_apply(
|
|
931
|
+
self,
|
|
932
|
+
*,
|
|
933
|
+
profile: str,
|
|
934
|
+
app_key: str,
|
|
935
|
+
upsert_resources: list[JSONObject],
|
|
936
|
+
remove_associated_item_ids: list[int],
|
|
937
|
+
reorder_associated_item_ids: list[int],
|
|
938
|
+
view_configs: list[JSONObject],
|
|
939
|
+
) -> JSONObject:
|
|
940
|
+
"""执行应用关联资源 apply 逻辑。"""
|
|
941
|
+
raw_request = {
|
|
942
|
+
"app_key": app_key,
|
|
943
|
+
"upsert_resources": upsert_resources,
|
|
944
|
+
"remove_associated_item_ids": remove_associated_item_ids,
|
|
945
|
+
"reorder_associated_item_ids": reorder_associated_item_ids,
|
|
946
|
+
"view_configs": view_configs,
|
|
947
|
+
}
|
|
948
|
+
try:
|
|
949
|
+
request = AssociatedResourcesApplyRequest.model_validate(raw_request)
|
|
950
|
+
except ValidationError as exc:
|
|
951
|
+
return _validation_failure(
|
|
952
|
+
str(exc),
|
|
953
|
+
tool_name="app_associated_resources_apply",
|
|
954
|
+
exc=exc,
|
|
955
|
+
suggested_next_call={
|
|
956
|
+
"tool_name": "app_associated_resources_apply",
|
|
957
|
+
"arguments": {
|
|
958
|
+
"profile": profile,
|
|
959
|
+
"app_key": app_key or "APP_KEY",
|
|
960
|
+
"upsert_resources": [
|
|
961
|
+
{
|
|
962
|
+
"client_key": "customer_view",
|
|
963
|
+
"graph_type": "view",
|
|
964
|
+
"target_app_key": "TARGET_APP",
|
|
965
|
+
"view_key": "VIEW_KEY",
|
|
966
|
+
}
|
|
967
|
+
],
|
|
968
|
+
"view_configs": [
|
|
969
|
+
{
|
|
970
|
+
"view_key": "MAIN_VIEW",
|
|
971
|
+
"visible": True,
|
|
972
|
+
"limit_type": "select",
|
|
973
|
+
"associated_item_refs": ["customer_view"],
|
|
974
|
+
}
|
|
975
|
+
],
|
|
976
|
+
},
|
|
977
|
+
},
|
|
978
|
+
)
|
|
979
|
+
normalized_args = request.model_dump(mode="json", exclude_none=True)
|
|
980
|
+
return _safe_tool_call(
|
|
981
|
+
lambda: self._facade.app_associated_resources_apply(profile=profile, request=request),
|
|
982
|
+
error_code="ASSOCIATED_RESOURCES_APPLY_FAILED",
|
|
983
|
+
normalized_args=normalized_args,
|
|
984
|
+
suggested_next_call={"tool_name": "app_associated_resources_apply", "arguments": {"profile": profile, **normalized_args}},
|
|
985
|
+
)
|
|
986
|
+
|
|
870
987
|
@tool_cn_name("应用按钮列表")
|
|
871
988
|
def app_custom_button_list(self, *, profile: str, app_key: str) -> JSONObject:
|
|
872
989
|
"""执行应用相关逻辑。"""
|
|
@@ -909,7 +1026,10 @@ class AiBuilderTools(ToolBase):
|
|
|
909
1026
|
"style_preset": "primary_blue",
|
|
910
1027
|
"button_icon": "ex-plus-circle",
|
|
911
1028
|
"trigger_action": "addData",
|
|
912
|
-
"trigger_add_data_config": {
|
|
1029
|
+
"trigger_add_data_config": {
|
|
1030
|
+
"target_app_key": "TARGET_APP_KEY",
|
|
1031
|
+
"field_mappings": [{"source_field": "客户名称", "target_field": "客户"}],
|
|
1032
|
+
},
|
|
913
1033
|
},
|
|
914
1034
|
},
|
|
915
1035
|
},
|
|
@@ -2572,115 +2692,209 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
2572
2692
|
"profile": "default",
|
|
2573
2693
|
},
|
|
2574
2694
|
},
|
|
2575
|
-
"
|
|
2576
|
-
"allowed_keys": [
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
"
|
|
2581
|
-
"
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
"
|
|
2590
|
-
"
|
|
2591
|
-
"
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2695
|
+
"app_custom_buttons_apply": {
|
|
2696
|
+
"allowed_keys": [
|
|
2697
|
+
"app_key",
|
|
2698
|
+
"upsert_buttons",
|
|
2699
|
+
"remove_buttons",
|
|
2700
|
+
"view_configs",
|
|
2701
|
+
"upsert_buttons[].client_key",
|
|
2702
|
+
"upsert_buttons[].button_id",
|
|
2703
|
+
"upsert_buttons[].button_text",
|
|
2704
|
+
"upsert_buttons[].style_preset",
|
|
2705
|
+
"upsert_buttons[].background_color",
|
|
2706
|
+
"upsert_buttons[].text_color",
|
|
2707
|
+
"upsert_buttons[].button_icon",
|
|
2708
|
+
"upsert_buttons[].trigger_action",
|
|
2709
|
+
"upsert_buttons[].trigger_link_url",
|
|
2710
|
+
"upsert_buttons[].trigger_add_data_config",
|
|
2711
|
+
"upsert_buttons[].trigger_add_data_config.target_app_key",
|
|
2712
|
+
"upsert_buttons[].trigger_add_data_config.field_mappings",
|
|
2713
|
+
"upsert_buttons[].trigger_add_data_config.field_mappings[].source_field",
|
|
2714
|
+
"upsert_buttons[].trigger_add_data_config.field_mappings[].target_field",
|
|
2715
|
+
"upsert_buttons[].trigger_add_data_config.default_values",
|
|
2716
|
+
"view_configs[].view_key",
|
|
2717
|
+
"view_configs[].mode",
|
|
2718
|
+
"view_configs[].buttons",
|
|
2719
|
+
"view_configs[].buttons[].button_ref",
|
|
2720
|
+
"view_configs[].buttons[].placement",
|
|
2721
|
+
"view_configs[].buttons[].primary",
|
|
2722
|
+
"view_configs[].buttons[].button_limit",
|
|
2723
|
+
"view_configs[].buttons[].button_formula",
|
|
2724
|
+
"view_configs[].buttons[].button_formula_type",
|
|
2725
|
+
"view_configs[].buttons[].print_tpls",
|
|
2726
|
+
"remove_buttons[].button_id",
|
|
2727
|
+
"remove_buttons[].button_text",
|
|
2728
|
+
],
|
|
2596
2729
|
"aliases": {
|
|
2597
|
-
"
|
|
2598
|
-
"
|
|
2599
|
-
"
|
|
2600
|
-
"
|
|
2601
|
-
"
|
|
2602
|
-
"
|
|
2603
|
-
"
|
|
2604
|
-
"
|
|
2605
|
-
"
|
|
2606
|
-
"
|
|
2607
|
-
"
|
|
2730
|
+
"upsertButtons": "upsert_buttons",
|
|
2731
|
+
"removeButtons": "remove_buttons",
|
|
2732
|
+
"viewConfigs": "view_configs",
|
|
2733
|
+
"clientKey": "client_key",
|
|
2734
|
+
"buttonId": "button_id",
|
|
2735
|
+
"buttonText": "button_text",
|
|
2736
|
+
"stylePreset": "style_preset",
|
|
2737
|
+
"backgroundColor": "background_color",
|
|
2738
|
+
"textColor": "text_color",
|
|
2739
|
+
"buttonIcon": "button_icon",
|
|
2740
|
+
"triggerAction": "trigger_action",
|
|
2741
|
+
"triggerLinkUrl": "trigger_link_url",
|
|
2742
|
+
"triggerAddDataConfig": "trigger_add_data_config",
|
|
2743
|
+
"targetAppKey": "trigger_add_data_config.target_app_key",
|
|
2744
|
+
"fieldMappings": "trigger_add_data_config.field_mappings",
|
|
2745
|
+
"defaultValues": "trigger_add_data_config.default_values",
|
|
2746
|
+
"mode": "view_configs[].mode",
|
|
2747
|
+
"applyMode": "view_configs[].mode",
|
|
2748
|
+
"buttonRef": "view_configs[].buttons[].button_ref",
|
|
2749
|
+
"beingMain": "view_configs[].buttons[].primary",
|
|
2750
|
+
"buttonLimit": "view_configs[].buttons[].button_limit",
|
|
2751
|
+
"visibleWhen": "view_configs[].buttons[].button_limit",
|
|
2752
|
+
"buttonFormula": "view_configs[].buttons[].button_formula",
|
|
2753
|
+
"buttonFormulaType": "view_configs[].buttons[].button_formula_type",
|
|
2754
|
+
"printTpls": "view_configs[].buttons[].print_tpls",
|
|
2755
|
+
"externalQrobotConfig": "external_qrobot_config",
|
|
2756
|
+
"customButtonExternalQRobotRelationVO": "external_qrobot_config",
|
|
2757
|
+
"triggerWingsConfig": "trigger_wings_config",
|
|
2608
2758
|
},
|
|
2609
2759
|
"allowed_values": {
|
|
2610
|
-
"
|
|
2611
|
-
"
|
|
2612
|
-
"
|
|
2613
|
-
"
|
|
2614
|
-
"
|
|
2760
|
+
"upsert_buttons[].trigger_action": [member.value for member in PublicButtonTriggerAction],
|
|
2761
|
+
"upsert_buttons[].style_preset": [item["key"] for item in BUTTON_STYLE_PRESETS],
|
|
2762
|
+
"upsert_buttons[].button_icon": list(BUTTON_ICONS),
|
|
2763
|
+
"upsert_buttons[].background_color": list(BUTTON_BACKGROUND_COLORS),
|
|
2764
|
+
"upsert_buttons[].text_color": list(BUTTON_TEXT_COLORS),
|
|
2765
|
+
"view_configs[].mode": ["merge", "replace"],
|
|
2766
|
+
"view_configs[].buttons[].placement": [member.value for member in PublicButtonPlacement],
|
|
2615
2767
|
},
|
|
2616
2768
|
"execution_notes": [
|
|
2617
|
-
"
|
|
2769
|
+
"this is the default custom-button write path; old list/get/create/update/delete tools are hidden from the public agent surface",
|
|
2770
|
+
"button_id targets an existing button; without button_id, button_text is used as an exact unique upsert key, otherwise a new button is created",
|
|
2771
|
+
"for addData buttons, use trigger_add_data_config.target_app_key plus field_mappings/default_values; field_mappings compiles to backend queRelation",
|
|
2772
|
+
"do not write raw que_relation unless maintaining a legacy config; field_mappings/default_values and que_relation are mutually exclusive",
|
|
2773
|
+
"view_configs binds custom buttons into views in the same apply call; button_ref may be a same-call client_key, a button_id, or an exact unique existing button_text",
|
|
2774
|
+
"view_configs[].buttons is required in merge mode; omitting buttons is blocked to avoid no-op writes and accidental publish",
|
|
2775
|
+
"view_configs[].mode defaults to merge; use mode=replace or an explicit empty buttons list to replace/clear a view's custom button bindings",
|
|
2776
|
+
"advanced view button binding supports button_limit, button_formula, button_formula_type, and print_tpls when visibility or print-template behavior is required",
|
|
2777
|
+
"default placements are header and detail; header maps to frontend top buttons",
|
|
2778
|
+
"placement=list is accepted as an experimental row/list placement, but some backend deployments reject it; if that happens, the tool returns LIST_BUTTON_BACKEND_UNSUPPORTED and still applies header/detail placements when they were part of the same view config",
|
|
2779
|
+
"remove_buttons supports button_id or exact unique button_text",
|
|
2780
|
+
"all operations share one edit context and publish after at least one write succeeds; there is no draft-only mode for this tool",
|
|
2618
2781
|
"background_color and text_color cannot both be white",
|
|
2619
|
-
"payload accepts either style_preset + optional button_icon, or explicit button_icon/background_color/text_color from button_style_catalog_get",
|
|
2620
|
-
"for addData buttons, put field mappings in payload.trigger_add_data_config.que_relation",
|
|
2621
2782
|
],
|
|
2622
2783
|
"minimal_example": {
|
|
2623
2784
|
"profile": "default",
|
|
2624
2785
|
"app_key": "APP_KEY",
|
|
2625
|
-
"
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2786
|
+
"upsert_buttons": [
|
|
2787
|
+
{
|
|
2788
|
+
"button_text": "同步客户",
|
|
2789
|
+
"style_preset": "primary_blue",
|
|
2790
|
+
"button_icon": "ex-switch",
|
|
2791
|
+
"trigger_action": "link",
|
|
2792
|
+
"trigger_link_url": "https://example.com",
|
|
2793
|
+
}
|
|
2794
|
+
],
|
|
2795
|
+
"remove_buttons": [{"button_text": "旧按钮"}],
|
|
2796
|
+
"view_configs": [],
|
|
2797
|
+
},
|
|
2798
|
+
"add_data_example": {
|
|
2799
|
+
"profile": "default",
|
|
2800
|
+
"app_key": "APP_KEY",
|
|
2801
|
+
"upsert_buttons": [
|
|
2802
|
+
{
|
|
2803
|
+
"client_key": "add_order",
|
|
2804
|
+
"button_text": "新增订单",
|
|
2805
|
+
"style_preset": "neutral_outline",
|
|
2806
|
+
"button_icon": "ex-plus-circle",
|
|
2807
|
+
"trigger_action": "addData",
|
|
2808
|
+
"trigger_add_data_config": {
|
|
2809
|
+
"target_app_key": "TARGET_APP",
|
|
2810
|
+
"field_mappings": [{"source_field": "客户名称", "target_field": "客户"}],
|
|
2811
|
+
"default_values": {"状态": "待提交"},
|
|
2812
|
+
},
|
|
2813
|
+
}
|
|
2814
|
+
],
|
|
2815
|
+
"remove_buttons": [],
|
|
2816
|
+
"view_configs": [
|
|
2817
|
+
{
|
|
2818
|
+
"view_key": "VIEW_KEY",
|
|
2819
|
+
"buttons": [{"button_ref": "add_order", "placement": "detail", "primary": True}],
|
|
2820
|
+
}
|
|
2821
|
+
],
|
|
2632
2822
|
},
|
|
2633
2823
|
},
|
|
2634
|
-
"
|
|
2635
|
-
"allowed_keys": [
|
|
2824
|
+
"app_associated_resources_apply": {
|
|
2825
|
+
"allowed_keys": [
|
|
2826
|
+
"app_key",
|
|
2827
|
+
"upsert_resources",
|
|
2828
|
+
"remove_associated_item_ids",
|
|
2829
|
+
"reorder_associated_item_ids",
|
|
2830
|
+
"view_configs",
|
|
2831
|
+
"upsert_resources[].client_key",
|
|
2832
|
+
"upsert_resources[].associated_item_id",
|
|
2833
|
+
"upsert_resources[].graph_type",
|
|
2834
|
+
"upsert_resources[].target_app_key",
|
|
2835
|
+
"upsert_resources[].view_key",
|
|
2836
|
+
"upsert_resources[].chart_key",
|
|
2837
|
+
"upsert_resources[].report_source",
|
|
2838
|
+
"upsert_resources[].match_rules",
|
|
2839
|
+
"view_configs[].view_key",
|
|
2840
|
+
"view_configs[].visible",
|
|
2841
|
+
"view_configs[].limit_type",
|
|
2842
|
+
"view_configs[].associated_item_ids",
|
|
2843
|
+
"view_configs[].associated_item_refs",
|
|
2844
|
+
],
|
|
2636
2845
|
"aliases": {
|
|
2637
|
-
"
|
|
2638
|
-
"
|
|
2639
|
-
"
|
|
2640
|
-
"
|
|
2641
|
-
"
|
|
2642
|
-
"
|
|
2643
|
-
"
|
|
2644
|
-
"
|
|
2645
|
-
"
|
|
2646
|
-
"
|
|
2647
|
-
"
|
|
2648
|
-
"
|
|
2846
|
+
"upsertResources": "upsert_resources",
|
|
2847
|
+
"resources": "upsert_resources",
|
|
2848
|
+
"removeAssociatedItemIds": "remove_associated_item_ids",
|
|
2849
|
+
"reorderAssociatedItemIds": "reorder_associated_item_ids",
|
|
2850
|
+
"viewConfigs": "view_configs",
|
|
2851
|
+
"associatedItemId": "associated_item_id",
|
|
2852
|
+
"graphType": "graph_type",
|
|
2853
|
+
"targetAppKey": "target_app_key",
|
|
2854
|
+
"chartKey": "chart_key",
|
|
2855
|
+
"viewKey": "view_key",
|
|
2856
|
+
"viewgraphKey": "view_key",
|
|
2857
|
+
"reportSource": "report_source",
|
|
2858
|
+
"matchRules": "match_rules",
|
|
2859
|
+
"associatedItemRefs": "associated_item_refs",
|
|
2860
|
+
"associatedItemIds": "associated_item_ids",
|
|
2649
2861
|
},
|
|
2650
2862
|
"allowed_values": {
|
|
2651
|
-
"
|
|
2652
|
-
"
|
|
2653
|
-
"
|
|
2654
|
-
"payload.background_color": list(BUTTON_BACKGROUND_COLORS),
|
|
2655
|
-
"payload.text_color": list(BUTTON_TEXT_COLORS),
|
|
2863
|
+
"upsert_resources[].graph_type": ["chart", "view"],
|
|
2864
|
+
"upsert_resources[].report_source": ["app", "dataset"],
|
|
2865
|
+
"view_configs[].limit_type": ["all", "select"],
|
|
2656
2866
|
},
|
|
2657
2867
|
"execution_notes": [
|
|
2658
|
-
"
|
|
2659
|
-
"
|
|
2660
|
-
"
|
|
2661
|
-
"
|
|
2868
|
+
"this is the default associated report/view path; it manages both the app-level associated resource pool and per-view display config",
|
|
2869
|
+
"associated_item_id is form_asos_chart.id from app_get.associated_resources[].associated_item_id; it is not chart_id, chart_key, or view_key",
|
|
2870
|
+
"graph_type=view uses view_key and internally compiles to the Qingflow view source; graph_type=chart uses chart_key and defaults to report_source=app",
|
|
2871
|
+
"report_source=app maps to BI_QINGFLOW; report_source=dataset maps to BI_DATASET; do not pass raw backend sourceType",
|
|
2872
|
+
"client_key lets a view_config reference a resource created earlier in the same apply call through associated_item_refs",
|
|
2873
|
+
"this tool publishes after at least one write succeeds; there is no draft-only mode",
|
|
2874
|
+
"visible=false hides the associated-resource area without clearing previous selected ids; visible=true with limit_type=all shows the whole app-level pool",
|
|
2662
2875
|
],
|
|
2663
2876
|
"minimal_example": {
|
|
2664
2877
|
"profile": "default",
|
|
2665
2878
|
"app_key": "APP_KEY",
|
|
2666
|
-
"
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2879
|
+
"upsert_resources": [
|
|
2880
|
+
{
|
|
2881
|
+
"client_key": "customer_view",
|
|
2882
|
+
"graph_type": "view",
|
|
2883
|
+
"target_app_key": "TARGET_APP",
|
|
2884
|
+
"view_key": "VIEW_KEY",
|
|
2885
|
+
"match_rules": [],
|
|
2886
|
+
}
|
|
2887
|
+
],
|
|
2888
|
+
"remove_associated_item_ids": [],
|
|
2889
|
+
"reorder_associated_item_ids": [],
|
|
2890
|
+
"view_configs": [
|
|
2891
|
+
{
|
|
2892
|
+
"view_key": "MAIN_VIEW",
|
|
2893
|
+
"visible": True,
|
|
2894
|
+
"limit_type": "select",
|
|
2895
|
+
"associated_item_refs": ["customer_view"],
|
|
2896
|
+
}
|
|
2897
|
+
],
|
|
2684
2898
|
},
|
|
2685
2899
|
},
|
|
2686
2900
|
"app_schema_plan": {
|
|
@@ -2709,6 +2923,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
2709
2923
|
"field.customBtnTextStatus": "field.custom_button_text_enabled",
|
|
2710
2924
|
"field.customBtnText": "field.custom_button_text",
|
|
2711
2925
|
"field.subfieldUpdates": "field.subfield_updates",
|
|
2926
|
+
"field.asDataTitle": "field.as_data_title",
|
|
2927
|
+
"field.asDataCover": "field.as_data_cover",
|
|
2712
2928
|
},
|
|
2713
2929
|
"allowed_values": {
|
|
2714
2930
|
"field.type": [member.value for member in PublicFieldType],
|
|
@@ -2728,7 +2944,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
2728
2944
|
"color": "emerald",
|
|
2729
2945
|
"visibility": deepcopy(_VISIBILITY_WORKSPACE_EXAMPLE),
|
|
2730
2946
|
"create_if_missing": True,
|
|
2731
|
-
"add_fields": [{"name": "项目名称", "type": "text"}],
|
|
2947
|
+
"add_fields": [{"name": "项目名称", "type": "text", "as_data_title": True}],
|
|
2732
2948
|
"update_fields": [],
|
|
2733
2949
|
"remove_fields": [],
|
|
2734
2950
|
},
|
|
@@ -2775,6 +2991,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
2775
2991
|
"field.customBtnTextStatus": "field.custom_button_text_enabled",
|
|
2776
2992
|
"field.customBtnText": "field.custom_button_text",
|
|
2777
2993
|
"field.subfieldUpdates": "field.subfield_updates",
|
|
2994
|
+
"field.asDataTitle": "field.as_data_title",
|
|
2995
|
+
"field.asDataCover": "field.as_data_cover",
|
|
2778
2996
|
},
|
|
2779
2997
|
"allowed_values": {
|
|
2780
2998
|
"field.type": [member.value for member in PublicFieldType],
|
|
@@ -2806,6 +3024,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
2806
3024
|
"code block outputs must be emitted through qf_output assignment; use qf_output = {...} or assign qf_output after building the result object, never const/let qf_output =",
|
|
2807
3025
|
"builder automatically normalizes const/let qf_output assignments on write and rejects output-bound code blocks that still do not contain a valid qf_output assignment",
|
|
2808
3026
|
"code_block_binding and q_linker_binding target fields are limited to text, long_text, number, amount, date, datetime, single_select, multi_select, and boolean",
|
|
3027
|
+
"data title is required: mark exactly one top-level field with as_data_title=true; use a readable name/number/date-like field",
|
|
3028
|
+
"data cover is optional: mark at most one top-level attachment field with as_data_cover=true",
|
|
2809
3029
|
],
|
|
2810
3030
|
"minimal_example": {
|
|
2811
3031
|
"profile": "default",
|
|
@@ -2816,7 +3036,10 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
2816
3036
|
"visibility": deepcopy(_VISIBILITY_WORKSPACE_EXAMPLE),
|
|
2817
3037
|
"create_if_missing": True,
|
|
2818
3038
|
"publish": True,
|
|
2819
|
-
"add_fields": [
|
|
3039
|
+
"add_fields": [
|
|
3040
|
+
{"name": "项目名称", "type": "text", "as_data_title": True},
|
|
3041
|
+
{"name": "项目封面", "type": "attachment", "as_data_cover": True},
|
|
3042
|
+
],
|
|
2820
3043
|
"update_fields": [],
|
|
2821
3044
|
"remove_fields": [],
|
|
2822
3045
|
},
|
|
@@ -3085,7 +3308,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3085
3308
|
},
|
|
3086
3309
|
},
|
|
3087
3310
|
"app_views_plan": {
|
|
3088
|
-
"allowed_keys": ["app_key", "upsert_views", "remove_views", "preset", "upsert_views[].view_key", "upsert_views[].buttons", "upsert_views[].visibility"],
|
|
3311
|
+
"allowed_keys": ["app_key", "upsert_views", "remove_views", "preset", "upsert_views[].view_key", "upsert_views[].buttons", "upsert_views[].visibility", "upsert_views[].query_conditions"],
|
|
3089
3312
|
"aliases": {
|
|
3090
3313
|
"fields": "columns",
|
|
3091
3314
|
"column_names": "columns",
|
|
@@ -3096,6 +3319,9 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3096
3319
|
"kanban": "board",
|
|
3097
3320
|
"filter_rules": "filters",
|
|
3098
3321
|
"filterRules": "filters",
|
|
3322
|
+
"queryConditions": "query_conditions",
|
|
3323
|
+
"query_condition": "query_conditions",
|
|
3324
|
+
"queryCondition": "query_conditions",
|
|
3099
3325
|
"startField": "start_field",
|
|
3100
3326
|
"endField": "end_field",
|
|
3101
3327
|
"titleField": "title_field",
|
|
@@ -3118,6 +3344,9 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3118
3344
|
},
|
|
3119
3345
|
"execution_notes": [
|
|
3120
3346
|
"upsert_views[].visibility may set per-view visibility; omit it to preserve an existing view's auth or default a new view to workspace/not",
|
|
3347
|
+
"filters are saved fixed filters that apply when the view opens; query_conditions configure the frontend query panel and only apply after a user enters query values",
|
|
3348
|
+
"upsert_views[].query_conditions.rows is a layout matrix of field names; it is compiled to backend queryCondition queIds",
|
|
3349
|
+
"view associated report/view display is now configured through app_associated_resources_apply, not app_views_apply",
|
|
3121
3350
|
"for multi-value operators such as in, pass values as a list; value may also be used as an alias when it already contains a list",
|
|
3122
3351
|
*_VISIBILITY_EXECUTION_NOTES,
|
|
3123
3352
|
],
|
|
@@ -3127,6 +3356,25 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3127
3356
|
"upsert_views": [{"name": "全部数据", "type": "table", "columns": ["项目名称"], "visibility": deepcopy(_VISIBILITY_WORKSPACE_EXAMPLE)}],
|
|
3128
3357
|
"remove_views": [],
|
|
3129
3358
|
},
|
|
3359
|
+
"query_conditions_example": {
|
|
3360
|
+
"profile": "default",
|
|
3361
|
+
"app_key": "APP_KEY",
|
|
3362
|
+
"upsert_views": [
|
|
3363
|
+
{
|
|
3364
|
+
"name": "客户查询视图",
|
|
3365
|
+
"type": "table",
|
|
3366
|
+
"columns": ["客户名称", "负责人", "客户状态", "创建时间"],
|
|
3367
|
+
"filters": [{"field_name": "客户状态", "operator": "eq", "value": "有效"}],
|
|
3368
|
+
"query_conditions": {
|
|
3369
|
+
"enabled": True,
|
|
3370
|
+
"exact": False,
|
|
3371
|
+
"hide_before_query": False,
|
|
3372
|
+
"rows": [["客户名称", "负责人"], ["创建时间"]],
|
|
3373
|
+
},
|
|
3374
|
+
}
|
|
3375
|
+
],
|
|
3376
|
+
"remove_views": [],
|
|
3377
|
+
},
|
|
3130
3378
|
"gantt_example": {
|
|
3131
3379
|
"profile": "default",
|
|
3132
3380
|
"app_key": "APP_KEY",
|
|
@@ -3145,7 +3393,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3145
3393
|
},
|
|
3146
3394
|
},
|
|
3147
3395
|
"app_views_apply": {
|
|
3148
|
-
"allowed_keys": ["app_key", "publish", "upsert_views", "remove_views", "upsert_views[].view_key", "upsert_views[].buttons", "upsert_views[].visibility"],
|
|
3396
|
+
"allowed_keys": ["app_key", "publish", "upsert_views", "remove_views", "upsert_views[].view_key", "upsert_views[].buttons", "upsert_views[].visibility", "upsert_views[].query_conditions"],
|
|
3149
3397
|
"aliases": {
|
|
3150
3398
|
"fields": "columns",
|
|
3151
3399
|
"column_names": "columns",
|
|
@@ -3156,6 +3404,9 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3156
3404
|
"kanban": "board",
|
|
3157
3405
|
"filter_rules": "filters",
|
|
3158
3406
|
"filterRules": "filters",
|
|
3407
|
+
"queryConditions": "query_conditions",
|
|
3408
|
+
"query_condition": "query_conditions",
|
|
3409
|
+
"queryCondition": "query_conditions",
|
|
3159
3410
|
"startField": "start_field",
|
|
3160
3411
|
"endField": "end_field",
|
|
3161
3412
|
"titleField": "title_field",
|
|
@@ -3178,10 +3429,13 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3178
3429
|
"execution_notes": [
|
|
3179
3430
|
"apply may return partial_success when some views land and others fail",
|
|
3180
3431
|
"when duplicate view names exist, supply view_key to target the exact view",
|
|
3181
|
-
"read back
|
|
3432
|
+
"read back app_get after any failed or partial view apply",
|
|
3182
3433
|
"view existence verification and saved-filter verification are separate; treat filters as unverified until verification.view_filters_verified is true",
|
|
3183
3434
|
"buttons omitted preserves existing button config; buttons=[] clears all buttons; buttons=[...] replaces the full button config",
|
|
3184
3435
|
"upsert_views[].visibility may set per-view visibility; omit it to preserve an existing view's auth or default a new view to workspace/not",
|
|
3436
|
+
"filters are saved fixed filters that apply when the view opens; query_conditions configure the frontend query panel and only apply after a user enters query values",
|
|
3437
|
+
"upsert_views[].query_conditions.rows is a layout matrix of field names; it is compiled to backend queryCondition queIds",
|
|
3438
|
+
"view associated report/view display is now configured through app_associated_resources_apply; app_views_apply keeps legacy associated_resources input compatible but it is no longer the recommended public contract",
|
|
3185
3439
|
"for multi-value operators such as in, pass values as a list; value may also be used as an alias when it already contains a list",
|
|
3186
3440
|
*_VISIBILITY_EXECUTION_NOTES,
|
|
3187
3441
|
],
|
|
@@ -3192,6 +3446,26 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3192
3446
|
"upsert_views": [{"name": "全部数据", "type": "table", "columns": ["项目名称"], "visibility": deepcopy(_VISIBILITY_WORKSPACE_EXAMPLE)}],
|
|
3193
3447
|
"remove_views": [],
|
|
3194
3448
|
},
|
|
3449
|
+
"query_conditions_example": {
|
|
3450
|
+
"profile": "default",
|
|
3451
|
+
"app_key": "APP_KEY",
|
|
3452
|
+
"publish": True,
|
|
3453
|
+
"upsert_views": [
|
|
3454
|
+
{
|
|
3455
|
+
"name": "客户查询视图",
|
|
3456
|
+
"type": "table",
|
|
3457
|
+
"columns": ["客户名称", "负责人", "客户状态", "创建时间"],
|
|
3458
|
+
"filters": [{"field_name": "客户状态", "operator": "eq", "value": "有效"}],
|
|
3459
|
+
"query_conditions": {
|
|
3460
|
+
"enabled": True,
|
|
3461
|
+
"exact": False,
|
|
3462
|
+
"hide_before_query": False,
|
|
3463
|
+
"rows": [["客户名称", "负责人"], ["创建时间"]],
|
|
3464
|
+
},
|
|
3465
|
+
}
|
|
3466
|
+
],
|
|
3467
|
+
"remove_views": [],
|
|
3468
|
+
},
|
|
3195
3469
|
"gantt_example": {
|
|
3196
3470
|
"profile": "default",
|
|
3197
3471
|
"app_key": "APP_KEY",
|
|
@@ -3215,12 +3489,14 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3215
3489
|
"aliases": {},
|
|
3216
3490
|
"allowed_values": {},
|
|
3217
3491
|
"execution_notes": [
|
|
3218
|
-
"returns builder-side app
|
|
3219
|
-
"use this as the default builder discovery read before
|
|
3492
|
+
"returns builder-side app map: base summary, editability, field/view/chart/button counts, compact views, compact charts, custom_buttons, and app-level associated_resources",
|
|
3493
|
+
"use this as the default builder discovery read before view_get/chart_get/apply detail work",
|
|
3220
3494
|
"editability is route-aware builder capability summary, not end-user data visibility",
|
|
3221
3495
|
"can_edit_app_base covers app base-info writes such as app_name, icon, and visibility",
|
|
3222
3496
|
"can_edit_form covers form/schema routes only and does not imply app base-info writes",
|
|
3223
3497
|
"returns normalized app visibility when backend auth is readable",
|
|
3498
|
+
"custom_buttons[].button_id is the id required by app_custom_buttons_apply view_configs[].buttons[].button_ref",
|
|
3499
|
+
"associated_resources[].associated_item_id is the id required by app_associated_resources_apply.view_configs.associated_item_ids; do not pass chart_id there",
|
|
3224
3500
|
],
|
|
3225
3501
|
"minimal_example": {
|
|
3226
3502
|
"profile": "default",
|
|
@@ -3260,7 +3536,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3260
3536
|
"allowed_values": {},
|
|
3261
3537
|
"execution_notes": [
|
|
3262
3538
|
"returns compact current view inventory for one app",
|
|
3263
|
-
"
|
|
3539
|
+
"compatibility/specialized inventory tool; default builder discovery should start with app_get",
|
|
3540
|
+
"use this before app_views_apply only when you need an exact current view inventory beyond app_get",
|
|
3264
3541
|
"view items include visibility_summary when backend view auth is readable",
|
|
3265
3542
|
],
|
|
3266
3543
|
"minimal_example": {
|
|
@@ -3287,7 +3564,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
3287
3564
|
"allowed_values": {},
|
|
3288
3565
|
"execution_notes": [
|
|
3289
3566
|
"returns a compact current chart inventory for one app",
|
|
3290
|
-
"
|
|
3567
|
+
"compatibility/specialized inventory tool; default builder discovery should start with app_get",
|
|
3568
|
+
"use this before app_charts_apply when you need exact current chart_id values beyond the app_get summary",
|
|
3291
3569
|
"chart summaries do not include full qingbi config payloads",
|
|
3292
3570
|
"chart items include visibility_summary when QingBI base info is readable",
|
|
3293
3571
|
],
|