@qingflow-tech/qingflow-cli 1.1.48-beta.5 → 1.1.49
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/npm/lib/runtime.mjs +13 -29
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/skills/qingflow-cli/SKILL.md +410 -91
- package/skills/qingflow-cli/manifest.yaml +1 -1
- package/skills/qingflow-cli/reference/00-INDEX.md +4 -4
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +137 -3
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_EXPLORATION_REPORT.md +4 -6
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_FIELD_DATA_TYPES.md +14 -14
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +19 -20
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +14 -18
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +12 -7
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +1 -2
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +95 -76
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md +4 -6
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +13 -13
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +19 -20
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +14 -18
- package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +1 -2
- package/skills/qingflow-cli/reference/record/analysis/README.md +113 -21
- package/skills/qingflow-cli/reference/record/analysis/analysis-gotchas.md +10 -10
- package/skills/qingflow-cli/reference/record/analysis/analysis-patterns.md +9 -9
- package/skills/qingflow-cli/reference/record/analysis/business-context.md +1 -1
- package/skills/qingflow-cli/reference/record/analysis/confidence-reporting.md +10 -10
- package/skills/qingflow-cli/reference/record/analysis/data-access-playbook.md +80 -52
- package/skills/qingflow-cli/reference/record/analysis/pandas-recipes.md +2 -2
- package/skills/qingflow-common/SKILL.md +17 -10
- package/src/qingflow_mcp/builder_facade/service.py +1 -119
- package/src/qingflow_mcp/cli/commands/__init__.py +1 -2
- package/src/qingflow_mcp/cli/commands/auth.py +1 -1
- package/src/qingflow_mcp/cli/commands/record.py +1 -1
- package/src/qingflow_mcp/cli/context.py +1 -4
- package/src/qingflow_mcp/cli/formatters.py +4 -159
- package/src/qingflow_mcp/cli/main.py +1 -4
- package/src/qingflow_mcp/public_surface.py +0 -6
- package/src/qingflow_mcp/response_trim.py +3 -3
- package/src/qingflow_mcp/server.py +0 -2
- package/src/qingflow_mcp/server_app_builder.py +0 -16
- package/src/qingflow_mcp/server_app_user.py +3 -10
- package/src/qingflow_mcp/tools/ai_builder_tools.py +39 -208
- package/src/qingflow_mcp/tools/app_tools.py +13 -52
- package/src/qingflow_mcp/tools/login_link_tools.py +6 -34
- package/src/qingflow_mcp/tools/record_tools.py +46 -11
- package/src/qingflow_mcp/tools/resource_read_tools.py +0 -13
- package/skills/qingflow-cli/reference/data/README.md +0 -32
- package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_LEGACY_RECORD_RETRIEVAL_WORKFLOW.md +0 -50
- package/src/qingflow_mcp/cli/commands/data.py +0 -134
- package/src/qingflow_mcp/resource_uri.py +0 -241
- package/src/qingflow_mcp/tools/csv_export.py +0 -168
- package/src/qingflow_mcp/tools/data_tools.py +0 -271
|
@@ -10,7 +10,6 @@ from .config import DEFAULT_PROFILE
|
|
|
10
10
|
from .response_trim import USER_SERVER_METHOD_MAP, trim_error_response, trim_public_response, wrap_trimmed_methods
|
|
11
11
|
from .session_store import SessionStore
|
|
12
12
|
from .tools.app_tools import AppTools
|
|
13
|
-
from .tools.data_tools import DataTools
|
|
14
13
|
from .tools.auth_tools import AuthTools
|
|
15
14
|
from .tools.code_block_tools import CodeBlockTools
|
|
16
15
|
from .tools.directory_tools import DirectoryTools
|
|
@@ -34,15 +33,12 @@ def build_user_server(*, stateless_http: bool = False) -> FastMCP:
|
|
|
34
33
|
|
|
35
34
|
## 页面交接
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
默认只交付用户请求的主要结果:安装方案默认提供应用包入口;直接创建或修改应用、视图时提供对应入口;用户明确要求多个主要对象时分别提供。使用业务结果中的稳定 `uri`,按 URI 去重,不为全部子资源预签票据。
|
|
39
|
-
主要对象没有可靠 URI 时说明限制,不猜地址,也不替换为不相关页面。部分成功时仅交付已确认成功且可定位的主要结果,保留失败或未验证说明。纯数据问答、中间读取、失败资源和删除操作不自动签发;用户明确要求不提供链接时遵从。
|
|
36
|
+
用户需要查看结果、继续编辑、处理业务或进入工作区页面时,使用 `get_login_link`;纯数据查询不自动签发链接。
|
|
40
37
|
目标路径由业务工具或领域 Skill 根据真实前端路由确定,不由票据工具根据业务标识推导。
|
|
41
38
|
已知目标传可选 `redirect_path`;明确指定页面但路径未知时继续定位或说明限制,不猜测,也不静默改为首页。
|
|
42
39
|
搜索未命中时继续搜索 `login` 或查看服务工具列表,不擅自打开固定正式站点;鉴权或工具失败时如实说明。
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
浏览器不可用时提供可点击链接,不假称已经打开,不展示工作区数字 ID 或原始 JSON。
|
|
40
|
+
临近交付时再签发,使用返回的完整 URL。要求“给我链接”时仅交付,不提前消费;要求“打开”时才调用浏览器。
|
|
41
|
+
浏览器不可用时提供可点击链接;用“查看记录”“继续编辑”等文案,不展示工作区数字 ID 或原始 JSON。
|
|
46
42
|
链接约 5 分钟内一次性有效,不能作为长期书签;安全验证及原有业务权限不变。
|
|
47
43
|
|
|
48
44
|
## App Discovery
|
|
@@ -243,7 +239,6 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
243
239
|
backend = BackendClient()
|
|
244
240
|
auth = wrap_trimmed_methods(AuthTools(sessions, backend), USER_SERVER_METHOD_MAP)
|
|
245
241
|
apps = wrap_trimmed_methods(AppTools(sessions, backend), USER_SERVER_METHOD_MAP)
|
|
246
|
-
data_tools = wrap_trimmed_methods(DataTools(sessions, backend), USER_SERVER_METHOD_MAP)
|
|
247
242
|
workspace = wrap_trimmed_methods(WorkspaceTools(sessions, backend), USER_SERVER_METHOD_MAP)
|
|
248
243
|
file_tools = wrap_trimmed_methods(FileTools(sessions, backend), USER_SERVER_METHOD_MAP)
|
|
249
244
|
imports = wrap_trimmed_methods(ImportTools(sessions, backend), USER_SERVER_METHOD_MAP)
|
|
@@ -397,8 +392,6 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
397
392
|
def app_get(profile: str = DEFAULT_PROFILE, app_key: str = "") -> dict:
|
|
398
393
|
return apps.app_get(profile=profile, app_key=app_key)
|
|
399
394
|
|
|
400
|
-
data_tools.register(server)
|
|
401
|
-
|
|
402
395
|
@server.tool()
|
|
403
396
|
def portal_list(profile: str = DEFAULT_PROFILE) -> dict:
|
|
404
397
|
return resources.portal_list(profile=profile)
|
|
@@ -20,7 +20,6 @@ from ..public_surface import public_builder_contract_tool_names
|
|
|
20
20
|
from ..config import DEFAULT_PROFILE
|
|
21
21
|
from ..errors import QingflowApiError, backend_code_int, backend_code_value_int
|
|
22
22
|
from ..json_types import JSONObject
|
|
23
|
-
from ..resource_uri import try_build_resource_uri
|
|
24
23
|
from ..builder_facade.models import (
|
|
25
24
|
AssociatedResourcesApplyRequest,
|
|
26
25
|
ChartApplyRequest,
|
|
@@ -188,26 +187,6 @@ class AiBuilderTools(ToolBase):
|
|
|
188
187
|
registry=app_form_schema_registry(),
|
|
189
188
|
)
|
|
190
189
|
|
|
191
|
-
def _selected_ws_id(self, profile: str) -> int:
|
|
192
|
-
session_profile, _backend_session, _context = self._require_context(profile, require_workspace=True)
|
|
193
|
-
assert session_profile.selected_ws_id is not None
|
|
194
|
-
return session_profile.selected_ws_id
|
|
195
|
-
|
|
196
|
-
def _attach_apply_envelope(self, profile: str, tool_name: str, payload: JSONObject) -> JSONObject:
|
|
197
|
-
result = _attach_builder_apply_envelope(tool_name, payload)
|
|
198
|
-
eligible = [
|
|
199
|
-
item
|
|
200
|
-
for item in result.get("resources") or []
|
|
201
|
-
if isinstance(item, dict)
|
|
202
|
-
and item.get("resource_type") in {"package", "app", "view"}
|
|
203
|
-
and str(item.get("status") or "").lower()
|
|
204
|
-
not in {"failed", "pending", "planned", "readback_pending", "pending_readback", "unknown", "removed"}
|
|
205
|
-
and str(item.get("operation") or "").lower() not in {"failed", "removed", "planned"}
|
|
206
|
-
]
|
|
207
|
-
if eligible:
|
|
208
|
-
_attach_builder_resource_uris(result, eligible, ws_id=self._selected_ws_id(profile))
|
|
209
|
-
return result
|
|
210
|
-
|
|
211
190
|
def _apply_app_batch(self, *, tool_name: str, profile: str, apps: list[JSONObject], apply_one) -> JSONObject:
|
|
212
191
|
started_at = time.perf_counter()
|
|
213
192
|
batch_item_apply_ms = 0
|
|
@@ -220,7 +199,7 @@ class AiBuilderTools(ToolBase):
|
|
|
220
199
|
child_total_ms=child_total_ms,
|
|
221
200
|
total_ms=_elapsed_ms(started_at),
|
|
222
201
|
)
|
|
223
|
-
return
|
|
202
|
+
return _attach_builder_apply_envelope(tool_name, payload)
|
|
224
203
|
|
|
225
204
|
if not isinstance(apps, list) or not apps:
|
|
226
205
|
return finish(
|
|
@@ -862,30 +841,16 @@ class AiBuilderTools(ToolBase):
|
|
|
862
841
|
being_draft: bool = False,
|
|
863
842
|
) -> JSONObject:
|
|
864
843
|
"""Read a canonical draft or published AppForm resource."""
|
|
865
|
-
|
|
844
|
+
return self._app_form.get(
|
|
866
845
|
profile=profile,
|
|
867
846
|
app_key=app_key,
|
|
868
847
|
schema_version=schema_version,
|
|
869
848
|
being_draft=being_draft,
|
|
870
849
|
)
|
|
871
|
-
if result.get("status") == "success":
|
|
872
|
-
_attach_uri(result, result, ws_id=self._selected_ws_id(profile), resource_type="app", app_key=app_key)
|
|
873
|
-
return result
|
|
874
850
|
|
|
875
851
|
def app_form_apply(self, *, profile: str, spec: JSONObject) -> JSONObject:
|
|
876
852
|
"""Reconcile one complete declarative AppForm target."""
|
|
877
|
-
|
|
878
|
-
if result.get("appKey") and (
|
|
879
|
-
str(result.get("status") or "") == "success" or result.get("createdAppPreserved") is True
|
|
880
|
-
):
|
|
881
|
-
_attach_uri(
|
|
882
|
-
result,
|
|
883
|
-
result,
|
|
884
|
-
ws_id=self._selected_ws_id(profile),
|
|
885
|
-
resource_type="app",
|
|
886
|
-
app_key=result.get("appKey"),
|
|
887
|
-
)
|
|
888
|
-
return result
|
|
853
|
+
return self._app_form.apply(profile=profile, spec=spec)
|
|
889
854
|
|
|
890
855
|
def app_form_evaluate_formula(
|
|
891
856
|
self,
|
|
@@ -952,24 +917,12 @@ class AiBuilderTools(ToolBase):
|
|
|
952
917
|
def package_list(self, *, profile: str, trial_status: str = "all", query: str = "") -> JSONObject:
|
|
953
918
|
"""执行分组与包相关逻辑。"""
|
|
954
919
|
normalized_args = {"trial_status": trial_status, "query": query}
|
|
955
|
-
|
|
920
|
+
return _safe_tool_call(
|
|
956
921
|
lambda: self._facade.package_list(profile=profile, trial_status=trial_status, query=query),
|
|
957
922
|
error_code="PACKAGE_LIST_FAILED",
|
|
958
923
|
normalized_args=normalized_args,
|
|
959
924
|
suggested_next_call={"tool_name": "package_list", "arguments": {"profile": profile, "trial_status": trial_status, "query": query}},
|
|
960
925
|
)
|
|
961
|
-
if result.get("status") == "success":
|
|
962
|
-
ws_id = self._selected_ws_id(profile)
|
|
963
|
-
for item in result.get("items") or []:
|
|
964
|
-
if isinstance(item, dict):
|
|
965
|
-
_attach_uri(
|
|
966
|
-
item,
|
|
967
|
-
result,
|
|
968
|
-
ws_id=ws_id,
|
|
969
|
-
resource_type="package",
|
|
970
|
-
package_id=item.get("package_id"),
|
|
971
|
-
)
|
|
972
|
-
return result
|
|
973
926
|
|
|
974
927
|
def package_resolve(self, *, profile: str, package_name: str) -> JSONObject:
|
|
975
928
|
"""执行分组与包相关逻辑。"""
|
|
@@ -1109,23 +1062,12 @@ class AiBuilderTools(ToolBase):
|
|
|
1109
1062
|
def package_get(self, *, profile: str, package_id: int | None = None) -> JSONObject:
|
|
1110
1063
|
"""执行分组与包相关逻辑。"""
|
|
1111
1064
|
normalized_args = {"package_id": package_id}
|
|
1112
|
-
|
|
1065
|
+
return _publicize_package_fields(_safe_tool_call(
|
|
1113
1066
|
lambda: self._facade.package_get(profile=profile, package_id=package_id),
|
|
1114
1067
|
error_code="PACKAGE_GET_FAILED",
|
|
1115
1068
|
normalized_args=normalized_args,
|
|
1116
1069
|
suggested_next_call={"tool_name": "package_get", "arguments": {"profile": profile, "package_id": package_id}},
|
|
1117
1070
|
))
|
|
1118
|
-
if result.get("status") == "success":
|
|
1119
|
-
ws_id = self._selected_ws_id(profile)
|
|
1120
|
-
_attach_uri(
|
|
1121
|
-
result,
|
|
1122
|
-
result,
|
|
1123
|
-
ws_id=ws_id,
|
|
1124
|
-
resource_type="package",
|
|
1125
|
-
package_id=result.get("package_id"),
|
|
1126
|
-
)
|
|
1127
|
-
_attach_package_item_uris(result.get("items"), result, ws_id=ws_id)
|
|
1128
|
-
return result
|
|
1129
1071
|
|
|
1130
1072
|
def package_apply(
|
|
1131
1073
|
self,
|
|
@@ -1155,7 +1097,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1155
1097
|
try:
|
|
1156
1098
|
visibility_patch = VisibilityPatch.model_validate(visibility)
|
|
1157
1099
|
except ValidationError as exc:
|
|
1158
|
-
return
|
|
1100
|
+
return _attach_builder_apply_envelope(
|
|
1159
1101
|
"package_apply",
|
|
1160
1102
|
_visibility_validation_failure(str(exc), tool_name="package_apply", exc=exc),
|
|
1161
1103
|
)
|
|
@@ -1166,7 +1108,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1166
1108
|
creating=package_id is None and bool(str(package_name or "").strip()),
|
|
1167
1109
|
)
|
|
1168
1110
|
if icon_failure is not None:
|
|
1169
|
-
return
|
|
1111
|
+
return _attach_builder_apply_envelope("package_apply", icon_failure)
|
|
1170
1112
|
normalized_args = {
|
|
1171
1113
|
"package_id": package_id,
|
|
1172
1114
|
**({"package_name": package_name} if str(package_name or "").strip() else {}),
|
|
@@ -1191,7 +1133,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1191
1133
|
normalized_args=normalized_args,
|
|
1192
1134
|
suggested_next_call={"tool_name": "package_apply", "arguments": {"profile": profile, **normalized_args}},
|
|
1193
1135
|
))
|
|
1194
|
-
return
|
|
1136
|
+
return _attach_builder_apply_envelope("package_apply", result)
|
|
1195
1137
|
|
|
1196
1138
|
def package_update(
|
|
1197
1139
|
self,
|
|
@@ -1245,7 +1187,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1245
1187
|
"being_copy_data": being_copy_data,
|
|
1246
1188
|
"solution_source": solution_source,
|
|
1247
1189
|
}
|
|
1248
|
-
|
|
1190
|
+
return _safe_tool_call(
|
|
1249
1191
|
lambda: self._facade.solution_install(
|
|
1250
1192
|
profile=profile,
|
|
1251
1193
|
solution_key=solution_key,
|
|
@@ -1256,7 +1198,6 @@ class AiBuilderTools(ToolBase):
|
|
|
1256
1198
|
normalized_args=normalized_args,
|
|
1257
1199
|
suggested_next_call={"tool_name": "solution_install", "arguments": {"profile": profile, **normalized_args}},
|
|
1258
1200
|
)
|
|
1259
|
-
return self._attach_apply_envelope(profile, "solution_install", result)
|
|
1260
1201
|
|
|
1261
1202
|
def member_search(
|
|
1262
1203
|
self,
|
|
@@ -1453,7 +1394,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1453
1394
|
try:
|
|
1454
1395
|
request = CustomButtonsApplyRequest.model_validate(raw_request)
|
|
1455
1396
|
except ValidationError as exc:
|
|
1456
|
-
return
|
|
1397
|
+
return _attach_builder_apply_envelope("app_custom_buttons_apply", _validation_failure(
|
|
1457
1398
|
str(exc),
|
|
1458
1399
|
tool_name="app_custom_buttons_apply",
|
|
1459
1400
|
exc=exc,
|
|
@@ -1477,7 +1418,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1477
1418
|
},
|
|
1478
1419
|
))
|
|
1479
1420
|
normalized_args = request.model_dump(mode="json")
|
|
1480
|
-
return
|
|
1421
|
+
return _attach_builder_apply_envelope("app_custom_buttons_apply", _safe_tool_call(
|
|
1481
1422
|
lambda: self._facade.app_custom_buttons_apply(profile=profile, request=request),
|
|
1482
1423
|
error_code="CUSTOM_BUTTONS_APPLY_FAILED",
|
|
1483
1424
|
normalized_args=normalized_args,
|
|
@@ -1534,7 +1475,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1534
1475
|
try:
|
|
1535
1476
|
request = AssociatedResourcesApplyRequest.model_validate(raw_request)
|
|
1536
1477
|
except ValidationError as exc:
|
|
1537
|
-
return
|
|
1478
|
+
return _attach_builder_apply_envelope("app_associated_resources_apply", _validation_failure(
|
|
1538
1479
|
str(exc),
|
|
1539
1480
|
tool_name="app_associated_resources_apply",
|
|
1540
1481
|
exc=exc,
|
|
@@ -1563,7 +1504,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1563
1504
|
},
|
|
1564
1505
|
))
|
|
1565
1506
|
normalized_args = request.model_dump(mode="json", exclude_none=True)
|
|
1566
|
-
return
|
|
1507
|
+
return _attach_builder_apply_envelope("app_associated_resources_apply", _safe_tool_call(
|
|
1567
1508
|
lambda: self._facade.app_associated_resources_apply(profile=profile, request=request),
|
|
1568
1509
|
error_code="ASSOCIATED_RESOURCES_APPLY_FAILED",
|
|
1569
1510
|
normalized_args=normalized_args,
|
|
@@ -1688,27 +1629,12 @@ class AiBuilderTools(ToolBase):
|
|
|
1688
1629
|
read_one=lambda item_app_key: self.app_get(profile=profile, app_key=item_app_key, app_keys=None),
|
|
1689
1630
|
)
|
|
1690
1631
|
normalized_args = {"app_key": app_key}
|
|
1691
|
-
|
|
1632
|
+
return _publicize_package_fields(_safe_tool_call(
|
|
1692
1633
|
lambda: self._facade.app_get(profile=profile, app_key=app_key),
|
|
1693
1634
|
error_code="APP_GET_FAILED",
|
|
1694
1635
|
normalized_args=normalized_args,
|
|
1695
1636
|
suggested_next_call={"tool_name": "app_get", "arguments": {"profile": profile, "app_key": app_key}},
|
|
1696
1637
|
))
|
|
1697
|
-
if result.get("status") == "success":
|
|
1698
|
-
ws_id = self._selected_ws_id(profile)
|
|
1699
|
-
_attach_uri(result, result, ws_id=ws_id, resource_type="app", app_key=app_key)
|
|
1700
|
-
for view in result.get("views") or []:
|
|
1701
|
-
if isinstance(view, dict) and (view.get("view_key") or view.get("viewKey")):
|
|
1702
|
-
_attach_uri(
|
|
1703
|
-
view,
|
|
1704
|
-
result,
|
|
1705
|
-
ws_id=ws_id,
|
|
1706
|
-
resource_type="view",
|
|
1707
|
-
app_key=app_key,
|
|
1708
|
-
view_kind="custom",
|
|
1709
|
-
view_key=view.get("view_key") or view.get("viewKey"),
|
|
1710
|
-
)
|
|
1711
|
-
return result
|
|
1712
1638
|
|
|
1713
1639
|
def app_read_fields(self, *, profile: str, app_key: str) -> JSONObject:
|
|
1714
1640
|
"""执行应用相关逻辑。"""
|
|
@@ -1801,27 +1727,12 @@ class AiBuilderTools(ToolBase):
|
|
|
1801
1727
|
read_one=lambda item_app_key: self.app_get_views(profile=profile, app_key=item_app_key, app_keys=None),
|
|
1802
1728
|
)
|
|
1803
1729
|
normalized_args = {"app_key": app_key}
|
|
1804
|
-
|
|
1730
|
+
return _safe_tool_call(
|
|
1805
1731
|
lambda: self._facade.app_get_views(profile=profile, app_key=app_key),
|
|
1806
1732
|
error_code="APP_GET_VIEWS_FAILED",
|
|
1807
1733
|
normalized_args=normalized_args,
|
|
1808
1734
|
suggested_next_call={"tool_name": "app_get_views", "arguments": {"profile": profile, "app_key": app_key}},
|
|
1809
1735
|
)
|
|
1810
|
-
if result.get("status") == "success":
|
|
1811
|
-
ws_id = self._selected_ws_id(profile)
|
|
1812
|
-
_attach_uri(result, result, ws_id=ws_id, resource_type="app", app_key=app_key)
|
|
1813
|
-
for view in result.get("views") or []:
|
|
1814
|
-
if isinstance(view, dict) and (view.get("view_key") or view.get("viewKey")):
|
|
1815
|
-
_attach_uri(
|
|
1816
|
-
view,
|
|
1817
|
-
result,
|
|
1818
|
-
ws_id=ws_id,
|
|
1819
|
-
resource_type="view",
|
|
1820
|
-
app_key=app_key,
|
|
1821
|
-
view_kind="custom",
|
|
1822
|
-
view_key=view.get("view_key") or view.get("viewKey"),
|
|
1823
|
-
)
|
|
1824
|
-
return result
|
|
1825
1736
|
|
|
1826
1737
|
def app_read_flow_summary(self, *, profile: str, app_key: str) -> JSONObject:
|
|
1827
1738
|
"""执行应用相关逻辑。"""
|
|
@@ -1960,27 +1871,12 @@ class AiBuilderTools(ToolBase):
|
|
|
1960
1871
|
"""执行视图相关逻辑。"""
|
|
1961
1872
|
resolved_view_key = _normalize_builder_view_key(str(view_key or viewgraph_key or "").strip())
|
|
1962
1873
|
normalized_args = {"view_key": resolved_view_key}
|
|
1963
|
-
|
|
1874
|
+
return _safe_tool_call(
|
|
1964
1875
|
lambda: self._facade.view_get(profile=profile, view_key=resolved_view_key),
|
|
1965
1876
|
error_code="VIEW_GET_FAILED",
|
|
1966
1877
|
normalized_args=normalized_args,
|
|
1967
1878
|
suggested_next_call={"tool_name": "view_get", "arguments": {"profile": profile, **normalized_args}},
|
|
1968
1879
|
)
|
|
1969
|
-
if result.get("status") == "success":
|
|
1970
|
-
config = result.get("config") if isinstance(result.get("config"), dict) else {}
|
|
1971
|
-
base_info = result.get("base_info") if isinstance(result.get("base_info"), dict) else {}
|
|
1972
|
-
app_key = str(config.get("appKey") or config.get("formKey") or base_info.get("appKey") or base_info.get("formKey") or "").strip()
|
|
1973
|
-
if app_key:
|
|
1974
|
-
_attach_uri(
|
|
1975
|
-
result,
|
|
1976
|
-
result,
|
|
1977
|
-
ws_id=self._selected_ws_id(profile),
|
|
1978
|
-
resource_type="view",
|
|
1979
|
-
app_key=app_key,
|
|
1980
|
-
view_kind="custom",
|
|
1981
|
-
view_key=resolved_view_key,
|
|
1982
|
-
)
|
|
1983
|
-
return result
|
|
1984
1880
|
|
|
1985
1881
|
def chart_get(
|
|
1986
1882
|
self,
|
|
@@ -2269,7 +2165,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2269
2165
|
)
|
|
2270
2166
|
failure = normalized_apps_payload.get("failure")
|
|
2271
2167
|
if isinstance(failure, dict):
|
|
2272
|
-
return
|
|
2168
|
+
return _attach_builder_apply_envelope("app_schema_apply", failure)
|
|
2273
2169
|
package_id = normalized_apps_payload.get("package_id") # type: ignore[assignment]
|
|
2274
2170
|
apps = normalized_apps_payload.get("apps") # type: ignore[assignment]
|
|
2275
2171
|
input_warnings = list(normalized_apps_payload.get("warnings") or [])
|
|
@@ -2285,7 +2181,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2285
2181
|
)
|
|
2286
2182
|
failure = form_result.get("failure")
|
|
2287
2183
|
if isinstance(failure, dict):
|
|
2288
|
-
return
|
|
2184
|
+
return _attach_builder_apply_envelope("app_schema_apply", failure)
|
|
2289
2185
|
normalized_apps.append(form_result.get("payload") or app_item)
|
|
2290
2186
|
apps = normalized_apps
|
|
2291
2187
|
result = self._app_schema_apply_multi(
|
|
@@ -2299,7 +2195,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2299
2195
|
result_warnings = list(result.get("warnings") or [])
|
|
2300
2196
|
result_warnings.extend(deepcopy(input_warnings))
|
|
2301
2197
|
result["warnings"] = result_warnings
|
|
2302
|
-
return
|
|
2198
|
+
return _attach_builder_apply_envelope("app_schema_apply", result)
|
|
2303
2199
|
inline_form_layout_sections: list[JSONObject] = []
|
|
2304
2200
|
if form:
|
|
2305
2201
|
form_payload: JSONObject = {"form": form}
|
|
@@ -2312,7 +2208,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2312
2208
|
)
|
|
2313
2209
|
failure = form_result.get("failure")
|
|
2314
2210
|
if isinstance(failure, dict):
|
|
2315
|
-
return
|
|
2211
|
+
return _attach_builder_apply_envelope("app_schema_apply", failure)
|
|
2316
2212
|
normalized_payload = form_result.get("payload") if isinstance(form_result.get("payload"), dict) else {}
|
|
2317
2213
|
add_fields = list(normalized_payload.get("add_fields") or [])
|
|
2318
2214
|
inline_form_layout_sections = list(form_result.get("layout_sections") or [])
|
|
@@ -2350,7 +2246,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2350
2246
|
inline_form_layout_sections=inline_form_layout_sections,
|
|
2351
2247
|
),
|
|
2352
2248
|
)
|
|
2353
|
-
return
|
|
2249
|
+
return _attach_builder_apply_envelope("app_schema_apply", result)
|
|
2354
2250
|
|
|
2355
2251
|
def _app_schema_apply_multi(
|
|
2356
2252
|
self,
|
|
@@ -3629,7 +3525,7 @@ class AiBuilderTools(ToolBase):
|
|
|
3629
3525
|
sections=sections,
|
|
3630
3526
|
),
|
|
3631
3527
|
)
|
|
3632
|
-
return
|
|
3528
|
+
return _attach_builder_apply_envelope("app_layout_apply", result)
|
|
3633
3529
|
|
|
3634
3530
|
def _app_layout_apply_once(self, *, profile: str, app_key: str, mode: str = "merge", publish: bool = True, sections: list[JSONObject]) -> JSONObject:
|
|
3635
3531
|
"""执行内部辅助逻辑。"""
|
|
@@ -3694,7 +3590,7 @@ class AiBuilderTools(ToolBase):
|
|
|
3694
3590
|
"idempotency_key": idempotency_key,
|
|
3695
3591
|
"schema_version": schema_version,
|
|
3696
3592
|
}
|
|
3697
|
-
return
|
|
3593
|
+
return _attach_builder_apply_envelope("app_flow_apply", _safe_tool_call(
|
|
3698
3594
|
lambda: self._facade.flow_patch_nodes(
|
|
3699
3595
|
profile=profile,
|
|
3700
3596
|
app_key=app_key,
|
|
@@ -3715,7 +3611,7 @@ class AiBuilderTools(ToolBase):
|
|
|
3715
3611
|
"idempotency_key": idempotency_key,
|
|
3716
3612
|
"schema_version": schema_version,
|
|
3717
3613
|
}
|
|
3718
|
-
return
|
|
3614
|
+
return _attach_builder_apply_envelope("app_flow_apply", _safe_tool_call(
|
|
3719
3615
|
lambda: self._facade.flow_apply(
|
|
3720
3616
|
profile=profile,
|
|
3721
3617
|
app_key=app_key,
|
|
@@ -3751,9 +3647,9 @@ class AiBuilderTools(ToolBase):
|
|
|
3751
3647
|
transitions=effective_transitions,
|
|
3752
3648
|
),
|
|
3753
3649
|
)
|
|
3754
|
-
return
|
|
3650
|
+
return _attach_builder_apply_envelope("app_flow_apply", result)
|
|
3755
3651
|
normalized_args = {"app_key": app_key, "publish": publish}
|
|
3756
|
-
return
|
|
3652
|
+
return _attach_builder_apply_envelope(
|
|
3757
3653
|
"app_flow_apply",
|
|
3758
3654
|
{
|
|
3759
3655
|
"status": "failed",
|
|
@@ -3888,7 +3784,7 @@ class AiBuilderTools(ToolBase):
|
|
|
3888
3784
|
patch_views=patch_views or [],
|
|
3889
3785
|
),
|
|
3890
3786
|
)
|
|
3891
|
-
return
|
|
3787
|
+
return _attach_builder_apply_envelope("app_views_apply", result)
|
|
3892
3788
|
|
|
3893
3789
|
def _app_views_apply_view_batch(
|
|
3894
3790
|
self,
|
|
@@ -3899,7 +3795,7 @@ class AiBuilderTools(ToolBase):
|
|
|
3899
3795
|
) -> JSONObject:
|
|
3900
3796
|
started_at = time.perf_counter()
|
|
3901
3797
|
if not isinstance(views, list) or not views:
|
|
3902
|
-
return
|
|
3798
|
+
return _attach_builder_apply_envelope(
|
|
3903
3799
|
"app_views_apply",
|
|
3904
3800
|
_config_failure(
|
|
3905
3801
|
tool_name="app_views_apply",
|
|
@@ -4130,7 +4026,7 @@ class AiBuilderTools(ToolBase):
|
|
|
4130
4026
|
view_write_parallel_wall_ms=view_write_parallel_wall_ms,
|
|
4131
4027
|
total_ms=_elapsed_ms(started_at),
|
|
4132
4028
|
)
|
|
4133
|
-
return
|
|
4029
|
+
return _attach_builder_apply_envelope("app_views_apply", payload)
|
|
4134
4030
|
|
|
4135
4031
|
def _app_views_apply_once(
|
|
4136
4032
|
self,
|
|
@@ -4253,7 +4149,7 @@ class AiBuilderTools(ToolBase):
|
|
|
4253
4149
|
}
|
|
4254
4150
|
)
|
|
4255
4151
|
except ValidationError as exc:
|
|
4256
|
-
return
|
|
4152
|
+
return _attach_builder_apply_envelope("app_charts_apply", _visibility_validation_failure(
|
|
4257
4153
|
str(exc),
|
|
4258
4154
|
tool_name="app_charts_apply",
|
|
4259
4155
|
exc=exc,
|
|
@@ -4269,7 +4165,7 @@ class AiBuilderTools(ToolBase):
|
|
|
4269
4165
|
},
|
|
4270
4166
|
))
|
|
4271
4167
|
normalized_args = request.model_dump(mode="json")
|
|
4272
|
-
return
|
|
4168
|
+
return _attach_builder_apply_envelope("app_charts_apply", _safe_tool_call(
|
|
4273
4169
|
lambda: self._facade.chart_apply(profile=profile, request=request),
|
|
4274
4170
|
error_code="CHART_APPLY_FAILED",
|
|
4275
4171
|
normalized_args=normalized_args,
|
|
@@ -4305,7 +4201,7 @@ class AiBuilderTools(ToolBase):
|
|
|
4305
4201
|
"publish": publish,
|
|
4306
4202
|
"patch_sections": patch_sections,
|
|
4307
4203
|
}
|
|
4308
|
-
return
|
|
4204
|
+
return _attach_builder_apply_envelope("portal_apply", _publicize_package_fields(_safe_tool_call(
|
|
4309
4205
|
lambda: self._facade.portal_patch_sections(
|
|
4310
4206
|
profile=profile,
|
|
4311
4207
|
dash_key=dash_key,
|
|
@@ -4352,7 +4248,7 @@ class AiBuilderTools(ToolBase):
|
|
|
4352
4248
|
try:
|
|
4353
4249
|
request = PortalApplyRequest.model_validate(request_payload)
|
|
4354
4250
|
except ValidationError as exc:
|
|
4355
|
-
return
|
|
4251
|
+
return _attach_builder_apply_envelope("portal_apply", _visibility_validation_failure(
|
|
4356
4252
|
str(exc),
|
|
4357
4253
|
tool_name="portal_apply",
|
|
4358
4254
|
exc=exc,
|
|
@@ -4383,14 +4279,14 @@ class AiBuilderTools(ToolBase):
|
|
|
4383
4279
|
creating=not bool(str(request.dash_key or "").strip()),
|
|
4384
4280
|
)
|
|
4385
4281
|
if icon_failure is not None:
|
|
4386
|
-
return
|
|
4282
|
+
return _attach_builder_apply_envelope("portal_apply", icon_failure)
|
|
4387
4283
|
result = _publicize_package_fields(_safe_tool_call(
|
|
4388
4284
|
lambda: self._facade.portal_apply(profile=profile, request=request),
|
|
4389
4285
|
error_code="PORTAL_APPLY_FAILED",
|
|
4390
4286
|
normalized_args=normalized_args,
|
|
4391
4287
|
suggested_next_call={"tool_name": "portal_apply", "arguments": {"profile": profile, **normalized_args}},
|
|
4392
4288
|
))
|
|
4393
|
-
return
|
|
4289
|
+
return _attach_builder_apply_envelope("portal_apply", result)
|
|
4394
4290
|
|
|
4395
4291
|
def portal_delete(self, *, profile: str, dash_key: str) -> JSONObject:
|
|
4396
4292
|
"""执行门户删除逻辑。"""
|
|
@@ -4401,7 +4297,7 @@ class AiBuilderTools(ToolBase):
|
|
|
4401
4297
|
normalized_args=normalized_args,
|
|
4402
4298
|
suggested_next_call={"tool_name": "portal_delete", "arguments": {"profile": profile, **normalized_args}},
|
|
4403
4299
|
))
|
|
4404
|
-
return
|
|
4300
|
+
return _attach_builder_apply_envelope("portal_delete", result)
|
|
4405
4301
|
|
|
4406
4302
|
def app_publish_verify(
|
|
4407
4303
|
self,
|
|
@@ -4440,7 +4336,7 @@ class AiBuilderTools(ToolBase):
|
|
|
4440
4336
|
expected_package_tag_id=expected_package_id,
|
|
4441
4337
|
),
|
|
4442
4338
|
))
|
|
4443
|
-
return
|
|
4339
|
+
return _attach_builder_apply_envelope("app_publish_verify", result)
|
|
4444
4340
|
|
|
4445
4341
|
def _retry_after_self_lock_release(self, *, profile: str, result: JSONObject, retry_call) -> JSONObject:
|
|
4446
4342
|
"""执行内部辅助逻辑。"""
|
|
@@ -5806,68 +5702,6 @@ def _publicize_package_fields(value):
|
|
|
5806
5702
|
return public
|
|
5807
5703
|
|
|
5808
5704
|
|
|
5809
|
-
def _append_uri_warning(payload: JSONObject, warning: JSONObject | None) -> None:
|
|
5810
|
-
if not warning:
|
|
5811
|
-
return
|
|
5812
|
-
warnings = payload.setdefault("warnings", [])
|
|
5813
|
-
if isinstance(warnings, list) and not any(
|
|
5814
|
-
isinstance(item, dict) and item.get("code") == warning.get("code") for item in warnings
|
|
5815
|
-
):
|
|
5816
|
-
warnings.append(warning)
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
def _attach_uri(target: JSONObject, payload: JSONObject, *, ws_id: int, **identity: Any) -> None:
|
|
5820
|
-
uri, warning = try_build_resource_uri(ws_id=ws_id, **identity)
|
|
5821
|
-
if uri:
|
|
5822
|
-
target["uri"] = uri
|
|
5823
|
-
_append_uri_warning(payload, warning)
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
def _attach_builder_resource_uris(payload: JSONObject, resources: list[JSONObject], *, ws_id: int) -> None:
|
|
5827
|
-
for resource in resources:
|
|
5828
|
-
resource_type = str(resource.get("resource_type") or "")
|
|
5829
|
-
ids = resource.get("ids") if isinstance(resource.get("ids"), dict) else {}
|
|
5830
|
-
if resource_type == "package":
|
|
5831
|
-
_attach_uri(
|
|
5832
|
-
resource,
|
|
5833
|
-
payload,
|
|
5834
|
-
ws_id=ws_id,
|
|
5835
|
-
resource_type="package",
|
|
5836
|
-
package_id=resource.get("id") or ids.get("package_id"),
|
|
5837
|
-
)
|
|
5838
|
-
elif resource_type == "app":
|
|
5839
|
-
_attach_uri(
|
|
5840
|
-
resource,
|
|
5841
|
-
payload,
|
|
5842
|
-
ws_id=ws_id,
|
|
5843
|
-
resource_type="app",
|
|
5844
|
-
app_key=resource.get("key") or ids.get("app_key"),
|
|
5845
|
-
)
|
|
5846
|
-
elif resource_type == "view":
|
|
5847
|
-
parent = resource.get("parent") if isinstance(resource.get("parent"), dict) else {}
|
|
5848
|
-
_attach_uri(
|
|
5849
|
-
resource,
|
|
5850
|
-
payload,
|
|
5851
|
-
ws_id=ws_id,
|
|
5852
|
-
resource_type="view",
|
|
5853
|
-
app_key=ids.get("app_key") or (parent.get("key") if parent.get("resource_type") == "app" else None),
|
|
5854
|
-
view_kind="custom",
|
|
5855
|
-
view_key=resource.get("key") or ids.get("view_key"),
|
|
5856
|
-
)
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
def _attach_package_item_uris(items: Any, payload: JSONObject, *, ws_id: int) -> None:
|
|
5860
|
-
if not isinstance(items, list):
|
|
5861
|
-
return
|
|
5862
|
-
for item in items:
|
|
5863
|
-
if not isinstance(item, dict):
|
|
5864
|
-
continue
|
|
5865
|
-
if item.get("type") == "app" and item.get("app_key"):
|
|
5866
|
-
_attach_uri(item, payload, ws_id=ws_id, resource_type="app", app_key=item.get("app_key"))
|
|
5867
|
-
if item.get("type") == "group":
|
|
5868
|
-
_attach_package_item_uris(item.get("items"), payload, ws_id=ws_id)
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
5705
|
def _builder_contract_with_apply_output(tool_name: str, contract: JSONObject) -> JSONObject:
|
|
5872
5706
|
public = deepcopy(contract)
|
|
5873
5707
|
if tool_name not in BUILDER_APPLY_TOOL_NAMES:
|
|
@@ -5880,7 +5714,7 @@ def _builder_contract_with_apply_output(tool_name: str, contract: JSONObject) ->
|
|
|
5880
5714
|
public["output_contract"] = {
|
|
5881
5715
|
"schema_version": BUILDER_APPLY_SCHEMA_VERSION,
|
|
5882
5716
|
"preferred_ui_fields": ["operation", "summary", "resources"],
|
|
5883
|
-
"resource_fields": ["resource_type", "operation", "status", "id", "key", "name", "ids", "parent", "
|
|
5717
|
+
"resource_fields": ["resource_type", "operation", "status", "id", "key", "name", "ids", "parent", "icon_config", "error_code", "message"],
|
|
5884
5718
|
"json_paths": _builder_apply_json_paths(),
|
|
5885
5719
|
"legacy_fields_preserved": True,
|
|
5886
5720
|
}
|
|
@@ -5932,7 +5766,6 @@ def _builder_apply_json_paths() -> JSONObject:
|
|
|
5932
5766
|
"resource_keys": "$.resources[].key",
|
|
5933
5767
|
"resource_ids": "$.resources[].id",
|
|
5934
5768
|
"resource_statuses": "$.resources[].status",
|
|
5935
|
-
"resource_uris": "$.resources[].uri",
|
|
5936
5769
|
}
|
|
5937
5770
|
|
|
5938
5771
|
|
|
@@ -6022,9 +5855,7 @@ def _builder_verification_truthy(value: object) -> bool:
|
|
|
6022
5855
|
|
|
6023
5856
|
def _builder_apply_resources(tool_name: str, payload: JSONObject) -> list[JSONObject]:
|
|
6024
5857
|
resources: list[JSONObject]
|
|
6025
|
-
if tool_name == "
|
|
6026
|
-
resources = [deepcopy(item) for item in payload.get("resources") or [] if isinstance(item, dict)]
|
|
6027
|
-
elif tool_name == "package_apply":
|
|
5858
|
+
if tool_name == "package_apply":
|
|
6028
5859
|
resources = _builder_package_resources(payload)
|
|
6029
5860
|
elif tool_name == "app_schema_apply":
|
|
6030
5861
|
resources = _builder_schema_resources(payload)
|