@qingflow-tech/qingflow-cli 1.1.41 → 1.1.43-beta.1
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 +4 -4
- package/package.json +2 -1
- package/pyproject.toml +3 -2
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_TASK_CONTEXT_WORKFLOW.md +1 -1
- package/skills/qingflow-cli/reference/task/QINGFLOW_CLI_TASK_CONTEXT_WORKFLOW.md +1 -1
- package/src/qingflow_mcp/app_form_compat.py +115 -0
- package/src/qingflow_mcp/app_form_validator.py +199 -0
- package/src/qingflow_mcp/builder_facade/app_form.py +2836 -0
- package/src/qingflow_mcp/builder_facade/app_form_schema.py +269 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/manifest.json +37 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/complete.json +1766 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/address.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/amount.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/attachment.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/code_block.json +223 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/data_relation.json +538 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/date.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/datetime.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/department.json +149 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/email.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/link.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/long_text.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/member.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/multi_select.json +92 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/number.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/phone.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/q_linker.json +338 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/relation.json +137 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_choice.json +92 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_select.json +92 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/subtable.json +810 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/text.json +76 -0
- package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/summary.json +713 -0
- package/src/qingflow_mcp/builder_facade/service.py +5 -2
- package/src/qingflow_mcp/cli/commands/builder.py +91 -28
- package/src/qingflow_mcp/cli/json_io.py +21 -2
- package/src/qingflow_mcp/cli/main.py +3 -39
- package/src/qingflow_mcp/cloud_auth.py +11 -0
- package/src/qingflow_mcp/cloud_context.py +5 -0
- package/src/qingflow_mcp/cloud_oauth_proxy.py +453 -0
- package/src/qingflow_mcp/cloud_redis.py +25 -0
- package/src/qingflow_mcp/config.py +44 -0
- package/src/qingflow_mcp/public_surface.py +5 -2
- package/src/qingflow_mcp/response_trim.py +8 -0
- package/src/qingflow_mcp/server_app_builder.py +38 -86
- package/src/qingflow_mcp/server_app_user.py +2 -1
- package/src/qingflow_mcp/server_cloud.py +245 -22
- package/src/qingflow_mcp/tools/ai_builder_tools.py +93 -100
- package/src/qingflow_mcp/tools/app_tools.py +46 -65
- package/src/qingflow_mcp/tools/base.py +2 -1
- package/src/qingflow_mcp/tools/task_context_tools.py +6 -0
|
@@ -14,6 +14,8 @@ from ..builder_facade.button_style_catalog import (
|
|
|
14
14
|
BUTTON_STYLE_PRESETS,
|
|
15
15
|
BUTTON_TEXT_COLORS,
|
|
16
16
|
)
|
|
17
|
+
from ..builder_facade.app_form import AppFormReconciler
|
|
18
|
+
from ..builder_facade.app_form_schema import app_form_schema_registry
|
|
17
19
|
from ..public_surface import public_builder_contract_tool_names
|
|
18
20
|
from ..config import DEFAULT_PROFILE
|
|
19
21
|
from ..errors import QingflowApiError, backend_code_int, backend_code_value_int
|
|
@@ -130,10 +132,14 @@ def _inline_form_layout_was_handled(payload: JSONObject) -> bool:
|
|
|
130
132
|
|
|
131
133
|
PUBLIC_STABLE_FLOW_NODE_TYPES = ["start", "approve", "fill", "copy", "webhook", "end"]
|
|
132
134
|
BUILDER_APPLY_SCHEMA_VERSION = "builder.apply.v1"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
# TODO(deprecation): Remove these names and their imperative adapters after internal AppForm migration completes.
|
|
136
|
+
LEGACY_IMPERATIVE_APP_FORM_TOOL_NAMES = {
|
|
135
137
|
"app_schema_apply",
|
|
136
138
|
"app_layout_apply",
|
|
139
|
+
}
|
|
140
|
+
BUILDER_APPLY_TOOL_NAMES = {
|
|
141
|
+
"package_apply",
|
|
142
|
+
*LEGACY_IMPERATIVE_APP_FORM_TOOL_NAMES,
|
|
137
143
|
"app_flow_apply",
|
|
138
144
|
"app_views_apply",
|
|
139
145
|
"app_custom_buttons_apply",
|
|
@@ -161,10 +167,12 @@ class AiBuilderTools(ToolBase):
|
|
|
161
167
|
def __init__(self, sessions, backend) -> None:
|
|
162
168
|
"""执行内部辅助逻辑。"""
|
|
163
169
|
super().__init__(sessions, backend)
|
|
170
|
+
apps = AppTools(sessions, backend)
|
|
171
|
+
packages = PackageTools(sessions, backend)
|
|
164
172
|
self._facade = AiBuilderFacade(
|
|
165
|
-
apps=
|
|
173
|
+
apps=apps,
|
|
166
174
|
buttons=CustomButtonTools(sessions, backend),
|
|
167
|
-
packages=
|
|
175
|
+
packages=packages,
|
|
168
176
|
views=ViewTools(sessions, backend),
|
|
169
177
|
workflows=WorkflowTools(sessions, backend),
|
|
170
178
|
portals=PortalTools(sessions, backend),
|
|
@@ -173,6 +181,11 @@ class AiBuilderTools(ToolBase):
|
|
|
173
181
|
directory=DirectoryTools(sessions, backend),
|
|
174
182
|
solutions=SolutionTools(sessions, backend),
|
|
175
183
|
)
|
|
184
|
+
self._app_form = AppFormReconciler(
|
|
185
|
+
apps=apps,
|
|
186
|
+
packages=packages,
|
|
187
|
+
registry=app_form_schema_registry(),
|
|
188
|
+
)
|
|
176
189
|
|
|
177
190
|
def _apply_app_batch(self, *, tool_name: str, profile: str, apps: list[JSONObject], apply_one) -> JSONObject:
|
|
178
191
|
started_at = time.perf_counter()
|
|
@@ -367,6 +380,41 @@ class AiBuilderTools(ToolBase):
|
|
|
367
380
|
def builder_tool_contract(tool_name: str = "") -> JSONObject:
|
|
368
381
|
return self.builder_tool_contract(tool_name=tool_name)
|
|
369
382
|
|
|
383
|
+
@mcp.tool()
|
|
384
|
+
def app_form_schema(
|
|
385
|
+
schema_version: str | None = None,
|
|
386
|
+
field_type: str | None = None,
|
|
387
|
+
) -> JSONObject:
|
|
388
|
+
return self.app_form_schema(schema_version=schema_version, field_type=field_type)
|
|
389
|
+
|
|
390
|
+
@mcp.tool()
|
|
391
|
+
def app_form_get(
|
|
392
|
+
profile: str = DEFAULT_PROFILE,
|
|
393
|
+
app_key: str = "",
|
|
394
|
+
schema_version: str | None = None,
|
|
395
|
+
being_draft: bool = False,
|
|
396
|
+
) -> JSONObject:
|
|
397
|
+
return self.app_form_get(
|
|
398
|
+
profile=profile,
|
|
399
|
+
app_key=app_key,
|
|
400
|
+
schema_version=schema_version,
|
|
401
|
+
being_draft=being_draft,
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
@mcp.tool()
|
|
405
|
+
def app_form_apply(
|
|
406
|
+
profile: str = DEFAULT_PROFILE,
|
|
407
|
+
spec: JSONObject | None = None,
|
|
408
|
+
) -> JSONObject:
|
|
409
|
+
return self.app_form_apply(profile=profile, spec=spec or {})
|
|
410
|
+
|
|
411
|
+
@mcp.tool(description=self._high_risk_tool_description(operation="delete", target="app configuration"))
|
|
412
|
+
def app_delete(
|
|
413
|
+
profile: str = DEFAULT_PROFILE,
|
|
414
|
+
app_key: str = "",
|
|
415
|
+
) -> JSONObject:
|
|
416
|
+
return self.app_delete(profile=profile, app_key=app_key)
|
|
417
|
+
|
|
370
418
|
@mcp.tool()
|
|
371
419
|
def workspace_icon_catalog_get(profile: str = DEFAULT_PROFILE) -> JSONObject:
|
|
372
420
|
return self.workspace_icon_catalog_get(profile=profile)
|
|
@@ -612,98 +660,6 @@ class AiBuilderTools(ToolBase):
|
|
|
612
660
|
) -> JSONObject:
|
|
613
661
|
return self.chart_get(profile=profile, chart_id=chart_id)
|
|
614
662
|
|
|
615
|
-
@mcp.tool()
|
|
616
|
-
def app_schema_apply(
|
|
617
|
-
profile: str = DEFAULT_PROFILE,
|
|
618
|
-
app_key: str = "",
|
|
619
|
-
package_id: int | None = None,
|
|
620
|
-
app_name: str = "",
|
|
621
|
-
app_title: str = "",
|
|
622
|
-
icon: str | JSONObject = "",
|
|
623
|
-
color: str = "",
|
|
624
|
-
icon_name: str | None = None,
|
|
625
|
-
icon_color: str | None = None,
|
|
626
|
-
icon_config: JSONObject | None = None,
|
|
627
|
-
visibility: JSONObject | None = None,
|
|
628
|
-
publish: bool = True,
|
|
629
|
-
form: list[JSONObject] | None = None,
|
|
630
|
-
add_fields: list[JSONObject] | None = None,
|
|
631
|
-
update_fields: list[JSONObject] | None = None,
|
|
632
|
-
remove_fields: list[JSONObject] | None = None,
|
|
633
|
-
apps: list[JSONObject] | None = None,
|
|
634
|
-
) -> JSONObject:
|
|
635
|
-
if apps is not None:
|
|
636
|
-
if app_key or app_name or app_title or form or add_fields or update_fields or remove_fields:
|
|
637
|
-
return _config_failure(
|
|
638
|
-
tool_name="app_schema_apply",
|
|
639
|
-
message="app_schema_apply multi-app mode accepts package_id plus apps only.",
|
|
640
|
-
fix_hint="Put per-app form in apps[].form when using batch mode.",
|
|
641
|
-
)
|
|
642
|
-
if package_id is None:
|
|
643
|
-
return _config_failure(
|
|
644
|
-
tool_name="app_schema_apply",
|
|
645
|
-
message="app_schema_apply multi-app mode requires package_id.",
|
|
646
|
-
fix_hint="Pass package_id and apps[].app_name for new apps, or apps[].app_key for existing apps.",
|
|
647
|
-
)
|
|
648
|
-
return self.app_schema_apply(
|
|
649
|
-
profile=profile,
|
|
650
|
-
package_id=package_id,
|
|
651
|
-
visibility=visibility,
|
|
652
|
-
publish=publish,
|
|
653
|
-
apps=apps,
|
|
654
|
-
form=None,
|
|
655
|
-
add_fields=[],
|
|
656
|
-
update_fields=[],
|
|
657
|
-
remove_fields=[],
|
|
658
|
-
)
|
|
659
|
-
has_app_key = bool((app_key or "").strip())
|
|
660
|
-
has_app_name = bool((app_name or "").strip())
|
|
661
|
-
has_app_title = bool((app_title or "").strip())
|
|
662
|
-
has_package_id = package_id is not None
|
|
663
|
-
if has_app_key:
|
|
664
|
-
if has_package_id:
|
|
665
|
-
return _config_failure(
|
|
666
|
-
tool_name="app_schema_apply",
|
|
667
|
-
message="app_schema_apply edit mode accepts app_key and optional app_name rename only.",
|
|
668
|
-
fix_hint="For existing apps, use `app_key` and optionally `app_name`. For create mode, use `package_id + app_name`.",
|
|
669
|
-
)
|
|
670
|
-
elif not (has_package_id and (has_app_name or has_app_title)):
|
|
671
|
-
return _config_failure(
|
|
672
|
-
tool_name="app_schema_apply",
|
|
673
|
-
message="app_schema_apply create mode requires package_id and app_name.",
|
|
674
|
-
fix_hint="Use `app_key` for existing apps, or pass `package_id + app_name` to create a new app.",
|
|
675
|
-
)
|
|
676
|
-
return self.app_schema_apply(
|
|
677
|
-
profile=profile,
|
|
678
|
-
app_key=app_key,
|
|
679
|
-
package_id=package_id,
|
|
680
|
-
app_name=app_name,
|
|
681
|
-
app_title=app_title,
|
|
682
|
-
icon=icon,
|
|
683
|
-
color=color,
|
|
684
|
-
icon_name=icon_name,
|
|
685
|
-
icon_color=icon_color,
|
|
686
|
-
icon_config=icon_config,
|
|
687
|
-
visibility=visibility,
|
|
688
|
-
publish=publish,
|
|
689
|
-
form=form or [],
|
|
690
|
-
add_fields=add_fields or [],
|
|
691
|
-
update_fields=update_fields or [],
|
|
692
|
-
remove_fields=remove_fields or [],
|
|
693
|
-
apps=None,
|
|
694
|
-
)
|
|
695
|
-
|
|
696
|
-
@mcp.tool()
|
|
697
|
-
def app_layout_apply(
|
|
698
|
-
profile: str = DEFAULT_PROFILE,
|
|
699
|
-
app_key: str = "",
|
|
700
|
-
mode: str = "merge",
|
|
701
|
-
publish: bool = True,
|
|
702
|
-
sections: list[JSONObject] | None = None,
|
|
703
|
-
apps: list[JSONObject] | None = None,
|
|
704
|
-
) -> JSONObject:
|
|
705
|
-
return self.app_layout_apply(profile=profile, app_key=app_key, mode=mode, publish=publish, sections=sections or [], apps=apps)
|
|
706
|
-
|
|
707
663
|
@mcp.tool()
|
|
708
664
|
def app_flow_get(
|
|
709
665
|
profile: str = DEFAULT_PROFILE,
|
|
@@ -857,6 +813,39 @@ class AiBuilderTools(ToolBase):
|
|
|
857
813
|
expected_package_id=expected_package_id,
|
|
858
814
|
)
|
|
859
815
|
|
|
816
|
+
def app_form_schema(
|
|
817
|
+
self,
|
|
818
|
+
*,
|
|
819
|
+
schema_version: str | None = None,
|
|
820
|
+
field_type: str | None = None,
|
|
821
|
+
) -> JSONObject:
|
|
822
|
+
"""Return the versioned AppForm summary or one field-type schema."""
|
|
823
|
+
return self._app_form.schema(schema_version=schema_version, field_type=field_type)
|
|
824
|
+
|
|
825
|
+
def app_form_get(
|
|
826
|
+
self,
|
|
827
|
+
*,
|
|
828
|
+
profile: str,
|
|
829
|
+
app_key: str,
|
|
830
|
+
schema_version: str | None = None,
|
|
831
|
+
being_draft: bool = False,
|
|
832
|
+
) -> JSONObject:
|
|
833
|
+
"""Read a canonical draft or published AppForm resource."""
|
|
834
|
+
return self._app_form.get(
|
|
835
|
+
profile=profile,
|
|
836
|
+
app_key=app_key,
|
|
837
|
+
schema_version=schema_version,
|
|
838
|
+
being_draft=being_draft,
|
|
839
|
+
)
|
|
840
|
+
|
|
841
|
+
def app_form_apply(self, *, profile: str, spec: JSONObject) -> JSONObject:
|
|
842
|
+
"""Reconcile one complete declarative AppForm target."""
|
|
843
|
+
return self._app_form.apply(profile=profile, spec=spec)
|
|
844
|
+
|
|
845
|
+
def app_delete(self, *, profile: str, app_key: str) -> JSONObject:
|
|
846
|
+
"""Delete an application explicitly."""
|
|
847
|
+
return self._app_form.delete(profile=profile, app_key=app_key)
|
|
848
|
+
|
|
860
849
|
def package_list(self, *, profile: str, trial_status: str = "all", query: str = "") -> JSONObject:
|
|
861
850
|
"""执行分组与包相关逻辑。"""
|
|
862
851
|
normalized_args = {"trial_status": trial_status, "query": query}
|
|
@@ -2092,7 +2081,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2092
2081
|
remove_fields: list[JSONObject],
|
|
2093
2082
|
apps: list[JSONObject] | None = None,
|
|
2094
2083
|
) -> JSONObject:
|
|
2095
|
-
"""
|
|
2084
|
+
"""Legacy imperative schema adapter retained only for internal callers pending deletion."""
|
|
2096
2085
|
icon, color = _normalize_builder_icon_args(
|
|
2097
2086
|
icon=icon,
|
|
2098
2087
|
color=color,
|
|
@@ -3435,7 +3424,7 @@ class AiBuilderTools(ToolBase):
|
|
|
3435
3424
|
sections: list[JSONObject],
|
|
3436
3425
|
apps: list[JSONObject] | None = None,
|
|
3437
3426
|
) -> JSONObject:
|
|
3438
|
-
"""
|
|
3427
|
+
"""Legacy imperative layout adapter retained only for internal callers pending deletion."""
|
|
3439
3428
|
if apps is not None:
|
|
3440
3429
|
return self._apply_app_batch(
|
|
3441
3430
|
tool_name="app_layout_apply",
|
|
@@ -7282,6 +7271,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
7282
7271
|
"remove_fields": [],
|
|
7283
7272
|
},
|
|
7284
7273
|
},
|
|
7274
|
+
# TODO(deprecation): Retained only for internal imperative adapter validation. This contract
|
|
7275
|
+
# is deliberately excluded from builder_tool_contract and must be deleted with the adapter.
|
|
7285
7276
|
"app_schema_apply": {
|
|
7286
7277
|
"allowed_keys": [
|
|
7287
7278
|
"app_key",
|
|
@@ -7638,6 +7629,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
7638
7629
|
},
|
|
7639
7630
|
"preset_example": {"profile": "default", "app_key": "APP_KEY", "mode": "merge", "preset": "balanced", "sections": []},
|
|
7640
7631
|
},
|
|
7632
|
+
# TODO(deprecation): Retained only for internal imperative adapter validation. This contract
|
|
7633
|
+
# is deliberately excluded from builder_tool_contract and must be deleted with the adapter.
|
|
7641
7634
|
"app_layout_apply": {
|
|
7642
7635
|
"allowed_keys": ["app_key", "mode", "publish", "sections"],
|
|
7643
7636
|
"aliases": {"overwrite": "replace", "sectionId": "section_id"},
|
|
@@ -8172,7 +8165,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
8172
8165
|
"allowed_values": {},
|
|
8173
8166
|
"execution_notes": [
|
|
8174
8167
|
"returns compact current field configuration for one app",
|
|
8175
|
-
"use
|
|
8168
|
+
"use app_form_get through the qingflow-app-form Skill for editable form definitions",
|
|
8176
8169
|
"also returns chart_fields from QingBI datasource fields; app_charts_apply field selectors should use chart_fields because record/schema-visible fields and QingBI fields are not the same schema",
|
|
8177
8170
|
"chart_fields[].field_id supports field_<queId> selectors, while chart_fields[].bi_field_id is the raw QingBI fieldId accepted by report configs",
|
|
8178
8171
|
"chart_fields[].chart_apply_examples contains copyable semantic app_charts_apply snippets such as count_by_field, filtered_count, and numeric sum_metric",
|
|
@@ -8189,7 +8182,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
8189
8182
|
"allowed_values": {},
|
|
8190
8183
|
"execution_notes": [
|
|
8191
8184
|
"returns compact current layout configuration for one app",
|
|
8192
|
-
"use
|
|
8185
|
+
"use app_form_get through the qingflow-app-form Skill for editable form layout",
|
|
8193
8186
|
],
|
|
8194
8187
|
"minimal_example": {
|
|
8195
8188
|
"profile": "default",
|
|
@@ -20,8 +20,11 @@ class AppTools(ToolBase):
|
|
|
20
20
|
类型:应用元数据与配置工具。
|
|
21
21
|
主要职责:
|
|
22
22
|
1. 查询应用列表、读取应用详情;
|
|
23
|
-
2.
|
|
24
|
-
3.
|
|
23
|
+
2. 为声明式 AppForm 和 Solution 编排保留底层应用适配器;
|
|
24
|
+
3. 仅将应用列表与详情注册为本类的 MCP 入口。
|
|
25
|
+
|
|
26
|
+
TODO(deprecation): Remove the imperative app-form adapters after AppForm and Solution
|
|
27
|
+
no longer call them. They are implementation details and must not be registered as MCP tools.
|
|
25
28
|
"""
|
|
26
29
|
|
|
27
30
|
def register(self, mcp: FastMCP) -> None:
|
|
@@ -34,58 +37,6 @@ class AppTools(ToolBase):
|
|
|
34
37
|
def app_get(profile: str = DEFAULT_PROFILE, app_key: str = "") -> JSONObject:
|
|
35
38
|
return self.app_get(profile=profile, app_key=app_key)
|
|
36
39
|
|
|
37
|
-
@mcp.tool()
|
|
38
|
-
def app_get_base(profile: str = DEFAULT_PROFILE, app_key: str = "", include_raw: bool = False) -> JSONObject:
|
|
39
|
-
return self.app_get_base(profile=profile, app_key=app_key, include_raw=include_raw)
|
|
40
|
-
|
|
41
|
-
@mcp.tool(description=self._high_risk_tool_description(operation="update", target="app base settings"))
|
|
42
|
-
def app_update_base(profile: str = DEFAULT_PROFILE, app_key: str = "", payload: JSONObject | None = None) -> JSONObject:
|
|
43
|
-
return self.app_update_base(profile=profile, app_key=app_key, payload=payload or {})
|
|
44
|
-
|
|
45
|
-
@mcp.tool()
|
|
46
|
-
def app_get_form_schema(
|
|
47
|
-
profile: str = DEFAULT_PROFILE,
|
|
48
|
-
app_key: str = "",
|
|
49
|
-
form_type: int | str = 1,
|
|
50
|
-
being_draft: bool | None = None,
|
|
51
|
-
being_apply: bool | None = None,
|
|
52
|
-
audit_node_id: int | None = None,
|
|
53
|
-
include_raw: bool = False,
|
|
54
|
-
) -> JSONObject:
|
|
55
|
-
return self.app_get_form_schema(
|
|
56
|
-
profile=profile,
|
|
57
|
-
app_key=app_key,
|
|
58
|
-
form_type=form_type,
|
|
59
|
-
being_draft=being_draft,
|
|
60
|
-
being_apply=being_apply,
|
|
61
|
-
audit_node_id=audit_node_id,
|
|
62
|
-
include_raw=include_raw,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
@mcp.tool()
|
|
66
|
-
def app_get_edit_version_no(profile: str = DEFAULT_PROFILE, app_key: str = "") -> JSONObject:
|
|
67
|
-
return self.app_get_edit_version_no(profile=profile, app_key=app_key)
|
|
68
|
-
|
|
69
|
-
@mcp.tool()
|
|
70
|
-
def app_edit_finished(profile: str = DEFAULT_PROFILE, app_key: str = "", payload: JSONObject | None = None) -> JSONObject:
|
|
71
|
-
return self.app_edit_finished(profile=profile, app_key=app_key, payload=payload or {})
|
|
72
|
-
|
|
73
|
-
@mcp.tool()
|
|
74
|
-
def app_create(profile: str = DEFAULT_PROFILE, payload: JSONObject | None = None) -> JSONObject:
|
|
75
|
-
return self.app_create(profile=profile, payload=payload or {})
|
|
76
|
-
|
|
77
|
-
@mcp.tool(description=self._high_risk_tool_description(operation="delete", target="app configuration"))
|
|
78
|
-
def app_delete(profile: str = DEFAULT_PROFILE, app_key: str = "") -> JSONObject:
|
|
79
|
-
return self.app_delete(profile=profile, app_key=app_key)
|
|
80
|
-
|
|
81
|
-
@mcp.tool()
|
|
82
|
-
def app_publish(
|
|
83
|
-
profile: str = DEFAULT_PROFILE,
|
|
84
|
-
app_key: str = "",
|
|
85
|
-
payload: JSONObject | None = None,
|
|
86
|
-
) -> JSONObject:
|
|
87
|
-
return self.app_publish(profile=profile, app_key=app_key, payload=payload or {})
|
|
88
|
-
|
|
89
40
|
def app_list(self, *, profile: str, query: str = "", keyword: str = "", ship_auth: bool = False) -> JSONObject:
|
|
90
41
|
"""List current-user visible apps in the selected workspace."""
|
|
91
42
|
def runner(session_profile, context):
|
|
@@ -294,7 +245,7 @@ class AppTools(ToolBase):
|
|
|
294
245
|
return self._run(profile, runner, tool_name='应用详情')
|
|
295
246
|
|
|
296
247
|
def app_get_base(self, *, profile: str, app_key: str, include_raw: bool = False) -> JSONObject:
|
|
297
|
-
"""
|
|
248
|
+
"""Legacy low-level app-form adapter retained for internal callers pending deletion."""
|
|
298
249
|
self._require_app_key(app_key)
|
|
299
250
|
|
|
300
251
|
def runner(session_profile, context):
|
|
@@ -343,7 +294,7 @@ class AppTools(ToolBase):
|
|
|
343
294
|
return self._run(profile, runner, tool_name='应用基础信息')
|
|
344
295
|
|
|
345
296
|
def app_update_base(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
|
|
346
|
-
"""
|
|
297
|
+
"""Legacy low-level app-form adapter retained for internal callers pending deletion."""
|
|
347
298
|
self._require_app_key(app_key)
|
|
348
299
|
body = self._require_dict(payload)
|
|
349
300
|
|
|
@@ -368,7 +319,7 @@ class AppTools(ToolBase):
|
|
|
368
319
|
audit_node_id: int | None,
|
|
369
320
|
include_raw: bool = False,
|
|
370
321
|
) -> JSONObject:
|
|
371
|
-
"""
|
|
322
|
+
"""Legacy low-level app-form adapter retained for internal callers pending deletion."""
|
|
372
323
|
self._require_app_key(app_key)
|
|
373
324
|
resolved_form_type = _normalize_form_type(form_type)
|
|
374
325
|
|
|
@@ -398,7 +349,7 @@ class AppTools(ToolBase):
|
|
|
398
349
|
return self._run(profile, runner, tool_name='应用表单结构')
|
|
399
350
|
|
|
400
351
|
def app_get_edit_version_no(self, *, profile: str, app_key: str) -> JSONObject:
|
|
401
|
-
"""
|
|
352
|
+
"""Legacy low-level app-form adapter retained for internal callers pending deletion."""
|
|
402
353
|
self._require_app_key(app_key)
|
|
403
354
|
|
|
404
355
|
def runner(session_profile, context):
|
|
@@ -446,7 +397,7 @@ class AppTools(ToolBase):
|
|
|
446
397
|
return self._run(profile, runner, tool_name='更新应用流程配置')
|
|
447
398
|
|
|
448
399
|
def app_update_form_schema(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
|
|
449
|
-
"""
|
|
400
|
+
"""Legacy low-level app-form adapter retained for internal callers pending deletion."""
|
|
450
401
|
self._require_app_key(app_key)
|
|
451
402
|
body = self._require_dict(payload)
|
|
452
403
|
|
|
@@ -461,7 +412,7 @@ class AppTools(ToolBase):
|
|
|
461
412
|
return self._run(profile, runner, tool_name='更新应用表单结构')
|
|
462
413
|
|
|
463
414
|
def app_edit_finished(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
|
|
464
|
-
"""
|
|
415
|
+
"""Legacy low-level app-form adapter retained for internal callers pending deletion."""
|
|
465
416
|
self._require_app_key(app_key)
|
|
466
417
|
body = self._require_dict(payload)
|
|
467
418
|
|
|
@@ -471,13 +422,19 @@ class AppTools(ToolBase):
|
|
|
471
422
|
|
|
472
423
|
return self._run(profile, runner, tool_name='应用编辑完成')
|
|
473
424
|
|
|
474
|
-
def app_create(
|
|
475
|
-
|
|
425
|
+
def app_create(
|
|
426
|
+
self,
|
|
427
|
+
*,
|
|
428
|
+
profile: str,
|
|
429
|
+
payload: JSONObject,
|
|
430
|
+
retry_without_qf_version: bool = True,
|
|
431
|
+
) -> JSONObject:
|
|
432
|
+
"""Legacy low-level app-form adapter retained for internal callers pending deletion."""
|
|
476
433
|
body = self._require_dict(payload)
|
|
477
434
|
|
|
478
435
|
def runner(session_profile, context):
|
|
479
436
|
attempted_contexts = [context]
|
|
480
|
-
if context.qf_version is not None:
|
|
437
|
+
if retry_without_qf_version and context.qf_version is not None:
|
|
481
438
|
attempted_contexts.append(
|
|
482
439
|
BackendRequestContext(
|
|
483
440
|
base_url=context.base_url,
|
|
@@ -519,7 +476,7 @@ class AppTools(ToolBase):
|
|
|
519
476
|
return self._run(profile, runner, tool_name='创建应用')
|
|
520
477
|
|
|
521
478
|
def app_delete(self, *, profile: str, app_key: str) -> JSONObject:
|
|
522
|
-
"""
|
|
479
|
+
"""Legacy low-level app-form adapter retained for the declarative delete path pending deletion."""
|
|
523
480
|
self._require_app_key(app_key)
|
|
524
481
|
|
|
525
482
|
def runner(session_profile, context):
|
|
@@ -533,7 +490,7 @@ class AppTools(ToolBase):
|
|
|
533
490
|
return self._run(profile, runner, tool_name='删除应用')
|
|
534
491
|
|
|
535
492
|
def app_publish(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
|
|
536
|
-
"""
|
|
493
|
+
"""Legacy low-level app-form adapter retained for internal callers pending deletion."""
|
|
537
494
|
self._require_app_key(app_key)
|
|
538
495
|
body = self._require_dict(payload)
|
|
539
496
|
|
|
@@ -543,6 +500,30 @@ class AppTools(ToolBase):
|
|
|
543
500
|
|
|
544
501
|
return self._run(profile, runner, tool_name='发布应用')
|
|
545
502
|
|
|
503
|
+
def app_publish_raw(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
|
|
504
|
+
"""Legacy low-level publish adapter retained for internal callers pending deletion."""
|
|
505
|
+
self._require_app_key(app_key)
|
|
506
|
+
body = self._require_dict(payload)
|
|
507
|
+
|
|
508
|
+
def runner(session_profile, context):
|
|
509
|
+
response = self.backend.request_with_meta(
|
|
510
|
+
"POST",
|
|
511
|
+
context,
|
|
512
|
+
f"/app/{app_key}/publish",
|
|
513
|
+
json_body=body,
|
|
514
|
+
unwrap=False,
|
|
515
|
+
)
|
|
516
|
+
return {
|
|
517
|
+
"profile": profile,
|
|
518
|
+
"ws_id": session_profile.selected_ws_id,
|
|
519
|
+
"app_key": app_key,
|
|
520
|
+
"http_status": response.http_status,
|
|
521
|
+
"request_id": response.request_id,
|
|
522
|
+
"response": response.data,
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return self._run(profile, runner, tool_name='发布应用')
|
|
526
|
+
|
|
546
527
|
def _require_app_key(self, app_key: str) -> None:
|
|
547
528
|
"""执行内部辅助逻辑。"""
|
|
548
529
|
if not app_key:
|
|
@@ -5,7 +5,7 @@ from contextvars import ContextVar
|
|
|
5
5
|
from typing import Any, Callable, TypeVar
|
|
6
6
|
|
|
7
7
|
from ..backend_client import BackendRequestContext, BackendClient
|
|
8
|
-
from ..cloud_context import current_cloud_context
|
|
8
|
+
from ..cloud_context import current_call_platform, current_cloud_context
|
|
9
9
|
from ..config import (
|
|
10
10
|
get_credit_meter_enabled,
|
|
11
11
|
get_credit_usage_base_url,
|
|
@@ -323,6 +323,7 @@ class ToolBase:
|
|
|
323
323
|
"scene": "MCP",
|
|
324
324
|
"aiBiz": "MCP",
|
|
325
325
|
"extraInfo": tool_name,
|
|
326
|
+
"callPlatform": current_call_platform.get(),
|
|
326
327
|
},
|
|
327
328
|
)
|
|
328
329
|
|
|
@@ -535,6 +535,10 @@ class TaskContextTools(ToolBase):
|
|
|
535
535
|
task_context=task_context,
|
|
536
536
|
fields=field_updates,
|
|
537
537
|
)
|
|
538
|
+
elif normalized_action == "transfer" and body.get("answers") is None:
|
|
539
|
+
record = task_context.get("record") if isinstance(task_context.get("record"), dict) else {}
|
|
540
|
+
current_answers = record.get("answers") if isinstance(record.get("answers"), list) else []
|
|
541
|
+
prepared_fields = {"merged_answers": current_answers}
|
|
538
542
|
before_apply_status = ((task_context.get("record") or {}).get("apply_status"))
|
|
539
543
|
runtime_baseline = None
|
|
540
544
|
if normalized_action != "save_only":
|
|
@@ -704,6 +708,8 @@ class TaskContextTools(ToolBase):
|
|
|
704
708
|
action_payload["auditFeedback"] = audit_feedback
|
|
705
709
|
if merged_answers is not None:
|
|
706
710
|
action_payload["answers"] = merged_answers
|
|
711
|
+
elif payload.get("answers") is not None:
|
|
712
|
+
action_payload["answers"] = payload["answers"]
|
|
707
713
|
return self._approval_tools.record_transfer(
|
|
708
714
|
profile=profile,
|
|
709
715
|
app_key=app_key,
|