@josephyan/qingflow-cli 1.1.15 → 1.1.17
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-cli/SKILL.md +2 -2
- package/skills/qingflow-cli/reference/builder/20-build-complete-system.md +10 -2
- package/skills/qingflow-cli/reference/builder/30-schema-fields.md +22 -1
- package/skills/qingflow-cli/reference/builder/50-views.md +83 -12
- package/skills/qingflow-cli/reference/builder/70-portal.md +16 -4
- package/skills/qingflow-cli/reference/builder/80-buttons-associated-resources.md +57 -4
- package/skills/qingflow-cli/reference/builder/90-workflow.md +1 -0
- package/skills/qingflow-cli/reference/builder/99-publish-verify.md +3 -0
- package/skills/qingflow-cli/reference/builder/workflow/README.md +1 -1
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +1 -1
- package/skills/qingflow-cli/reference/examples/portal/portal_sections_all_types.example.json +2 -2
- package/skills/qingflow-cli/reference/examples/portal/portal_sections_five_types.example.json +2 -2
- package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +1 -1
- package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +4 -0
- package/skills/qingflow-cli/reference/record/insert/README.md +3 -0
- package/skills/qingflow-cli/reference/task/QINGFLOW_CLI_TASK_CONTEXT_WORKFLOW.md +2 -0
- package/src/qingflow_mcp/builder_facade/models.py +167 -0
- package/src/qingflow_mcp/builder_facade/service.py +556 -16
- package/src/qingflow_mcp/tools/ai_builder_tools.py +157 -6
|
@@ -49,6 +49,8 @@ from ..builder_facade.models import (
|
|
|
49
49
|
ViewUpsertPatch,
|
|
50
50
|
ViewsPreset,
|
|
51
51
|
ViewsPlanRequest,
|
|
52
|
+
public_view_partial_payload,
|
|
53
|
+
public_view_upsert_payload,
|
|
52
54
|
)
|
|
53
55
|
from ..builder_facade.service import AiBuilderFacade, INTEGRATION_OUTPUT_TARGET_FIELD_TYPES
|
|
54
56
|
from ..solution.compiler.icon_utils import (
|
|
@@ -2018,6 +2020,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2018
2020
|
profile: str,
|
|
2019
2021
|
app_key: str,
|
|
2020
2022
|
upsert_views: list[JSONObject] | None = None,
|
|
2023
|
+
patch_views: list[JSONObject] | None = None,
|
|
2021
2024
|
remove_views: list[str] | None = None,
|
|
2022
2025
|
preset: str | None = None,
|
|
2023
2026
|
) -> JSONObject:
|
|
@@ -2036,6 +2039,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2036
2039
|
{
|
|
2037
2040
|
"app_key": app_key,
|
|
2038
2041
|
"upsert_views": upsert_views or [],
|
|
2042
|
+
"patch_views": patch_views or [],
|
|
2039
2043
|
"remove_views": remove_views or [],
|
|
2040
2044
|
"preset": preset,
|
|
2041
2045
|
}
|
|
@@ -2052,6 +2056,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2052
2056
|
"app_key": app_key,
|
|
2053
2057
|
"preset": "default_table",
|
|
2054
2058
|
"upsert_views": [],
|
|
2059
|
+
"patch_views": [],
|
|
2055
2060
|
"remove_views": [],
|
|
2056
2061
|
},
|
|
2057
2062
|
},
|
|
@@ -2059,8 +2064,24 @@ class AiBuilderTools(ToolBase):
|
|
|
2059
2064
|
return _safe_tool_call(
|
|
2060
2065
|
lambda: self._facade.app_views_plan(profile=profile, request=request),
|
|
2061
2066
|
error_code="VIEWS_PLAN_FAILED",
|
|
2062
|
-
normalized_args=
|
|
2063
|
-
|
|
2067
|
+
normalized_args={
|
|
2068
|
+
"app_key": request.app_key,
|
|
2069
|
+
"upsert_views": [public_view_upsert_payload(view) for view in request.upsert_views],
|
|
2070
|
+
"patch_views": [public_view_partial_payload(patch) for patch in request.patch_views],
|
|
2071
|
+
"remove_views": list(request.remove_views),
|
|
2072
|
+
"preset": request.preset.value if request.preset is not None else None,
|
|
2073
|
+
},
|
|
2074
|
+
suggested_next_call={
|
|
2075
|
+
"tool_name": "app_views_plan",
|
|
2076
|
+
"arguments": {
|
|
2077
|
+
"profile": profile,
|
|
2078
|
+
"app_key": request.app_key,
|
|
2079
|
+
"upsert_views": [public_view_upsert_payload(view) for view in request.upsert_views],
|
|
2080
|
+
"patch_views": [public_view_partial_payload(patch) for patch in request.patch_views],
|
|
2081
|
+
"remove_views": list(request.remove_views),
|
|
2082
|
+
"preset": request.preset.value if request.preset is not None else None,
|
|
2083
|
+
},
|
|
2084
|
+
},
|
|
2064
2085
|
)
|
|
2065
2086
|
|
|
2066
2087
|
@tool_cn_name("应用结构应用")
|
|
@@ -2990,7 +3011,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2990
3011
|
)
|
|
2991
3012
|
if reserved_failure is not None:
|
|
2992
3013
|
return reserved_failure
|
|
2993
|
-
if patch_views:
|
|
3014
|
+
if patch_views or _view_payload_has_action_buttons(upsert_views=upsert_views, patch_views=patch_views):
|
|
2994
3015
|
try:
|
|
2995
3016
|
parsed_views = [ViewUpsertPatch.model_validate(item) for item in (upsert_views or [])]
|
|
2996
3017
|
parsed_patch_views = [ViewPartialPatch.model_validate(item) for item in patch_views]
|
|
@@ -3016,8 +3037,8 @@ class AiBuilderTools(ToolBase):
|
|
|
3016
3037
|
normalized_args = {
|
|
3017
3038
|
"app_key": app_key,
|
|
3018
3039
|
"publish": publish,
|
|
3019
|
-
"upsert_views": [view
|
|
3020
|
-
"patch_views": [patch
|
|
3040
|
+
"upsert_views": [public_view_upsert_payload(view) for view in parsed_views],
|
|
3041
|
+
"patch_views": [public_view_partial_payload(patch) for patch in parsed_patch_views],
|
|
3021
3042
|
"remove_views": list(remove_views or []),
|
|
3022
3043
|
}
|
|
3023
3044
|
return _safe_tool_call(
|
|
@@ -3072,7 +3093,8 @@ class AiBuilderTools(ToolBase):
|
|
|
3072
3093
|
normalized_args = {
|
|
3073
3094
|
"app_key": str(plan_args.get("app_key") or app_key),
|
|
3074
3095
|
"publish": publish,
|
|
3075
|
-
"upsert_views": [view
|
|
3096
|
+
"upsert_views": [public_view_upsert_payload(view) for view in parsed_views],
|
|
3097
|
+
"patch_views": [],
|
|
3076
3098
|
"remove_views": list(plan_args.get("remove_views") or remove_views),
|
|
3077
3099
|
}
|
|
3078
3100
|
return _safe_tool_call(
|
|
@@ -4278,6 +4300,23 @@ def _reserved_system_view_name_failure(
|
|
|
4278
4300
|
return None
|
|
4279
4301
|
|
|
4280
4302
|
|
|
4303
|
+
def _view_payload_has_action_buttons(
|
|
4304
|
+
*,
|
|
4305
|
+
upsert_views: list[JSONObject] | None = None,
|
|
4306
|
+
patch_views: list[JSONObject] | None = None,
|
|
4307
|
+
) -> bool:
|
|
4308
|
+
for item in upsert_views or []:
|
|
4309
|
+
if isinstance(item, dict) and any(key in item for key in ("action_buttons", "actionButtons")):
|
|
4310
|
+
return True
|
|
4311
|
+
for item in patch_views or []:
|
|
4312
|
+
if not isinstance(item, dict):
|
|
4313
|
+
continue
|
|
4314
|
+
raw_set = item.get("set")
|
|
4315
|
+
if isinstance(raw_set, dict) and any(key in raw_set for key in ("action_buttons", "actionButtons")):
|
|
4316
|
+
return True
|
|
4317
|
+
return False
|
|
4318
|
+
|
|
4319
|
+
|
|
4281
4320
|
def _config_failure(
|
|
4282
4321
|
*,
|
|
4283
4322
|
tool_name: str,
|
|
@@ -4986,6 +5025,15 @@ def _builder_view_resources(payload: JSONObject) -> list[JSONObject]:
|
|
|
4986
5025
|
message=message,
|
|
4987
5026
|
)
|
|
4988
5027
|
)
|
|
5028
|
+
details = payload.get("details") if isinstance(payload.get("details"), dict) else {}
|
|
5029
|
+
action_buttons_result = details.get("action_buttons_result") if isinstance(details, dict) else None
|
|
5030
|
+
if isinstance(action_buttons_result, dict):
|
|
5031
|
+
nested_payload = {
|
|
5032
|
+
**action_buttons_result,
|
|
5033
|
+
"app_key": payload.get("app_key"),
|
|
5034
|
+
"app_name": payload.get("app_name"),
|
|
5035
|
+
}
|
|
5036
|
+
resources.extend(_builder_button_resources(nested_payload))
|
|
4989
5037
|
return resources
|
|
4990
5038
|
|
|
4991
5039
|
|
|
@@ -6460,11 +6508,15 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6460
6508
|
"upsert_views[].columns",
|
|
6461
6509
|
"upsert_views[].filters",
|
|
6462
6510
|
"upsert_views[].buttons",
|
|
6511
|
+
"upsert_views[].action_buttons",
|
|
6512
|
+
"upsert_views[].action_buttons_mode",
|
|
6463
6513
|
"upsert_views[].visibility",
|
|
6464
6514
|
"upsert_views[].query_conditions",
|
|
6465
6515
|
"patch_views[].view_key",
|
|
6466
6516
|
"patch_views[].name",
|
|
6467
6517
|
"patch_views[].set",
|
|
6518
|
+
"patch_views[].set.action_buttons",
|
|
6519
|
+
"patch_views[].set.action_buttons_mode",
|
|
6468
6520
|
"patch_views[].unset",
|
|
6469
6521
|
],
|
|
6470
6522
|
"aliases": {
|
|
@@ -6492,6 +6544,14 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6492
6544
|
"buttons[].buttonFormula": "buttons[].button_formula",
|
|
6493
6545
|
"buttons[].buttonFormulaType": "buttons[].button_formula_type",
|
|
6494
6546
|
"buttons[].printTpls": "buttons[].print_tpls",
|
|
6547
|
+
"actionButtons": "action_buttons",
|
|
6548
|
+
"actionButtonsMode": "action_buttons_mode",
|
|
6549
|
+
"action_buttons[].button_text": "action_buttons[].text",
|
|
6550
|
+
"action_buttons[].trigger_action": "action_buttons[].action",
|
|
6551
|
+
"action_buttons[].trigger_link_url": "action_buttons[].url",
|
|
6552
|
+
"action_buttons[].visibleWhen": "action_buttons[].visible_when",
|
|
6553
|
+
"action_buttons[].fieldMappings": "action_buttons[].field_mappings",
|
|
6554
|
+
"action_buttons[].defaultValues": "action_buttons[].default_values",
|
|
6495
6555
|
},
|
|
6496
6556
|
"allowed_values": {
|
|
6497
6557
|
"preset": [member.value for member in ViewsPreset],
|
|
@@ -6499,6 +6559,9 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6499
6559
|
"view.filter.operator": [member.value for member in ViewFilterOperator],
|
|
6500
6560
|
"view.buttons.button_type": ["SYSTEM", "CUSTOM"],
|
|
6501
6561
|
"view.buttons.config_type": ["TOP", "DETAIL", "INSIDE"],
|
|
6562
|
+
"view.action_buttons.action": ["add_data", "link", "qRobot", "wings"],
|
|
6563
|
+
"view.action_buttons.placement": [member.value for member in PublicButtonPlacement],
|
|
6564
|
+
"view.action_buttons_mode": ["merge", "replace"],
|
|
6502
6565
|
**deepcopy(_VISIBILITY_ALLOWED_VALUES),
|
|
6503
6566
|
},
|
|
6504
6567
|
"execution_notes": [
|
|
@@ -6508,6 +6571,9 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6508
6571
|
"upsert_views[].query_conditions.rows is a layout matrix of query-panel supported field names; it is compiled to backend queryCondition queIds",
|
|
6509
6572
|
"do not put relation/attachment/subtable/code_block/q_linker/address fields in query_conditions; use filters for fixed filters or app_associated_resources_apply.match_mappings for current-record relation/report matching",
|
|
6510
6573
|
"use patch_views for partial parameter replacement on existing views; the tool reads current config, merges patch_views[].set/unset, then submits the backend full-save payload internally",
|
|
6574
|
+
"business buttons should be declared with action_buttons on the target view; app_views_apply writes the view first, then compiles action_buttons through the custom button writer and binds them to the resulting view_key",
|
|
6575
|
+
"action_buttons_mode defaults to merge; replace rewrites this view's custom button bindings, and replace plus action_buttons=[] clears this view's custom button bindings without deleting button bodies",
|
|
6576
|
+
"legacy upsert_views[].buttons is a compatibility path for raw full replacement of existing view button config; do not use it as the normal agent path",
|
|
6511
6577
|
"remove_views accepts a raw view_key or an exact unique view name; after DELETE the tool verifies deletion by single view_key readback, not by a full app view list",
|
|
6512
6578
|
"deleted views return verification.by_view[].delete_executed, readback_status, and safe_to_retry_delete=false; if readback is pending, do not blindly repeat the delete",
|
|
6513
6579
|
"do not create business views named 全部数据, 我的数据, 我发起的, 待办, 已办, or 抄送; these are built-in system/default views. Use business-specific names for new views, and pass the existing raw view_key or patch_views when changing a built-in view",
|
|
@@ -6538,6 +6604,27 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6538
6604
|
],
|
|
6539
6605
|
"remove_views": [],
|
|
6540
6606
|
},
|
|
6607
|
+
"action_buttons_example": {
|
|
6608
|
+
"profile": "default",
|
|
6609
|
+
"app_key": "APP_KEY",
|
|
6610
|
+
"upsert_views": [
|
|
6611
|
+
{
|
|
6612
|
+
"name": "生产工单执行视图",
|
|
6613
|
+
"type": "table",
|
|
6614
|
+
"columns": ["工单编号", "产品", "状态", "负责人"],
|
|
6615
|
+
"action_buttons": [
|
|
6616
|
+
{
|
|
6617
|
+
"text": "开始生产",
|
|
6618
|
+
"action": "link",
|
|
6619
|
+
"url": "https://example.com/start",
|
|
6620
|
+
"placement": "list",
|
|
6621
|
+
"visible_when": [{"field_name": "状态", "operator": "eq", "value": "待排产"}],
|
|
6622
|
+
}
|
|
6623
|
+
],
|
|
6624
|
+
}
|
|
6625
|
+
],
|
|
6626
|
+
"remove_views": [],
|
|
6627
|
+
},
|
|
6541
6628
|
"full_upsert_query_conditions_example": {
|
|
6542
6629
|
"profile": "default",
|
|
6543
6630
|
"app_key": "APP_KEY",
|
|
@@ -6595,11 +6682,15 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6595
6682
|
"upsert_views[].columns",
|
|
6596
6683
|
"upsert_views[].filters",
|
|
6597
6684
|
"upsert_views[].buttons",
|
|
6685
|
+
"upsert_views[].action_buttons",
|
|
6686
|
+
"upsert_views[].action_buttons_mode",
|
|
6598
6687
|
"upsert_views[].visibility",
|
|
6599
6688
|
"upsert_views[].query_conditions",
|
|
6600
6689
|
"patch_views[].view_key",
|
|
6601
6690
|
"patch_views[].name",
|
|
6602
6691
|
"patch_views[].set",
|
|
6692
|
+
"patch_views[].set.action_buttons",
|
|
6693
|
+
"patch_views[].set.action_buttons_mode",
|
|
6603
6694
|
"patch_views[].unset",
|
|
6604
6695
|
],
|
|
6605
6696
|
"aliases": {
|
|
@@ -6627,12 +6718,23 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6627
6718
|
"buttons[].buttonFormula": "buttons[].button_formula",
|
|
6628
6719
|
"buttons[].buttonFormulaType": "buttons[].button_formula_type",
|
|
6629
6720
|
"buttons[].printTpls": "buttons[].print_tpls",
|
|
6721
|
+
"actionButtons": "action_buttons",
|
|
6722
|
+
"actionButtonsMode": "action_buttons_mode",
|
|
6723
|
+
"action_buttons[].button_text": "action_buttons[].text",
|
|
6724
|
+
"action_buttons[].trigger_action": "action_buttons[].action",
|
|
6725
|
+
"action_buttons[].trigger_link_url": "action_buttons[].url",
|
|
6726
|
+
"action_buttons[].visibleWhen": "action_buttons[].visible_when",
|
|
6727
|
+
"action_buttons[].fieldMappings": "action_buttons[].field_mappings",
|
|
6728
|
+
"action_buttons[].defaultValues": "action_buttons[].default_values",
|
|
6630
6729
|
},
|
|
6631
6730
|
"allowed_values": {
|
|
6632
6731
|
"view.type": [member.value for member in PublicViewType],
|
|
6633
6732
|
"view.filter.operator": [member.value for member in ViewFilterOperator],
|
|
6634
6733
|
"view.buttons.button_type": ["SYSTEM", "CUSTOM"],
|
|
6635
6734
|
"view.buttons.config_type": ["TOP", "DETAIL", "INSIDE"],
|
|
6735
|
+
"view.action_buttons.action": ["add_data", "link", "qRobot", "wings"],
|
|
6736
|
+
"view.action_buttons.placement": [member.value for member in PublicButtonPlacement],
|
|
6737
|
+
"view.action_buttons_mode": ["merge", "replace"],
|
|
6636
6738
|
**deepcopy(_VISIBILITY_ALLOWED_VALUES),
|
|
6637
6739
|
},
|
|
6638
6740
|
"execution_notes": [
|
|
@@ -6642,6 +6744,10 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6642
6744
|
"read back app_get after any failed or partial view apply",
|
|
6643
6745
|
"view existence verification and saved-filter verification are separate; treat filters as unverified until verification.view_filters_verified is true",
|
|
6644
6746
|
"buttons omitted preserves existing button config; buttons=[] clears all buttons; buttons=[...] replaces the full button config",
|
|
6747
|
+
"business buttons should be declared with action_buttons on the target view; app_views_apply writes the view first, then compiles action_buttons through the custom button writer and binds them to the resulting view_key",
|
|
6748
|
+
"patch_views[].set.action_buttons can add buttons to an existing view without rewriting columns/filters; action_buttons_mode defaults to merge, replace rewrites this view's custom button bindings, and replace plus action_buttons=[] clears bindings without deleting button bodies",
|
|
6749
|
+
"publish=false with action_buttons is blocked as VIEW_ACTION_BUTTONS_REQUIRE_PUBLISH because the underlying custom button writer may publish after successful button writes",
|
|
6750
|
+
"legacy upsert_views[].buttons is a compatibility path for raw full replacement of existing view button config; do not use it as the normal agent path",
|
|
6645
6751
|
"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",
|
|
6646
6752
|
"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",
|
|
6647
6753
|
"upsert_views[].query_conditions.rows is a layout matrix of query-panel supported field names; it is compiled to backend queryCondition queIds",
|
|
@@ -6679,6 +6785,51 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6679
6785
|
],
|
|
6680
6786
|
"remove_views": [],
|
|
6681
6787
|
},
|
|
6788
|
+
"action_buttons_example": {
|
|
6789
|
+
"profile": "default",
|
|
6790
|
+
"app_key": "APP_KEY",
|
|
6791
|
+
"publish": True,
|
|
6792
|
+
"upsert_views": [
|
|
6793
|
+
{
|
|
6794
|
+
"name": "生产工单执行视图",
|
|
6795
|
+
"type": "table",
|
|
6796
|
+
"columns": ["工单编号", "产品", "状态", "负责人"],
|
|
6797
|
+
"action_buttons": [
|
|
6798
|
+
{
|
|
6799
|
+
"text": "开始生产",
|
|
6800
|
+
"action": "link",
|
|
6801
|
+
"url": "https://example.com/start",
|
|
6802
|
+
"placement": "list",
|
|
6803
|
+
"visible_when": [{"field_name": "状态", "operator": "eq", "value": "待排产"}],
|
|
6804
|
+
}
|
|
6805
|
+
],
|
|
6806
|
+
}
|
|
6807
|
+
],
|
|
6808
|
+
"remove_views": [],
|
|
6809
|
+
},
|
|
6810
|
+
"action_buttons_patch_example": {
|
|
6811
|
+
"profile": "default",
|
|
6812
|
+
"app_key": "APP_KEY",
|
|
6813
|
+
"publish": True,
|
|
6814
|
+
"patch_views": [
|
|
6815
|
+
{
|
|
6816
|
+
"view_key": "RAW_VIEW_KEY",
|
|
6817
|
+
"set": {
|
|
6818
|
+
"action_buttons": [
|
|
6819
|
+
{
|
|
6820
|
+
"text": "创建验收单",
|
|
6821
|
+
"action": "add_data",
|
|
6822
|
+
"target_app_key": "ARRIVAL_APP",
|
|
6823
|
+
"field_mappings": [{"source_field": "数据ID", "target_field": "关联工单"}],
|
|
6824
|
+
"default_values": {"状态": "待验收"},
|
|
6825
|
+
"placement": "detail",
|
|
6826
|
+
}
|
|
6827
|
+
]
|
|
6828
|
+
},
|
|
6829
|
+
}
|
|
6830
|
+
],
|
|
6831
|
+
"remove_views": [],
|
|
6832
|
+
},
|
|
6682
6833
|
"full_upsert_query_conditions_example": {
|
|
6683
6834
|
"profile": "default",
|
|
6684
6835
|
"app_key": "APP_KEY",
|