@josephyan/qingflow-cli 0.2.0-beta.58 → 0.2.0-beta.59

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.
Files changed (34) hide show
  1. package/README.md +3 -2
  2. package/docs/local-agent-install.md +9 -0
  3. package/npm/bin/qingflow.mjs +1 -1
  4. package/npm/lib/runtime.mjs +156 -21
  5. package/package.json +1 -1
  6. package/pyproject.toml +1 -1
  7. package/src/qingflow_mcp/builder_facade/service.py +137 -5
  8. package/src/qingflow_mcp/cli/commands/app.py +16 -16
  9. package/src/qingflow_mcp/cli/commands/auth.py +19 -16
  10. package/src/qingflow_mcp/cli/commands/builder.py +124 -162
  11. package/src/qingflow_mcp/cli/commands/common.py +21 -95
  12. package/src/qingflow_mcp/cli/commands/imports.py +42 -34
  13. package/src/qingflow_mcp/cli/commands/record.py +131 -133
  14. package/src/qingflow_mcp/cli/commands/task.py +43 -44
  15. package/src/qingflow_mcp/cli/commands/workspace.py +10 -10
  16. package/src/qingflow_mcp/cli/context.py +35 -32
  17. package/src/qingflow_mcp/cli/formatters.py +124 -121
  18. package/src/qingflow_mcp/cli/main.py +52 -17
  19. package/src/qingflow_mcp/server_app_builder.py +122 -190
  20. package/src/qingflow_mcp/server_app_user.py +63 -662
  21. package/src/qingflow_mcp/tools/solution_tools.py +95 -3
  22. package/src/qingflow_mcp/ops/__init__.py +0 -3
  23. package/src/qingflow_mcp/ops/apps.py +0 -64
  24. package/src/qingflow_mcp/ops/auth.py +0 -121
  25. package/src/qingflow_mcp/ops/base.py +0 -290
  26. package/src/qingflow_mcp/ops/builder.py +0 -357
  27. package/src/qingflow_mcp/ops/context.py +0 -120
  28. package/src/qingflow_mcp/ops/directory.py +0 -171
  29. package/src/qingflow_mcp/ops/feedback.py +0 -49
  30. package/src/qingflow_mcp/ops/files.py +0 -78
  31. package/src/qingflow_mcp/ops/imports.py +0 -140
  32. package/src/qingflow_mcp/ops/records.py +0 -415
  33. package/src/qingflow_mcp/ops/tasks.py +0 -171
  34. package/src/qingflow_mcp/ops/workspace.py +0 -76
@@ -1,357 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any
4
-
5
- from .base import normalize_tool_error, success_result, tool_payload
6
-
7
-
8
- class BuilderOperations:
9
- def __init__(self, tools: Any) -> None:
10
- self._tools = tools
11
-
12
- def package_list(self, *, profile: str, trial_status: str) -> dict:
13
- return self._call("PACKAGES_READY", "已读取应用包列表", self._tools.builder.package_list(profile=profile, trial_status=trial_status))
14
-
15
- def package_resolve(self, *, profile: str, package_name: str) -> dict:
16
- return self._call("PACKAGE_RESOLVED", "已解析应用包", self._tools.builder.package_resolve(profile=profile, package_name=package_name))
17
-
18
- def builder_tool_contract(self, *, tool_name: str) -> dict:
19
- return self._call("BUILDER_TOOL_CONTRACT_READY", "已读取工具契约", self._tools.builder.builder_tool_contract(tool_name=tool_name))
20
-
21
- def package_create(self, *, profile: str, package_name: str) -> dict:
22
- return self._call("PACKAGE_CREATED", "已创建应用包", self._tools.builder.package_create(profile=profile, package_name=package_name))
23
-
24
- def member_search(
25
- self,
26
- *,
27
- profile: str,
28
- query: str,
29
- page_num: int,
30
- page_size: int,
31
- contain_disable: bool,
32
- ) -> dict:
33
- return self._call(
34
- "MEMBERS_READY",
35
- "已读取成员候选",
36
- self._tools.builder.member_search(
37
- profile=profile,
38
- query=query,
39
- page_num=page_num,
40
- page_size=page_size,
41
- contain_disable=contain_disable,
42
- ),
43
- )
44
-
45
- def role_search(self, *, profile: str, keyword: str, page_num: int, page_size: int) -> dict:
46
- return self._call(
47
- "ROLES_READY",
48
- "已读取角色候选",
49
- self._tools.builder.role_search(profile=profile, keyword=keyword, page_num=page_num, page_size=page_size),
50
- )
51
-
52
- def role_create(
53
- self,
54
- *,
55
- profile: str,
56
- role_name: str,
57
- member_uids: list[int],
58
- member_emails: list[str],
59
- member_names: list[str],
60
- role_icon: str,
61
- ) -> dict:
62
- return self._call(
63
- "ROLE_CREATED",
64
- "已创建角色",
65
- self._tools.builder.role_create(
66
- profile=profile,
67
- role_name=role_name,
68
- member_uids=member_uids,
69
- member_emails=member_emails,
70
- member_names=member_names,
71
- role_icon=role_icon,
72
- ),
73
- )
74
-
75
- def package_attach_app(self, *, profile: str, tag_id: int, app_key: str, app_title: str) -> dict:
76
- return self._call(
77
- "PACKAGE_APP_ATTACHED",
78
- "已挂载应用到应用包",
79
- self._tools.builder.package_attach_app(profile=profile, tag_id=tag_id, app_key=app_key, app_title=app_title),
80
- )
81
-
82
- def release_edit_lock_if_mine(
83
- self,
84
- *,
85
- profile: str,
86
- app_key: str,
87
- lock_owner_email: str,
88
- lock_owner_name: str,
89
- ) -> dict:
90
- return self._call(
91
- "APP_EDIT_LOCK_RELEASED",
92
- "已释放编辑锁",
93
- self._tools.builder.app_release_edit_lock_if_mine(
94
- profile=profile,
95
- app_key=app_key,
96
- lock_owner_email=lock_owner_email,
97
- lock_owner_name=lock_owner_name,
98
- ),
99
- )
100
-
101
- def app_resolve(self, *, profile: str, app_key: str, app_name: str, package_tag_id: int | None) -> dict:
102
- return self._call(
103
- "APP_RESOLVED",
104
- "已解析应用",
105
- self._tools.builder.app_resolve(
106
- profile=profile,
107
- app_key=app_key,
108
- app_name=app_name,
109
- package_tag_id=package_tag_id,
110
- ),
111
- )
112
-
113
- def app_show(self, *, profile: str, app_key: str) -> dict:
114
- return self._call("APP_SUMMARY_READY", "已读取应用摘要", self._tools.builder.app_read_summary(profile=profile, app_key=app_key))
115
-
116
- def fields_show(self, *, profile: str, app_key: str) -> dict:
117
- return self._call("FIELDS_READY", "已读取字段摘要", self._tools.builder.app_read_fields(profile=profile, app_key=app_key))
118
-
119
- def layout_show(self, *, profile: str, app_key: str) -> dict:
120
- return self._call("LAYOUT_READY", "已读取布局摘要", self._tools.builder.app_read_layout_summary(profile=profile, app_key=app_key))
121
-
122
- def views_show(self, *, profile: str, app_key: str) -> dict:
123
- return self._call("VIEWS_READY", "已读取视图摘要", self._tools.builder.app_read_views_summary(profile=profile, app_key=app_key))
124
-
125
- def flow_show(self, *, profile: str, app_key: str) -> dict:
126
- return self._call("FLOW_READY", "已读取流程摘要", self._tools.builder.app_read_flow_summary(profile=profile, app_key=app_key))
127
-
128
- def charts_show(self, *, profile: str, app_key: str) -> dict:
129
- return self._call("CHARTS_READY", "已读取报表摘要", self._tools.builder.app_read_charts_summary(profile=profile, app_key=app_key))
130
-
131
- def portal_show(self, *, profile: str, dash_key: str, being_draft: bool) -> dict:
132
- return self._call(
133
- "PORTAL_READY",
134
- "已读取门户摘要",
135
- self._tools.builder.portal_read_summary(profile=profile, dash_key=dash_key, being_draft=being_draft),
136
- )
137
-
138
- def fields_apply(
139
- self,
140
- *,
141
- profile: str,
142
- app_key: str,
143
- package_tag_id: int | None,
144
- app_name: str,
145
- app_title: str,
146
- create_if_missing: bool,
147
- publish: bool,
148
- add_fields: list[Any],
149
- update_fields: list[Any],
150
- remove_fields: list[Any],
151
- ) -> dict:
152
- return self._call(
153
- "FIELDS_APPLIED",
154
- "已执行字段变更",
155
- self._tools.builder.app_schema_apply(
156
- profile=profile,
157
- app_key=app_key,
158
- package_tag_id=package_tag_id,
159
- app_name=app_name,
160
- app_title=app_title,
161
- create_if_missing=create_if_missing,
162
- publish=publish,
163
- add_fields=[_normalize_field_spec(item) for item in add_fields],
164
- update_fields=[_normalize_field_update(item) for item in update_fields],
165
- remove_fields=[_normalize_field_selector(item) for item in remove_fields],
166
- ),
167
- )
168
-
169
- def layout_apply(
170
- self,
171
- *,
172
- profile: str,
173
- app_key: str,
174
- mode: str,
175
- publish: bool,
176
- sections: list[Any],
177
- ) -> dict:
178
- return self._call(
179
- "LAYOUT_APPLIED",
180
- "已执行布局变更",
181
- self._tools.builder.app_layout_apply(
182
- profile=profile,
183
- app_key=app_key,
184
- mode=mode,
185
- publish=publish,
186
- sections=sections,
187
- ),
188
- )
189
-
190
- def flow_apply(
191
- self,
192
- *,
193
- profile: str,
194
- app_key: str,
195
- mode: str,
196
- publish: bool,
197
- nodes: list[Any],
198
- transitions: list[Any],
199
- ) -> dict:
200
- return self._call(
201
- "FLOW_APPLIED",
202
- "已执行流程变更",
203
- self._tools.builder.app_flow_apply(
204
- profile=profile,
205
- app_key=app_key,
206
- mode=mode,
207
- publish=publish,
208
- nodes=nodes,
209
- transitions=transitions,
210
- ),
211
- )
212
-
213
- def views_apply(
214
- self,
215
- *,
216
- profile: str,
217
- app_key: str,
218
- publish: bool,
219
- upsert_views: list[Any],
220
- remove_views: list[Any],
221
- ) -> dict:
222
- return self._call(
223
- "VIEWS_APPLIED",
224
- "已执行视图变更",
225
- self._tools.builder.app_views_apply(
226
- profile=profile,
227
- app_key=app_key,
228
- publish=publish,
229
- upsert_views=upsert_views,
230
- remove_views=remove_views,
231
- ),
232
- )
233
-
234
- def charts_apply(
235
- self,
236
- *,
237
- profile: str,
238
- app_key: str,
239
- upsert_charts: list[Any],
240
- remove_chart_ids: list[Any],
241
- reorder_chart_ids: list[Any],
242
- ) -> dict:
243
- return self._call(
244
- "CHARTS_APPLIED",
245
- "已执行报表变更",
246
- self._tools.builder.app_charts_apply(
247
- profile=profile,
248
- app_key=app_key,
249
- upsert_charts=upsert_charts,
250
- remove_chart_ids=remove_chart_ids,
251
- reorder_chart_ids=reorder_chart_ids,
252
- ),
253
- )
254
-
255
- def portal_apply(
256
- self,
257
- *,
258
- profile: str,
259
- dash_key: str,
260
- dash_name: str,
261
- package_tag_id: int | None,
262
- publish: bool,
263
- sections: list[Any],
264
- auth: dict | None,
265
- icon: str | None,
266
- color: str | None,
267
- hide_copyright: bool | None,
268
- dash_global_config: dict | None,
269
- config: dict | None,
270
- ) -> dict:
271
- return self._call(
272
- "PORTAL_APPLIED",
273
- "已执行门户变更",
274
- self._tools.builder.portal_apply(
275
- profile=profile,
276
- dash_key=dash_key,
277
- dash_name=dash_name,
278
- package_tag_id=package_tag_id,
279
- publish=publish,
280
- sections=sections,
281
- auth=auth,
282
- icon=icon,
283
- color=color,
284
- hide_copyright=hide_copyright,
285
- dash_global_config=dash_global_config,
286
- config=config,
287
- ),
288
- )
289
-
290
- def publish_verify(self, *, profile: str, app_key: str, expected_package_tag_id: int | None) -> dict:
291
- return self._call(
292
- "PUBLISH_VERIFIED",
293
- "已完成发布校验",
294
- self._tools.builder.app_publish_verify(
295
- profile=profile,
296
- app_key=app_key,
297
- expected_package_tag_id=expected_package_tag_id,
298
- ),
299
- )
300
-
301
- def _call(self, code: str, message: str, raw: Any) -> dict:
302
- if isinstance(raw, dict) and (raw.get("ok") is False or str(raw.get("status") or "").lower() in {"failed", "blocked"}):
303
- return normalize_tool_error(raw)
304
- warnings = raw.get("warnings") if isinstance(raw, dict) and isinstance(raw.get("warnings"), list) else []
305
- meta = {}
306
- if isinstance(raw, dict):
307
- if raw.get("profile") is not None:
308
- meta["profile"] = raw.get("profile")
309
- if raw.get("request_id") is not None:
310
- meta["request_id"] = raw.get("request_id")
311
- if raw.get("request_route") is not None:
312
- meta["request_route"] = raw.get("request_route")
313
- if raw.get("verification") not in (None, {}):
314
- meta["verification"] = raw.get("verification")
315
- data = tool_payload(raw)
316
- if isinstance(data, dict):
317
- normalized_args = data.pop("normalized_args", None)
318
- verified = data.pop("verified", None)
319
- if normalized_args is not None:
320
- meta["normalized_args"] = normalized_args
321
- if verified is not None:
322
- meta["verified"] = verified
323
- return success_result(code, message, data=data, warnings=warnings, meta=meta, legacy=raw)
324
-
325
-
326
- def _normalize_field_spec(value: Any) -> Any:
327
- if not isinstance(value, dict):
328
- return value
329
- normalized = dict(value)
330
- if "name" not in normalized and isinstance(normalized.get("field_name"), str):
331
- normalized["name"] = normalized["field_name"]
332
- if "type" not in normalized and isinstance(normalized.get("field_type"), str):
333
- normalized["type"] = normalized["field_type"]
334
- normalized.pop("field_name", None)
335
- normalized.pop("field_type", None)
336
- return normalized
337
-
338
-
339
- def _normalize_field_selector(value: Any) -> Any:
340
- if not isinstance(value, dict):
341
- return value
342
- normalized = dict(value)
343
- if "name" not in normalized and isinstance(normalized.get("field_name"), str):
344
- normalized["name"] = normalized["field_name"]
345
- normalized.pop("field_name", None)
346
- return normalized
347
-
348
-
349
- def _normalize_field_update(value: Any) -> Any:
350
- if not isinstance(value, dict):
351
- return value
352
- normalized = dict(value)
353
- if isinstance(normalized.get("selector"), dict):
354
- normalized["selector"] = _normalize_field_selector(normalized["selector"])
355
- if isinstance(normalized.get("set"), dict):
356
- normalized["set"] = _normalize_field_spec(normalized["set"])
357
- return normalized
@@ -1,120 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
-
5
- from ..backend_client import BackendClient
6
- from ..builder_facade.service import AiBuilderFacade
7
- from ..session_store import SessionStore
8
- from ..tools.ai_builder_tools import AiBuilderTools
9
- from ..tools.app_tools import AppTools
10
- from ..tools.auth_tools import AuthTools
11
- from ..tools.code_block_tools import CodeBlockTools
12
- from ..tools.directory_tools import DirectoryTools
13
- from ..tools.feedback_tools import FeedbackTools
14
- from ..tools.file_tools import FileTools
15
- from ..tools.import_tools import ImportTools
16
- from ..tools.package_tools import PackageTools
17
- from ..tools.portal_tools import PortalTools
18
- from ..tools.qingbi_report_tools import QingbiReportTools
19
- from ..tools.record_tools import RecordTools
20
- from ..tools.role_tools import RoleTools
21
- from ..tools.solution_tools import SolutionTools
22
- from ..tools.task_context_tools import TaskContextTools
23
- from ..tools.view_tools import ViewTools
24
- from ..tools.workflow_tools import WorkflowTools
25
- from ..tools.workspace_tools import WorkspaceTools
26
- from .apps import AppOperations
27
- from .auth import AuthOperations
28
- from .builder import BuilderOperations
29
- from .directory import DirectoryOperations
30
- from .feedback import FeedbackOperations
31
- from .files import FileOperations
32
- from .imports import ImportOperations
33
- from .records import RecordOperations
34
- from .tasks import TaskOperations
35
- from .workspace import WorkspaceOperations
36
-
37
-
38
- @dataclass(slots=True)
39
- class Toolset:
40
- auth: AuthTools
41
- workspace: WorkspaceTools
42
- app: AppTools
43
- file: FileTools
44
- feedback: FeedbackTools
45
- directory: DirectoryTools
46
- record: RecordTools
47
- code_block: CodeBlockTools
48
- imports: ImportTools
49
- task: TaskContextTools
50
- builder: AiBuilderTools
51
- facade: AiBuilderFacade
52
-
53
-
54
- @dataclass(slots=True)
55
- class OperationsRuntime:
56
- sessions: SessionStore
57
- backend: BackendClient
58
- tools: Toolset
59
- auth: AuthOperations
60
- workspace: WorkspaceOperations
61
- apps: AppOperations
62
- files: FileOperations
63
- feedback: FeedbackOperations
64
- directory: DirectoryOperations
65
- records: RecordOperations
66
- imports: ImportOperations
67
- tasks: TaskOperations
68
- builder: BuilderOperations
69
-
70
- def close(self) -> None:
71
- self.backend.close()
72
-
73
- def build_operations_runtime(
74
- *,
75
- sessions: SessionStore | None = None,
76
- backend: BackendClient | None = None,
77
- feedback_mcp_side: str = "CLI",
78
- ) -> OperationsRuntime:
79
- sessions = sessions or SessionStore()
80
- backend = backend or BackendClient()
81
- facade = AiBuilderFacade(
82
- apps=AppTools(sessions, backend),
83
- packages=PackageTools(sessions, backend),
84
- views=ViewTools(sessions, backend),
85
- workflows=WorkflowTools(sessions, backend),
86
- portals=PortalTools(sessions, backend),
87
- charts=QingbiReportTools(sessions, backend),
88
- roles=RoleTools(sessions, backend),
89
- directory=DirectoryTools(sessions, backend),
90
- solutions=SolutionTools(sessions, backend),
91
- )
92
- tools = Toolset(
93
- auth=AuthTools(sessions, backend),
94
- workspace=WorkspaceTools(sessions, backend),
95
- app=AppTools(sessions, backend),
96
- file=FileTools(sessions, backend),
97
- feedback=FeedbackTools(backend, mcp_side=feedback_mcp_side),
98
- directory=DirectoryTools(sessions, backend),
99
- record=RecordTools(sessions, backend),
100
- code_block=CodeBlockTools(sessions, backend),
101
- imports=ImportTools(sessions, backend),
102
- task=TaskContextTools(sessions, backend),
103
- builder=AiBuilderTools(sessions, backend),
104
- facade=facade,
105
- )
106
- return OperationsRuntime(
107
- sessions=sessions,
108
- backend=backend,
109
- tools=tools,
110
- auth=AuthOperations(tools),
111
- workspace=WorkspaceOperations(tools),
112
- apps=AppOperations(tools),
113
- files=FileOperations(tools),
114
- feedback=FeedbackOperations(tools),
115
- directory=DirectoryOperations(tools),
116
- records=RecordOperations(tools),
117
- imports=ImportOperations(tools),
118
- tasks=TaskOperations(tools),
119
- builder=BuilderOperations(tools),
120
- )
@@ -1,171 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any
4
-
5
- from .base import normalize_exception, success_result, tool_payload
6
-
7
-
8
- class DirectoryOperations:
9
- def __init__(self, tools: Any) -> None:
10
- self._tools = tools
11
-
12
- def search(
13
- self,
14
- *,
15
- profile: str,
16
- query: str,
17
- scopes: list[str] | None,
18
- page_num: int,
19
- page_size: int,
20
- ) -> dict:
21
- return self._call(
22
- "DIRECTORY_SEARCH_READY",
23
- "已完成目录搜索",
24
- profile=profile,
25
- raw_call=lambda: self._tools.directory.directory_search(
26
- profile=profile,
27
- query=query,
28
- scopes=scopes,
29
- page_num=page_num,
30
- page_size=page_size,
31
- ),
32
- )
33
-
34
- def list_internal_users(
35
- self,
36
- *,
37
- profile: str,
38
- keyword: str | None,
39
- department_id: int | None,
40
- role_id: int | None,
41
- page_num: int,
42
- page_size: int,
43
- include_disabled: bool,
44
- ) -> dict:
45
- return self._call(
46
- "DIRECTORY_INTERNAL_USERS_READY",
47
- "已读取内部成员",
48
- profile=profile,
49
- raw_call=lambda: self._tools.directory.directory_list_internal_users(
50
- profile=profile,
51
- keyword=keyword,
52
- dept_id=department_id,
53
- role_id=role_id,
54
- page_num=page_num,
55
- page_size=page_size,
56
- contain_disable=include_disabled,
57
- ),
58
- )
59
-
60
- def list_all_internal_users(
61
- self,
62
- *,
63
- profile: str,
64
- keyword: str | None,
65
- department_id: int | None,
66
- role_id: int | None,
67
- page_size: int,
68
- include_disabled: bool,
69
- max_pages: int,
70
- ) -> dict:
71
- return self._call(
72
- "DIRECTORY_ALL_INTERNAL_USERS_READY",
73
- "已读取全部内部成员",
74
- profile=profile,
75
- raw_call=lambda: self._tools.directory.directory_list_all_internal_users(
76
- profile=profile,
77
- keyword=keyword,
78
- dept_id=department_id,
79
- role_id=role_id,
80
- page_size=page_size,
81
- contain_disable=include_disabled,
82
- max_pages=max_pages,
83
- ),
84
- )
85
-
86
- def list_internal_departments(
87
- self,
88
- *,
89
- profile: str,
90
- keyword: str,
91
- page_num: int,
92
- page_size: int,
93
- ) -> dict:
94
- return self._call(
95
- "DIRECTORY_INTERNAL_DEPARTMENTS_READY",
96
- "已读取内部部门",
97
- profile=profile,
98
- raw_call=lambda: self._tools.directory.directory_list_internal_departments(
99
- profile=profile,
100
- keyword=keyword,
101
- page_num=page_num,
102
- page_size=page_size,
103
- ),
104
- )
105
-
106
- def list_all_departments(
107
- self,
108
- *,
109
- profile: str,
110
- parent_department_id: int | None,
111
- max_depth: int,
112
- max_items: int,
113
- ) -> dict:
114
- return self._call(
115
- "DIRECTORY_ALL_DEPARTMENTS_READY",
116
- "已读取全部部门",
117
- profile=profile,
118
- raw_call=lambda: self._tools.directory.directory_list_all_departments(
119
- profile=profile,
120
- parent_dept_id=parent_department_id,
121
- max_depth=max_depth,
122
- max_items=max_items,
123
- ),
124
- )
125
-
126
- def list_sub_departments(self, *, profile: str, parent_department_id: int | None) -> dict:
127
- return self._call(
128
- "DIRECTORY_SUB_DEPARTMENTS_READY",
129
- "已读取子部门",
130
- profile=profile,
131
- raw_call=lambda: self._tools.directory.directory_list_sub_departments(
132
- profile=profile,
133
- parent_dept_id=parent_department_id,
134
- ),
135
- )
136
-
137
- def list_external_members(
138
- self,
139
- *,
140
- profile: str,
141
- keyword: str | None,
142
- page_num: int,
143
- page_size: int,
144
- simple: bool,
145
- ) -> dict:
146
- return self._call(
147
- "DIRECTORY_EXTERNAL_MEMBERS_READY",
148
- "已读取外部联系人",
149
- profile=profile,
150
- raw_call=lambda: self._tools.directory.directory_list_external_members(
151
- profile=profile,
152
- keyword=keyword,
153
- page_num=page_num,
154
- page_size=page_size,
155
- simple=simple,
156
- ),
157
- )
158
-
159
- def _call(self, code: str, message: str, *, profile: str, raw_call: Any) -> dict:
160
- try:
161
- raw = raw_call()
162
- except Exception as error: # noqa: BLE001
163
- return normalize_exception(error)
164
- return success_result(
165
- code,
166
- message,
167
- data=tool_payload(raw) if isinstance(tool_payload(raw), dict) else raw,
168
- warnings=raw.get("warnings") if isinstance(raw, dict) and isinstance(raw.get("warnings"), list) else [],
169
- meta={"profile": profile, "request_route": raw.get("request_route") if isinstance(raw, dict) else None},
170
- legacy=raw,
171
- )
@@ -1,49 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any
4
-
5
- from .base import normalize_exception, success_result, tool_payload
6
-
7
-
8
- class FeedbackOperations:
9
- def __init__(self, tools: Any) -> None:
10
- self._tools = tools
11
-
12
- def submit(
13
- self,
14
- *,
15
- category: str,
16
- title: str,
17
- description: str,
18
- expected_behavior: str | None,
19
- actual_behavior: str | None,
20
- impact_scope: str | None,
21
- tool_name: str | None,
22
- app_key: str | None,
23
- record_id: str | int | None,
24
- workflow_node_id: str | int | None,
25
- note: str | None,
26
- ) -> dict:
27
- try:
28
- raw = self._tools.feedback.feedback_submit(
29
- category=category,
30
- title=title,
31
- description=description,
32
- expected_behavior=expected_behavior,
33
- actual_behavior=actual_behavior,
34
- impact_scope=impact_scope,
35
- tool_name=tool_name,
36
- app_key=app_key,
37
- record_id=record_id,
38
- workflow_node_id=workflow_node_id,
39
- note=note,
40
- )
41
- except Exception as error: # noqa: BLE001
42
- return normalize_exception(error)
43
- return success_result(
44
- "FEEDBACK_SUBMITTED",
45
- "已提交需求反馈",
46
- data=tool_payload(raw) if isinstance(tool_payload(raw), dict) else raw,
47
- meta={"request_route": raw.get("request_route") if isinstance(raw, dict) else None},
48
- legacy=raw,
49
- )