@josephyan/qingflow-cli 0.2.0-beta.1000
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 +31 -0
- package/docs/local-agent-install.md +309 -0
- package/entry_point.py +13 -0
- package/npm/bin/qingflow.mjs +5 -0
- package/npm/lib/runtime.mjs +346 -0
- package/npm/scripts/postinstall.mjs +16 -0
- package/package.json +34 -0
- package/pyproject.toml +67 -0
- package/qingflow +15 -0
- package/src/qingflow_mcp/__init__.py +37 -0
- package/src/qingflow_mcp/__main__.py +5 -0
- package/src/qingflow_mcp/backend_client.py +649 -0
- package/src/qingflow_mcp/builder_facade/__init__.py +3 -0
- package/src/qingflow_mcp/builder_facade/models.py +1846 -0
- package/src/qingflow_mcp/builder_facade/service.py +16502 -0
- package/src/qingflow_mcp/cli/__init__.py +1 -0
- package/src/qingflow_mcp/cli/commands/__init__.py +18 -0
- package/src/qingflow_mcp/cli/commands/app.py +40 -0
- package/src/qingflow_mcp/cli/commands/auth.py +112 -0
- package/src/qingflow_mcp/cli/commands/builder.py +539 -0
- package/src/qingflow_mcp/cli/commands/chart.py +18 -0
- package/src/qingflow_mcp/cli/commands/common.py +62 -0
- package/src/qingflow_mcp/cli/commands/imports.py +96 -0
- package/src/qingflow_mcp/cli/commands/portal.py +25 -0
- package/src/qingflow_mcp/cli/commands/record.py +331 -0
- package/src/qingflow_mcp/cli/commands/repo.py +80 -0
- package/src/qingflow_mcp/cli/commands/task.py +141 -0
- package/src/qingflow_mcp/cli/commands/view.py +18 -0
- package/src/qingflow_mcp/cli/commands/workspace.py +110 -0
- package/src/qingflow_mcp/cli/context.py +60 -0
- package/src/qingflow_mcp/cli/formatters.py +573 -0
- package/src/qingflow_mcp/cli/json_io.py +50 -0
- package/src/qingflow_mcp/cli/main.py +186 -0
- package/src/qingflow_mcp/cli/qingflow_login.py +116 -0
- package/src/qingflow_mcp/cli/terminal_ui.py +173 -0
- package/src/qingflow_mcp/config.py +407 -0
- package/src/qingflow_mcp/errors.py +66 -0
- package/src/qingflow_mcp/id_utils.py +49 -0
- package/src/qingflow_mcp/import_store.py +121 -0
- package/src/qingflow_mcp/json_types.py +18 -0
- package/src/qingflow_mcp/list_type_labels.py +76 -0
- package/src/qingflow_mcp/public_surface.py +243 -0
- package/src/qingflow_mcp/repository_store.py +71 -0
- package/src/qingflow_mcp/response_trim.py +841 -0
- package/src/qingflow_mcp/server.py +216 -0
- package/src/qingflow_mcp/server_app_builder.py +543 -0
- package/src/qingflow_mcp/server_app_user.py +386 -0
- package/src/qingflow_mcp/session_store.py +369 -0
- package/src/qingflow_mcp/solution/__init__.py +6 -0
- package/src/qingflow_mcp/solution/build_assembly_store.py +181 -0
- package/src/qingflow_mcp/solution/compiler/__init__.py +282 -0
- package/src/qingflow_mcp/solution/compiler/chart_compiler.py +96 -0
- package/src/qingflow_mcp/solution/compiler/form_compiler.py +495 -0
- package/src/qingflow_mcp/solution/compiler/icon_utils.py +187 -0
- package/src/qingflow_mcp/solution/compiler/navigation_compiler.py +57 -0
- package/src/qingflow_mcp/solution/compiler/package_compiler.py +19 -0
- package/src/qingflow_mcp/solution/compiler/portal_compiler.py +60 -0
- package/src/qingflow_mcp/solution/compiler/view_compiler.py +51 -0
- package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
- package/src/qingflow_mcp/solution/design_session.py +222 -0
- package/src/qingflow_mcp/solution/design_store.py +100 -0
- package/src/qingflow_mcp/solution/executor.py +2398 -0
- package/src/qingflow_mcp/solution/normalizer.py +23 -0
- package/src/qingflow_mcp/solution/requirements_builder.py +536 -0
- package/src/qingflow_mcp/solution/run_store.py +244 -0
- package/src/qingflow_mcp/solution/spec_models.py +855 -0
- package/src/qingflow_mcp/tools/__init__.py +1 -0
- package/src/qingflow_mcp/tools/ai_builder_tools.py +3449 -0
- package/src/qingflow_mcp/tools/app_tools.py +926 -0
- package/src/qingflow_mcp/tools/approval_tools.py +1062 -0
- package/src/qingflow_mcp/tools/auth_tools.py +1133 -0
- package/src/qingflow_mcp/tools/base.py +281 -0
- package/src/qingflow_mcp/tools/code_block_tools.py +777 -0
- package/src/qingflow_mcp/tools/custom_button_tools.py +202 -0
- package/src/qingflow_mcp/tools/directory_tools.py +675 -0
- package/src/qingflow_mcp/tools/feedback_tools.py +238 -0
- package/src/qingflow_mcp/tools/file_tools.py +409 -0
- package/src/qingflow_mcp/tools/import_tools.py +2223 -0
- package/src/qingflow_mcp/tools/navigation_tools.py +210 -0
- package/src/qingflow_mcp/tools/package_tools.py +326 -0
- package/src/qingflow_mcp/tools/portal_tools.py +158 -0
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +374 -0
- package/src/qingflow_mcp/tools/record_tools.py +14291 -0
- package/src/qingflow_mcp/tools/repository_dev_tools.py +552 -0
- package/src/qingflow_mcp/tools/resource_read_tools.py +503 -0
- package/src/qingflow_mcp/tools/role_tools.py +112 -0
- package/src/qingflow_mcp/tools/solution_tools.py +4054 -0
- package/src/qingflow_mcp/tools/task_context_tools.py +2986 -0
- package/src/qingflow_mcp/tools/task_tools.py +889 -0
- package/src/qingflow_mcp/tools/view_tools.py +335 -0
- package/src/qingflow_mcp/tools/workflow_tools.py +376 -0
- package/src/qingflow_mcp/tools/workspace_tools.py +266 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from mcp.server.fastmcp import FastMCP
|
|
4
|
+
|
|
5
|
+
from ..config import DEFAULT_PROFILE
|
|
6
|
+
from ..errors import QingflowApiError, raise_tool_error
|
|
7
|
+
from ..json_types import JSONObject, JSONValue
|
|
8
|
+
from .base import ToolBase, tool_cn_name
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ViewTools(ToolBase):
|
|
12
|
+
"""视图工具(中文名:视图查询与配置读取)。
|
|
13
|
+
|
|
14
|
+
类型:视图配置工具。
|
|
15
|
+
主要职责:
|
|
16
|
+
1. 查询应用视图列表;
|
|
17
|
+
2. 获取视图配置与结构信息;
|
|
18
|
+
3. 为记录查询和分析提供视图侧元数据。
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def register(self, mcp: FastMCP) -> None:
|
|
22
|
+
"""注册当前工具到 MCP 服务。"""
|
|
23
|
+
@mcp.tool()
|
|
24
|
+
def view_list(profile: str = DEFAULT_PROFILE, app_key: str = "") -> JSONObject:
|
|
25
|
+
return self.view_list(profile=profile, app_key=app_key)
|
|
26
|
+
|
|
27
|
+
@mcp.tool()
|
|
28
|
+
def view_list_flat(profile: str = DEFAULT_PROFILE, app_key: str = "") -> JSONObject:
|
|
29
|
+
return self.view_list_flat(profile=profile, app_key=app_key)
|
|
30
|
+
|
|
31
|
+
@mcp.tool()
|
|
32
|
+
def view_get_config(profile: str = DEFAULT_PROFILE, viewgraph_key: str = "") -> JSONObject:
|
|
33
|
+
return self.view_get_config(profile=profile, viewgraph_key=viewgraph_key)
|
|
34
|
+
|
|
35
|
+
@mcp.tool()
|
|
36
|
+
def view_get_base_info(profile: str = DEFAULT_PROFILE, viewgraph_key: str = "", passcode: str | None = None) -> JSONObject:
|
|
37
|
+
return self.view_get_base_info(profile=profile, viewgraph_key=viewgraph_key, passcode=passcode)
|
|
38
|
+
|
|
39
|
+
@mcp.tool()
|
|
40
|
+
def view_list_questions(profile: str = DEFAULT_PROFILE, viewgraph_key: str = "") -> JSONObject:
|
|
41
|
+
return self.view_list_questions(profile=profile, viewgraph_key=viewgraph_key)
|
|
42
|
+
|
|
43
|
+
@mcp.tool()
|
|
44
|
+
def view_list_associations(profile: str = DEFAULT_PROFILE, viewgraph_key: str = "") -> JSONObject:
|
|
45
|
+
return self.view_list_associations(profile=profile, viewgraph_key=viewgraph_key)
|
|
46
|
+
|
|
47
|
+
@mcp.tool()
|
|
48
|
+
def view_board_get_lane_base_info(profile: str = DEFAULT_PROFILE, viewgraph_key: str = "", page_num: int = 1, page_size: int = 20) -> JSONObject:
|
|
49
|
+
return self.view_board_get_lane_base_info(profile=profile, viewgraph_key=viewgraph_key, page_num=page_num, page_size=page_size)
|
|
50
|
+
|
|
51
|
+
@mcp.tool()
|
|
52
|
+
def view_get_future_nodes(profile: str = DEFAULT_PROFILE, viewgraph_key: str = "", apply_id: int = 0, app_key: str = "") -> JSONObject:
|
|
53
|
+
return self.view_get_future_nodes(profile=profile, viewgraph_key=viewgraph_key, apply_id=apply_id, app_key=app_key)
|
|
54
|
+
|
|
55
|
+
@mcp.tool()
|
|
56
|
+
def view_get_workflow_status(profile: str = DEFAULT_PROFILE, viewgraph_key: str = "", row_record_id: int = 0) -> JSONObject:
|
|
57
|
+
return self.view_get_workflow_status(profile=profile, viewgraph_key=viewgraph_key, row_record_id=row_record_id)
|
|
58
|
+
|
|
59
|
+
@tool_cn_name("视图列表")
|
|
60
|
+
def view_list(self, *, profile: str, app_key: str) -> JSONObject:
|
|
61
|
+
"""执行视图相关逻辑。"""
|
|
62
|
+
self._require_app_key(app_key)
|
|
63
|
+
return self._request(profile, "GET", f"/app/{app_key}/view/viewList", app_key=app_key)
|
|
64
|
+
|
|
65
|
+
@tool_cn_name("视图列表(扁平)")
|
|
66
|
+
def view_list_flat(self, *, profile: str, app_key: str) -> JSONObject:
|
|
67
|
+
"""执行视图相关逻辑。"""
|
|
68
|
+
self._require_app_key(app_key)
|
|
69
|
+
return self._request(profile, "GET", f"/app/{app_key}/view/views", app_key=app_key)
|
|
70
|
+
|
|
71
|
+
@tool_cn_name("视图排序")
|
|
72
|
+
def view_reorder(self, *, profile: str, app_key: str, payload: list[JSONObject]) -> JSONObject:
|
|
73
|
+
"""执行视图相关逻辑。"""
|
|
74
|
+
self._require_app_key(app_key)
|
|
75
|
+
if not isinstance(payload, list) or not payload:
|
|
76
|
+
raise_tool_error(QingflowApiError.config_error("payload must be a non-empty array"))
|
|
77
|
+
return self._request(
|
|
78
|
+
profile,
|
|
79
|
+
"POST",
|
|
80
|
+
f"/app/{app_key}/view/ordinal",
|
|
81
|
+
app_key=app_key,
|
|
82
|
+
json_body=self._normalize_reorder_payload(payload),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@tool_cn_name("设置视图列宽")
|
|
86
|
+
def view_set_column_width(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
|
|
87
|
+
"""执行视图相关逻辑。"""
|
|
88
|
+
self._require_app_key(app_key)
|
|
89
|
+
body = self._require_dict(payload)
|
|
90
|
+
return self._request(profile, "POST", f"/app/{app_key}/view/que/width", app_key=app_key, json_body=body)
|
|
91
|
+
|
|
92
|
+
@tool_cn_name("创建视图")
|
|
93
|
+
def view_create(self, *, profile: str, payload: JSONObject) -> JSONObject:
|
|
94
|
+
"""执行视图相关逻辑。"""
|
|
95
|
+
body = self._require_dict(payload)
|
|
96
|
+
app_key = str(body.get("appKey") or "")
|
|
97
|
+
return self._request(profile, "POST", "/view/viewConfig", app_key=app_key, json_body=body)
|
|
98
|
+
|
|
99
|
+
@tool_cn_name("视图配置")
|
|
100
|
+
def view_get_config(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
101
|
+
"""执行视图相关逻辑。"""
|
|
102
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
103
|
+
return self._request(profile, "GET", f"/view/{viewgraph_key}/viewConfig", viewgraph_key=viewgraph_key)
|
|
104
|
+
|
|
105
|
+
@tool_cn_name("视图基础信息")
|
|
106
|
+
def view_get_base_info(self, *, profile: str, viewgraph_key: str, passcode: str | None) -> JSONObject:
|
|
107
|
+
"""执行视图相关逻辑。"""
|
|
108
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
109
|
+
params = {"pass": passcode} if passcode else None
|
|
110
|
+
return self._request(profile, "GET", f"/view/{viewgraph_key}/viewConfig/baseInfo", viewgraph_key=viewgraph_key, params=params)
|
|
111
|
+
|
|
112
|
+
@tool_cn_name("更新视图配置")
|
|
113
|
+
def view_update(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
114
|
+
"""执行视图相关逻辑。"""
|
|
115
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
116
|
+
body = self._require_dict(payload)
|
|
117
|
+
return self._request(
|
|
118
|
+
profile,
|
|
119
|
+
"POST",
|
|
120
|
+
f"/view/{viewgraph_key}/viewConfig",
|
|
121
|
+
viewgraph_key=viewgraph_key,
|
|
122
|
+
json_body=body,
|
|
123
|
+
risk_operation="update",
|
|
124
|
+
risk_target="view configuration",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
@tool_cn_name("删除视图")
|
|
128
|
+
def view_delete(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
129
|
+
"""执行视图相关逻辑。"""
|
|
130
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
131
|
+
return self._request(
|
|
132
|
+
profile,
|
|
133
|
+
"DELETE",
|
|
134
|
+
f"/view/{viewgraph_key}",
|
|
135
|
+
viewgraph_key=viewgraph_key,
|
|
136
|
+
risk_operation="delete",
|
|
137
|
+
risk_target="view configuration",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
@tool_cn_name("复制视图")
|
|
141
|
+
def view_copy(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
142
|
+
"""执行视图相关逻辑。"""
|
|
143
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
144
|
+
return self._request(profile, "POST", f"/view/{viewgraph_key}/copy", viewgraph_key=viewgraph_key)
|
|
145
|
+
|
|
146
|
+
@tool_cn_name("视图字段列表")
|
|
147
|
+
def view_list_questions(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
148
|
+
"""执行视图相关逻辑。"""
|
|
149
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
150
|
+
return self._request(profile, "GET", f"/view/{viewgraph_key}/question", viewgraph_key=viewgraph_key)
|
|
151
|
+
|
|
152
|
+
@tool_cn_name("视图关联列表")
|
|
153
|
+
def view_list_associations(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
154
|
+
"""执行视图相关逻辑。"""
|
|
155
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
156
|
+
return self._request(profile, "GET", f"/view/{viewgraph_key}/association", viewgraph_key=viewgraph_key)
|
|
157
|
+
|
|
158
|
+
@tool_cn_name("更新视图成员配置")
|
|
159
|
+
def view_update_member_config(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
160
|
+
"""执行视图相关逻辑。"""
|
|
161
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
162
|
+
body = self._require_dict(payload)
|
|
163
|
+
return self._request(
|
|
164
|
+
profile,
|
|
165
|
+
"POST",
|
|
166
|
+
f"/view/{viewgraph_key}/member/config",
|
|
167
|
+
viewgraph_key=viewgraph_key,
|
|
168
|
+
json_body=body,
|
|
169
|
+
risk_operation="update",
|
|
170
|
+
risk_target="view member visibility",
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
@tool_cn_name("更新视图数据配置")
|
|
174
|
+
def view_update_apply_config(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
175
|
+
"""执行视图相关逻辑。"""
|
|
176
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
177
|
+
body = self._require_dict(payload)
|
|
178
|
+
return self._request(
|
|
179
|
+
profile,
|
|
180
|
+
"POST",
|
|
181
|
+
f"/view/{viewgraph_key}/apply/config",
|
|
182
|
+
viewgraph_key=viewgraph_key,
|
|
183
|
+
json_body=body,
|
|
184
|
+
risk_operation="update",
|
|
185
|
+
risk_target="view apply visibility",
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
@tool_cn_name("看板泳道配置")
|
|
189
|
+
def view_board_set_lane_config(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
190
|
+
"""执行视图相关逻辑。"""
|
|
191
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
192
|
+
body = self._require_dict(payload)
|
|
193
|
+
return self._request(
|
|
194
|
+
profile,
|
|
195
|
+
"POST",
|
|
196
|
+
f"/view/{viewgraph_key}/lane/config",
|
|
197
|
+
viewgraph_key=viewgraph_key,
|
|
198
|
+
json_body=body,
|
|
199
|
+
risk_operation="update",
|
|
200
|
+
risk_target="board lane configuration",
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
@tool_cn_name("看板泳道基础信息")
|
|
204
|
+
def view_board_get_lane_base_info(self, *, profile: str, viewgraph_key: str, page_num: int, page_size: int) -> JSONObject:
|
|
205
|
+
"""执行视图相关逻辑。"""
|
|
206
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
207
|
+
return self._request(
|
|
208
|
+
profile,
|
|
209
|
+
"GET",
|
|
210
|
+
f"/view/{viewgraph_key}/lane/baseInfo",
|
|
211
|
+
viewgraph_key=viewgraph_key,
|
|
212
|
+
params={"pageNum": page_num, "pageSize": page_size},
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
@tool_cn_name("甘特图自动校准")
|
|
216
|
+
def view_gantt_switch_auto_calibration(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
217
|
+
"""执行视图相关逻辑。"""
|
|
218
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
219
|
+
body = self._require_dict(payload)
|
|
220
|
+
return self._request(
|
|
221
|
+
profile,
|
|
222
|
+
"PUT",
|
|
223
|
+
f"/view/gantt/{viewgraph_key}/auto/calibration",
|
|
224
|
+
viewgraph_key=viewgraph_key,
|
|
225
|
+
json_body=body,
|
|
226
|
+
risk_operation="update",
|
|
227
|
+
risk_target="gantt auto calibration settings",
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
@tool_cn_name("甘特图批量更新时间")
|
|
231
|
+
def view_gantt_batch_update_time(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
232
|
+
"""执行视图相关逻辑。"""
|
|
233
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
234
|
+
body = self._require_dict(payload)
|
|
235
|
+
return self._request(
|
|
236
|
+
profile,
|
|
237
|
+
"PUT",
|
|
238
|
+
f"/view/gantt/{viewgraph_key}/batch/update",
|
|
239
|
+
viewgraph_key=viewgraph_key,
|
|
240
|
+
json_body=body,
|
|
241
|
+
risk_operation="update",
|
|
242
|
+
risk_target="gantt task timing",
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
@tool_cn_name("视图后续节点")
|
|
246
|
+
def view_get_future_nodes(self, *, profile: str, viewgraph_key: str, apply_id: int, app_key: str) -> JSONObject:
|
|
247
|
+
"""执行视图相关逻辑。"""
|
|
248
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
249
|
+
self._require_app_key(app_key)
|
|
250
|
+
self._require_positive("apply_id", apply_id)
|
|
251
|
+
return self._request(
|
|
252
|
+
profile,
|
|
253
|
+
"GET",
|
|
254
|
+
f"/view/{viewgraph_key}/auditNode/futureList/{apply_id}",
|
|
255
|
+
viewgraph_key=viewgraph_key,
|
|
256
|
+
app_key=app_key,
|
|
257
|
+
apply_id=apply_id,
|
|
258
|
+
params={"appKey": app_key},
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
@tool_cn_name("视图流程状态")
|
|
262
|
+
def view_get_workflow_status(self, *, profile: str, viewgraph_key: str, row_record_id: int) -> JSONObject:
|
|
263
|
+
"""执行视图相关逻辑。"""
|
|
264
|
+
self._require_viewgraph_key(viewgraph_key)
|
|
265
|
+
self._require_positive("row_record_id", row_record_id)
|
|
266
|
+
return self._request(profile, "GET", f"/view/{viewgraph_key}/workflow/status/{row_record_id}", viewgraph_key=viewgraph_key, row_record_id=row_record_id)
|
|
267
|
+
|
|
268
|
+
def _request(
|
|
269
|
+
self,
|
|
270
|
+
profile: str,
|
|
271
|
+
method: str,
|
|
272
|
+
path: str,
|
|
273
|
+
*,
|
|
274
|
+
json_body: JSONValue = None,
|
|
275
|
+
params: JSONObject | None = None,
|
|
276
|
+
risk_operation: str | None = None,
|
|
277
|
+
risk_target: str | None = None,
|
|
278
|
+
**extra: JSONValue,
|
|
279
|
+
) -> JSONObject:
|
|
280
|
+
"""执行内部辅助逻辑。"""
|
|
281
|
+
def runner(session_profile, context):
|
|
282
|
+
result = self.backend.request(method, context, path, json_body=json_body, params=params)
|
|
283
|
+
response: JSONObject = {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
|
|
284
|
+
response.update(extra)
|
|
285
|
+
if risk_operation and risk_target:
|
|
286
|
+
return self._attach_human_review_notice(response, operation=risk_operation, target=risk_target)
|
|
287
|
+
return response
|
|
288
|
+
|
|
289
|
+
return self._run(profile, runner)
|
|
290
|
+
|
|
291
|
+
def _require_app_key(self, app_key: str) -> None:
|
|
292
|
+
"""执行内部辅助逻辑。"""
|
|
293
|
+
if not app_key:
|
|
294
|
+
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
295
|
+
|
|
296
|
+
def _require_viewgraph_key(self, viewgraph_key: str) -> None:
|
|
297
|
+
"""执行内部辅助逻辑。"""
|
|
298
|
+
if not viewgraph_key:
|
|
299
|
+
raise_tool_error(QingflowApiError.config_error("viewgraph_key is required"))
|
|
300
|
+
|
|
301
|
+
def _require_positive(self, field_name: str, value: int) -> None:
|
|
302
|
+
"""执行内部辅助逻辑。"""
|
|
303
|
+
if value <= 0:
|
|
304
|
+
raise_tool_error(QingflowApiError.config_error(f"{field_name} must be positive"))
|
|
305
|
+
|
|
306
|
+
def _normalize_reorder_payload(self, payload: list[JSONObject]) -> list[JSONObject]:
|
|
307
|
+
"""执行内部辅助逻辑。"""
|
|
308
|
+
first_item = payload[0]
|
|
309
|
+
if "ordinalType" in first_item and "viewKeyList" in first_item:
|
|
310
|
+
return payload
|
|
311
|
+
if "ordinalType" in first_item and "viewList" in first_item:
|
|
312
|
+
normalized_groups: list[JSONObject] = []
|
|
313
|
+
for group in payload:
|
|
314
|
+
view_list = group.get("viewList")
|
|
315
|
+
view_keys = [
|
|
316
|
+
str(view.get("viewKey"))
|
|
317
|
+
for view in view_list
|
|
318
|
+
if isinstance(view_list, list) and isinstance(view, dict) and view.get("viewKey")
|
|
319
|
+
]
|
|
320
|
+
if group.get("ordinalType") and view_keys:
|
|
321
|
+
normalized_groups.append({"ordinalType": group["ordinalType"], "viewKeyList": view_keys})
|
|
322
|
+
if normalized_groups:
|
|
323
|
+
return normalized_groups
|
|
324
|
+
sorted_items = sorted(
|
|
325
|
+
payload,
|
|
326
|
+
key=lambda item: int(item.get("ordinal", payload.index(item))) if isinstance(item.get("ordinal"), int) else payload.index(item),
|
|
327
|
+
)
|
|
328
|
+
view_keys = [
|
|
329
|
+
str(item.get("viewgraphKey") or item.get("viewKey"))
|
|
330
|
+
for item in sorted_items
|
|
331
|
+
if item.get("viewgraphKey") or item.get("viewKey")
|
|
332
|
+
]
|
|
333
|
+
if not view_keys:
|
|
334
|
+
raise_tool_error(QingflowApiError.config_error("payload must include viewgraphKey/viewKey or ordinalType/viewKeyList"))
|
|
335
|
+
return [{"ordinalType": "FIXED_VIEW_LIST", "viewKeyList": view_keys}]
|