@qingflow-tech/qingflow-cli 1.1.39 → 1.1.41

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 (32) hide show
  1. package/README.md +3 -3
  2. package/package.json +1 -1
  3. package/pyproject.toml +1 -1
  4. package/src/qingflow_mcp/builder_facade/service.py +8 -8
  5. package/src/qingflow_mcp/server_cloud.py +89 -3
  6. package/src/qingflow_mcp/session_store.py +7 -1
  7. package/src/qingflow_mcp/tools/ai_builder_tools.py +1 -59
  8. package/src/qingflow_mcp/tools/app_tools.py +15 -29
  9. package/src/qingflow_mcp/tools/approval_tools.py +16 -40
  10. package/src/qingflow_mcp/tools/auth_tools.py +18 -13
  11. package/src/qingflow_mcp/tools/base.py +114 -74
  12. package/src/qingflow_mcp/tools/code_block_tools.py +2 -5
  13. package/src/qingflow_mcp/tools/custom_button_tools.py +6 -11
  14. package/src/qingflow_mcp/tools/directory_tools.py +9 -16
  15. package/src/qingflow_mcp/tools/export_tools.py +5 -9
  16. package/src/qingflow_mcp/tools/feedback_tools.py +0 -2
  17. package/src/qingflow_mcp/tools/file_tools.py +3 -5
  18. package/src/qingflow_mcp/tools/import_tools.py +7 -13
  19. package/src/qingflow_mcp/tools/navigation_tools.py +12 -23
  20. package/src/qingflow_mcp/tools/package_tools.py +11 -21
  21. package/src/qingflow_mcp/tools/portal_tools.py +9 -17
  22. package/src/qingflow_mcp/tools/qingbi_report_tools.py +18 -23
  23. package/src/qingflow_mcp/tools/record_tools.py +97 -53
  24. package/src/qingflow_mcp/tools/repository_dev_tools.py +4 -7
  25. package/src/qingflow_mcp/tools/resource_read_tools.py +6 -9
  26. package/src/qingflow_mcp/tools/role_tools.py +5 -9
  27. package/src/qingflow_mcp/tools/solution_tools.py +4 -16
  28. package/src/qingflow_mcp/tools/task_context_tools.py +6 -12
  29. package/src/qingflow_mcp/tools/task_tools.py +12 -29
  30. package/src/qingflow_mcp/tools/view_tools.py +23 -32
  31. package/src/qingflow_mcp/tools/workflow_tools.py +30 -47
  32. package/src/qingflow_mcp/tools/workspace_tools.py +5 -9
@@ -5,7 +5,7 @@ from copy import deepcopy
5
5
  from ..config import DEFAULT_PROFILE
6
6
  from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, raise_tool_error
7
7
  from ..json_types import JSONObject
8
- from .base import ToolBase, tool_cn_name
8
+ from .base import ToolBase
9
9
 
10
10
 
11
11
  class CustomButtonTools(ToolBase):
@@ -18,7 +18,6 @@ class CustomButtonTools(ToolBase):
18
18
  3. 支持草稿与发布态按钮配置维护。
19
19
  """
20
20
 
21
- @tool_cn_name("自定义按钮列表")
22
21
  def custom_button_list(
23
22
  self,
24
23
  *,
@@ -82,9 +81,8 @@ class CustomButtonTools(ToolBase):
82
81
  response["summary"] = items
83
82
  return response
84
83
 
85
- return self._run(profile, runner)
84
+ return self._run(profile, runner, tool_name='自定义按钮列表')
86
85
 
87
- @tool_cn_name("自定义按钮详情")
88
86
  def custom_button_get(
89
87
  self,
90
88
  *,
@@ -135,9 +133,8 @@ class CustomButtonTools(ToolBase):
135
133
  response["summary"] = self._compact_button_detail(result if isinstance(result, dict) else {})
136
134
  return response
137
135
 
138
- return self._run(profile, runner)
136
+ return self._run(profile, runner, tool_name='自定义按钮详情')
139
137
 
140
- @tool_cn_name("创建自定义按钮")
141
138
  def custom_button_create(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
142
139
  """执行工具方法逻辑。"""
143
140
  self._require_app_key(app_key)
@@ -147,9 +144,8 @@ class CustomButtonTools(ToolBase):
147
144
  result = self.backend.request("POST", context, f"/app/{app_key}/customButton", json_body=deepcopy(body))
148
145
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "app_key": app_key, "result": result}
149
146
 
150
- return self._run(profile, runner)
147
+ return self._run(profile, runner, tool_name='创建自定义按钮')
151
148
 
152
- @tool_cn_name("更新自定义按钮")
153
149
  def custom_button_update(self, *, profile: str, app_key: str, button_id: int, payload: JSONObject) -> JSONObject:
154
150
  """执行工具方法逻辑。"""
155
151
  self._require_app_key(app_key)
@@ -175,9 +171,8 @@ class CustomButtonTools(ToolBase):
175
171
  target="custom button configuration",
176
172
  )
177
173
 
178
- return self._run(profile, runner)
174
+ return self._run(profile, runner, tool_name='更新自定义按钮')
179
175
 
180
- @tool_cn_name("删除自定义按钮")
181
176
  def custom_button_delete(self, *, profile: str, app_key: str, button_id: int) -> JSONObject:
182
177
  """执行工具方法逻辑。"""
183
178
  self._require_app_key(app_key)
@@ -197,7 +192,7 @@ class CustomButtonTools(ToolBase):
197
192
  target="custom button configuration",
198
193
  )
199
194
 
200
- return self._run(profile, runner)
195
+ return self._run(profile, runner, tool_name='删除自定义按钮')
201
196
 
202
197
  def _require_app_key(self, app_key: str) -> None:
203
198
  """执行内部辅助逻辑。"""
@@ -7,7 +7,7 @@ from mcp.server.fastmcp import FastMCP
7
7
 
8
8
  from ..config import DEFAULT_PROFILE
9
9
  from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, raise_tool_error
10
- from .base import ToolBase, tool_cn_name
10
+ from .base import ToolBase
11
11
 
12
12
 
13
13
  ALLOWED_DIRECTORY_SEARCH_SCOPES = {"MEMBER", "DEPT"}
@@ -139,7 +139,6 @@ class DirectoryTools(ToolBase):
139
139
  page_size=page_size,
140
140
  )
141
141
 
142
- @tool_cn_name("通讯录搜索")
143
142
  def directory_search(
144
143
  self,
145
144
  *,
@@ -187,7 +186,7 @@ class DirectoryTools(ToolBase):
187
186
  "result": result,
188
187
  }
189
188
 
190
- raw = self._run(profile, runner)
189
+ raw = self._run(profile, runner, tool_name='通讯录搜索')
191
190
  items = [item for item in _directory_items(raw.get("result")) if isinstance(item, dict)]
192
191
  return self._public_directory_response(
193
192
  raw,
@@ -202,7 +201,6 @@ class DirectoryTools(ToolBase):
202
201
  selection={"query": query, "scopes": normalized_scopes},
203
202
  )
204
203
 
205
- @tool_cn_name("内部成员列表")
206
204
  def directory_list_internal_users(
207
205
  self,
208
206
  *,
@@ -246,7 +244,7 @@ class DirectoryTools(ToolBase):
246
244
  "result": result,
247
245
  }
248
246
 
249
- raw = self._run(profile, runner)
247
+ raw = self._run(profile, runner, tool_name='内部成员列表')
250
248
  items = [item for item in _directory_items(raw.get("result")) if isinstance(item, dict)]
251
249
  return self._public_directory_response(
252
250
  raw,
@@ -261,7 +259,6 @@ class DirectoryTools(ToolBase):
261
259
  selection={"keyword": keyword, "department_id": dept_id, "role_id": role_id, "include_disabled": contain_disable},
262
260
  )
263
261
 
264
- @tool_cn_name("内部成员全量")
265
262
  def directory_list_all_internal_users(
266
263
  self,
267
264
  *,
@@ -343,7 +340,7 @@ class DirectoryTools(ToolBase):
343
340
  },
344
341
  }
345
342
 
346
- raw = self._run(profile, runner)
343
+ raw = self._run(profile, runner, tool_name='内部成员全量')
347
344
  return self._public_directory_response(
348
345
  raw,
349
346
  items=[item for item in raw.get("items", []) if isinstance(item, dict)],
@@ -351,7 +348,6 @@ class DirectoryTools(ToolBase):
351
348
  selection={"keyword": keyword, "department_id": dept_id, "role_id": role_id, "include_disabled": contain_disable},
352
349
  )
353
350
 
354
- @tool_cn_name("内部部门列表")
355
351
  def directory_list_internal_departments(
356
352
  self,
357
353
  *,
@@ -408,7 +404,7 @@ class DirectoryTools(ToolBase):
408
404
  },
409
405
  }
410
406
 
411
- raw = self._run(profile, runner)
407
+ raw = self._run(profile, runner, tool_name='内部部门列表')
412
408
  items = [item for item in raw.get("items", []) if isinstance(item, dict)]
413
409
  return self._public_directory_response(
414
410
  raw,
@@ -449,7 +445,7 @@ class DirectoryTools(ToolBase):
449
445
  "result": result,
450
446
  }
451
447
 
452
- raw = self._run(profile, runner)
448
+ raw = self._run(profile, runner, tool_name='内部部门列表')
453
449
  items = [item for item in _directory_items(raw.get("page")) if isinstance(item, dict)]
454
450
  return self._public_directory_response(
455
451
  raw,
@@ -464,7 +460,6 @@ class DirectoryTools(ToolBase):
464
460
  selection={"keyword": normalized_keyword},
465
461
  )
466
462
 
467
- @tool_cn_name("部门树全量")
468
463
  def directory_list_all_departments(
469
464
  self,
470
465
  *,
@@ -519,7 +514,7 @@ class DirectoryTools(ToolBase):
519
514
  },
520
515
  }
521
516
 
522
- raw = self._run(profile, runner)
517
+ raw = self._run(profile, runner, tool_name='部门树全量')
523
518
  return self._public_directory_response(
524
519
  raw,
525
520
  items=[item for item in raw.get("items", []) if isinstance(item, dict)],
@@ -527,7 +522,6 @@ class DirectoryTools(ToolBase):
527
522
  selection={"parent_department_id": parent_dept_id, "max_depth": max_depth, "max_items": max_items},
528
523
  )
529
524
 
530
- @tool_cn_name("子部门列表")
531
525
  def directory_list_sub_departments(self, *, profile: str, parent_dept_id: int | None) -> dict[str, Any]:
532
526
  """执行组织目录相关逻辑。"""
533
527
  def runner(session_profile, context):
@@ -553,7 +547,7 @@ class DirectoryTools(ToolBase):
553
547
  "items": result,
554
548
  }
555
549
 
556
- raw = self._run(profile, runner)
550
+ raw = self._run(profile, runner, tool_name='子部门列表')
557
551
  items = [item for item in raw.get("items", []) if isinstance(item, dict)]
558
552
  return self._public_directory_response(
559
553
  raw,
@@ -562,7 +556,6 @@ class DirectoryTools(ToolBase):
562
556
  selection={"parent_department_id": parent_dept_id},
563
557
  )
564
558
 
565
- @tool_cn_name("外部联系人列表")
566
559
  def directory_list_external_members(
567
560
  self,
568
561
  *,
@@ -618,7 +611,7 @@ class DirectoryTools(ToolBase):
618
611
  "simple": simple,
619
612
  }
620
613
 
621
- raw = self._run(profile, runner)
614
+ raw = self._run(profile, runner, tool_name='外部联系人列表')
622
615
  items = [item for item in _directory_items(raw.get("page")) if isinstance(item, dict)]
623
616
  return self._public_directory_response(
624
617
  raw,
@@ -16,7 +16,7 @@ from ..config import DEFAULT_PROFILE, DEFAULT_RECORD_LIST_TYPE
16
16
  from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, message_looks_like_invalid_token
17
17
  from ..export_store import ExportJobStore
18
18
  from ..json_types import JSONObject
19
- from .base import ToolBase, tool_cn_name
19
+ from .base import ToolBase
20
20
  from .record_tools import (
21
21
  AccessibleViewRoute,
22
22
  DEFAULT_LIST_PAGE_SIZE,
@@ -131,7 +131,6 @@ class ExportTools(ToolBase):
131
131
  wait_timeout_seconds=wait_timeout_seconds,
132
132
  )
133
133
 
134
- @tool_cn_name("记录导出启动")
135
134
  def record_export_start(
136
135
  self,
137
136
  *,
@@ -277,7 +276,7 @@ class ExportTools(ToolBase):
277
276
  }
278
277
 
279
278
  try:
280
- return self._run(profile, runner)
279
+ return self._run(profile, runner, tool_name='记录导出启动')
281
280
  except RuntimeError as exc:
282
281
  return self._runtime_error_as_result(
283
282
  exc,
@@ -285,7 +284,6 @@ class ExportTools(ToolBase):
285
284
  extra={"app_key": normalized_app_key, "view_id": normalized_view_id},
286
285
  )
287
286
 
288
- @tool_cn_name("记录导出状态")
289
287
  def record_export_status_get(
290
288
  self,
291
289
  *,
@@ -318,7 +316,7 @@ class ExportTools(ToolBase):
318
316
  return self._status_payload_from_snapshot(local_job, normalized_handle, snapshot)
319
317
 
320
318
  try:
321
- return self._run(profile, runner)
319
+ return self._run(profile, runner, tool_name='记录导出状态')
322
320
  except RuntimeError as exc:
323
321
  return self._runtime_error_as_result(
324
322
  exc,
@@ -326,7 +324,6 @@ class ExportTools(ToolBase):
326
324
  extra={"export_handle": normalized_handle},
327
325
  )
328
326
 
329
- @tool_cn_name("记录导出结果")
330
327
  def record_export_get(
331
328
  self,
332
329
  *,
@@ -454,7 +451,7 @@ class ExportTools(ToolBase):
454
451
  }
455
452
 
456
453
  try:
457
- return self._run(profile, runner)
454
+ return self._run(profile, runner, tool_name='记录导出结果')
458
455
  except RuntimeError as exc:
459
456
  return self._runtime_error_as_result(
460
457
  exc,
@@ -462,7 +459,6 @@ class ExportTools(ToolBase):
462
459
  extra={"export_handle": normalized_handle},
463
460
  )
464
461
 
465
- @tool_cn_name("记录直接导出")
466
462
  def record_export_direct(
467
463
  self,
468
464
  *,
@@ -637,7 +633,7 @@ class ExportTools(ToolBase):
637
633
  }
638
634
 
639
635
  try:
640
- return self._run(profile, runner)
636
+ return self._run(profile, runner, tool_name='记录直接导出')
641
637
  except RuntimeError as exc:
642
638
  return self._runtime_error_as_result(
643
639
  exc,
@@ -8,7 +8,6 @@ from ..backend_client import BackendClient
8
8
  from ..config import get_feedback_app_key, get_feedback_base_url, get_feedback_qsource_token, normalize_base_url
9
9
  from ..errors import QingflowApiError, raise_tool_error
10
10
  from ..json_types import JSONObject
11
- from .base import tool_cn_name
12
11
 
13
12
 
14
13
  CATEGORY_MAP = {
@@ -68,7 +67,6 @@ class FeedbackTools:
68
67
  note=note,
69
68
  )
70
69
 
71
- @tool_cn_name("提交反馈")
72
70
  def feedback_submit(
73
71
  self,
74
72
  *,
@@ -14,7 +14,7 @@ from mcp.server.fastmcp import FastMCP
14
14
  from ..config import DEFAULT_PROFILE
15
15
  from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, raise_tool_error
16
16
  from ..json_types import JSONObject
17
- from .base import ToolBase, tool_cn_name
17
+ from .base import ToolBase
18
18
 
19
19
 
20
20
  ATTACHMENT_UPLOAD_INFO_FALLBACK_CODES = {40118}
@@ -79,7 +79,6 @@ class FileTools(ToolBase):
79
79
  file_related_url=file_related_url,
80
80
  )
81
81
 
82
- @tool_cn_name("文件上传信息")
83
82
  def file_get_upload_info(
84
83
  self,
85
84
  *,
@@ -120,9 +119,8 @@ class FileTools(ToolBase):
120
119
  "result": upload_info["result"],
121
120
  }
122
121
 
123
- return self._run(profile, runner)
122
+ return self._run(profile, runner, tool_name='文件上传信息')
124
123
 
125
- @tool_cn_name("本地文件上传")
126
124
  def file_upload_local(
127
125
  self,
128
126
  *,
@@ -204,7 +202,7 @@ class FileTools(ToolBase):
204
202
  },
205
203
  }
206
204
 
207
- return self._run(profile, runner)
205
+ return self._run(profile, runner, tool_name='本地文件上传')
208
206
 
209
207
  def _build_file_upload_bo(
210
208
  self,
@@ -21,7 +21,7 @@ from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, mes
21
21
  from ..import_store import ImportJobStore, ImportVerificationStore
22
22
  from ..json_types import JSONObject
23
23
  from .app_tools import _derive_import_capability
24
- from .base import ToolBase, tool_cn_name
24
+ from .base import ToolBase
25
25
  from .file_tools import FileTools
26
26
  from .record_tools import RecordTools, _build_field_index, _normalize_form_schema
27
27
 
@@ -174,7 +174,6 @@ class ImportTools(ToolBase):
174
174
  process_id_str=process_id_str,
175
175
  )
176
176
 
177
- @tool_cn_name("导入 Schema")
178
177
  def record_import_schema_get(
179
178
  self,
180
179
  *,
@@ -259,9 +258,8 @@ class ImportTools(ToolBase):
259
258
  response["import_capability"] = import_capability
260
259
  return response
261
260
 
262
- return self._run(profile, runner)
261
+ return self._run(profile, runner, tool_name='导入 Schema')
263
262
 
264
- @tool_cn_name("导入模板")
265
263
  def record_import_template_get(
266
264
  self,
267
265
  *,
@@ -386,11 +384,10 @@ class ImportTools(ToolBase):
386
384
  }
387
385
 
388
386
  try:
389
- return self._run(profile, runner)
387
+ return self._run(profile, runner, tool_name='导入模板')
390
388
  except RuntimeError as exc:
391
389
  return self._runtime_error_as_result(exc, error_code="IMPORT_TEMPLATE_UNAUTHORIZED")
392
390
 
393
- @tool_cn_name("导入校验")
394
391
  def record_import_verify(
395
392
  self,
396
393
  *,
@@ -612,7 +609,7 @@ class ImportTools(ToolBase):
612
609
  }
613
610
 
614
611
  try:
615
- return self._run(profile, runner)
612
+ return self._run(profile, runner, tool_name='导入校验')
616
613
  except RuntimeError as exc:
617
614
  return self._runtime_error_as_result(
618
615
  exc,
@@ -620,7 +617,6 @@ class ImportTools(ToolBase):
620
617
  extra={"can_import": _runtime_import_can_import_value(exc)},
621
618
  )
622
619
 
623
- @tool_cn_name("导入修复")
624
620
  def record_import_repair_local(
625
621
  self,
626
622
  *,
@@ -727,11 +723,10 @@ class ImportTools(ToolBase):
727
723
  }
728
724
 
729
725
  try:
730
- return self._run(profile, runner)
726
+ return self._run(profile, runner, tool_name='导入修复')
731
727
  except RuntimeError as exc:
732
728
  return self._runtime_error_as_result(exc, error_code="IMPORT_REPAIR_FORMAT_UNSUPPORTED")
733
729
 
734
- @tool_cn_name("开始导入")
735
730
  def record_import_start(
736
731
  self,
737
732
  *,
@@ -848,11 +843,10 @@ class ImportTools(ToolBase):
848
843
  }
849
844
 
850
845
  try:
851
- return self._run(profile, runner)
846
+ return self._run(profile, runner, tool_name='开始导入')
852
847
  except RuntimeError as exc:
853
848
  return self._runtime_error_as_result(exc, error_code="IMPORT_VERIFICATION_FAILED", extra={"accepted": False})
854
849
 
855
- @tool_cn_name("导入状态")
856
850
  def record_import_status_get(
857
851
  self,
858
852
  *,
@@ -1048,7 +1042,7 @@ class ImportTools(ToolBase):
1048
1042
  }
1049
1043
 
1050
1044
  try:
1051
- return self._run(profile, runner)
1045
+ return self._run(profile, runner, tool_name='导入状态')
1052
1046
  except RuntimeError as exc:
1053
1047
  return self._runtime_error_as_result(
1054
1048
  exc,
@@ -5,7 +5,7 @@ from mcp.server.fastmcp import FastMCP
5
5
  from ..config import DEFAULT_PROFILE
6
6
  from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, raise_tool_error
7
7
  from ..json_types import JSONObject
8
- from .base import ToolBase, tool_cn_name
8
+ from .base import ToolBase
9
9
 
10
10
 
11
11
  class NavigationTools(ToolBase):
@@ -69,16 +69,14 @@ class NavigationTools(ToolBase):
69
69
  def navigation_reorder(profile: str = DEFAULT_PROFILE, payload: list[JSONObject] | None = None) -> JSONObject:
70
70
  return self.navigation_reorder(profile=profile, payload=payload or [])
71
71
 
72
- @tool_cn_name("导航已发布列表")
73
72
  def navigation_list_published(self, *, profile: str, page_num: int = 1, page_size: int = 50) -> JSONObject:
74
73
  """执行工具方法逻辑。"""
75
74
  def runner(session_profile, context):
76
75
  result = self.backend.request("GET", context, "/navigation", params={"pageNum": page_num, "pageSize": page_size})
77
76
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "page": result}
78
77
 
79
- return self._run(profile, runner)
78
+ return self._run(profile, runner, tool_name='导航已发布列表')
80
79
 
81
- @tool_cn_name("导航草稿分页")
82
80
  def navigation_list_draft_page(self, *, profile: str, page_num: int = 1, page_size: int = 50, query_key: str | None = None) -> JSONObject:
83
81
  """执行工具方法逻辑。"""
84
82
  def runner(session_profile, context):
@@ -106,9 +104,8 @@ class NavigationTools(ToolBase):
106
104
  response["verification"] = {"draft_readable": False, "published_fallback_used": True}
107
105
  return response
108
106
 
109
- return self._run(profile, runner)
107
+ return self._run(profile, runner, tool_name='导航草稿分页')
110
108
 
111
- @tool_cn_name("导航草稿全量")
112
109
  def navigation_list_draft_all(self, *, profile: str, query_key: str | None = None) -> JSONObject:
113
110
  """执行工具方法逻辑。"""
114
111
  def runner(session_profile, context):
@@ -136,9 +133,8 @@ class NavigationTools(ToolBase):
136
133
  response["verification"] = {"draft_readable": False, "published_fallback_used": True}
137
134
  return response
138
135
 
139
- return self._run(profile, runner)
136
+ return self._run(profile, runner, tool_name='导航草稿全量')
140
137
 
141
- @tool_cn_name("导航详情")
142
138
  def navigation_get_detail(self, *, profile: str, navigation_item_id: int, status: str = "draft") -> JSONObject:
143
139
  """执行工具方法逻辑。"""
144
140
  self._require_navigation_item_id(navigation_item_id)
@@ -178,18 +174,16 @@ class NavigationTools(ToolBase):
178
174
  response["verification"] = {"draft_readable": False, "published_fallback_used": True}
179
175
  return response
180
176
 
181
- return self._run(profile, runner)
177
+ return self._run(profile, runner, tool_name='导航详情')
182
178
 
183
- @tool_cn_name("导航发布状态")
184
179
  def navigation_get_status(self, *, profile: str) -> JSONObject:
185
180
  """执行工具方法逻辑。"""
186
181
  def runner(session_profile, context):
187
182
  result = self.backend.request("GET", context, "/navigation/status")
188
183
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
189
184
 
190
- return self._run(profile, runner)
185
+ return self._run(profile, runner, tool_name='导航发布状态')
191
186
 
192
- @tool_cn_name("设置导航可见性")
193
187
  def navigation_set_visible(self, *, profile: str, payload: JSONObject) -> JSONObject:
194
188
  """执行工具方法逻辑。"""
195
189
  body = self._require_dict(payload)
@@ -198,9 +192,8 @@ class NavigationTools(ToolBase):
198
192
  result = self.backend.request("POST", context, "/navigation/visible", json_body=body)
199
193
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
200
194
 
201
- return self._run(profile, runner)
195
+ return self._run(profile, runner, tool_name='设置导航可见性')
202
196
 
203
- @tool_cn_name("创建导航项")
204
197
  def navigation_create(self, *, profile: str, payload: JSONObject) -> JSONObject:
205
198
  """执行工具方法逻辑。"""
206
199
  body = self._require_dict(payload)
@@ -209,9 +202,8 @@ class NavigationTools(ToolBase):
209
202
  result = self.backend.request("POST", context, "/navigation", json_body=body)
210
203
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
211
204
 
212
- return self._run(profile, runner)
205
+ return self._run(profile, runner, tool_name='创建导航项')
213
206
 
214
- @tool_cn_name("更新导航项")
215
207
  def navigation_update(self, *, profile: str, navigation_item_id: int, payload: JSONObject) -> JSONObject:
216
208
  """执行工具方法逻辑。"""
217
209
  self._require_navigation_item_id(navigation_item_id)
@@ -225,9 +217,8 @@ class NavigationTools(ToolBase):
225
217
  target="navigation item configuration",
226
218
  )
227
219
 
228
- return self._run(profile, runner)
220
+ return self._run(profile, runner, tool_name='更新导航项')
229
221
 
230
- @tool_cn_name("删除导航项")
231
222
  def navigation_delete(self, *, profile: str, navigation_item_id: int) -> JSONObject:
232
223
  """执行工具方法逻辑。"""
233
224
  self._require_navigation_item_id(navigation_item_id)
@@ -240,9 +231,8 @@ class NavigationTools(ToolBase):
240
231
  target="navigation item configuration",
241
232
  )
242
233
 
243
- return self._run(profile, runner)
234
+ return self._run(profile, runner, tool_name='删除导航项')
244
235
 
245
- @tool_cn_name("发布导航")
246
236
  def navigation_publish(self, *, profile: str, navigation_id: int) -> JSONObject:
247
237
  """执行工具方法逻辑。"""
248
238
  if navigation_id <= 0:
@@ -252,9 +242,8 @@ class NavigationTools(ToolBase):
252
242
  result = self.backend.request("POST", context, f"/navigation/publish/{navigation_id}")
253
243
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "navigation_id": navigation_id, "result": result}
254
244
 
255
- return self._run(profile, runner)
245
+ return self._run(profile, runner, tool_name='发布导航')
256
246
 
257
- @tool_cn_name("导航排序")
258
247
  def navigation_reorder(self, *, profile: str, payload: list[JSONObject]) -> JSONObject:
259
248
  """执行工具方法逻辑。"""
260
249
  if not isinstance(payload, list) or not payload:
@@ -264,7 +253,7 @@ class NavigationTools(ToolBase):
264
253
  result = self.backend.request("POST", context, "/navigation/ordinal", json_body=payload)
265
254
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
266
255
 
267
- return self._run(profile, runner)
256
+ return self._run(profile, runner, tool_name='导航排序')
268
257
 
269
258
  def _require_navigation_item_id(self, navigation_item_id: int) -> None:
270
259
  """执行内部辅助逻辑。"""
@@ -8,7 +8,7 @@ from ..config import DEFAULT_PROFILE
8
8
  from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, raise_tool_error
9
9
  from ..json_types import JSONObject
10
10
  from ..solution.compiler.icon_utils import workspace_icon_config
11
- from .base import ToolBase, tool_cn_name
11
+ from .base import ToolBase
12
12
 
13
13
 
14
14
  class PackageTools(ToolBase):
@@ -47,7 +47,6 @@ class PackageTools(ToolBase):
47
47
  def package_delete(profile: str = DEFAULT_PROFILE, tag_id: int = 0, deleted_all_data: bool = False) -> JSONObject:
48
48
  return self.package_delete(profile=profile, tag_id=tag_id, deleted_all_data=deleted_all_data)
49
49
 
50
- @tool_cn_name("分组列表")
51
50
  def package_list(self, *, profile: str, trial_status: str = "all", include_raw: bool = False) -> JSONObject:
52
51
  """执行分组与包相关逻辑。"""
53
52
  def runner(session_profile, context):
@@ -68,9 +67,8 @@ class PackageTools(ToolBase):
68
67
  response["summary"] = compact_items
69
68
  return response
70
69
 
71
- return self._run(profile, runner)
70
+ return self._run(profile, runner, tool_name='分组列表')
72
71
 
73
- @tool_cn_name("分组详情")
74
72
  def package_get(self, *, profile: str, tag_id: int, include_raw: bool = False) -> JSONObject:
75
73
  """执行分组与包相关逻辑。"""
76
74
  self._require_tag_id(tag_id)
@@ -133,9 +131,8 @@ class PackageTools(ToolBase):
133
131
  response["summary"] = compact
134
132
  return response
135
133
 
136
- return self._run(profile, runner)
134
+ return self._run(profile, runner, tool_name='分组详情')
137
135
 
138
- @tool_cn_name("分组基础信息")
139
136
  def package_get_base(self, *, profile: str, tag_id: int, include_raw: bool = False) -> JSONObject:
140
137
  """执行分组与包相关逻辑。"""
141
138
  self._require_readable_tag_id(tag_id)
@@ -177,9 +174,8 @@ class PackageTools(ToolBase):
177
174
  response["summary"] = compact
178
175
  return response
179
176
 
180
- return self._run(profile, runner)
177
+ return self._run(profile, runner, tool_name='分组基础信息')
181
178
 
182
- @tool_cn_name("创建分组")
183
179
  def package_create(self, *, profile: str, payload: JSONObject) -> JSONObject:
184
180
  """执行分组与包相关逻辑。"""
185
181
  body = self._require_dict(payload)
@@ -188,9 +184,8 @@ class PackageTools(ToolBase):
188
184
  result = self.backend.request("POST", context, "/tag", json_body=self._normalize_package_payload(body))
189
185
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
190
186
 
191
- return self._run(profile, runner)
187
+ return self._run(profile, runner, tool_name='创建分组')
192
188
 
193
- @tool_cn_name("更新分组")
194
189
  def package_update(self, *, profile: str, tag_id: int, payload: JSONObject) -> JSONObject:
195
190
  """执行分组与包相关逻辑。"""
196
191
  self._require_tag_id(tag_id)
@@ -239,9 +234,8 @@ class PackageTools(ToolBase):
239
234
  target="app package settings",
240
235
  )
241
236
 
242
- return self._run(profile, runner)
237
+ return self._run(profile, runner, tool_name='更新分组')
243
238
 
244
- @tool_cn_name("分组排序")
245
239
  def package_sort_items(self, *, profile: str, tag_id: int, tag_items: list[JSONObject]) -> JSONObject:
246
240
  """执行分组与包相关逻辑。"""
247
241
  self._require_tag_id(tag_id)
@@ -255,9 +249,8 @@ class PackageTools(ToolBase):
255
249
  )
256
250
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "tag_id": tag_id, "result": result}
257
251
 
258
- return self._run(profile, runner)
252
+ return self._run(profile, runner, tool_name='分组排序')
259
253
 
260
- @tool_cn_name("创建分组分栏")
261
254
  def package_group_create(self, *, profile: str, tag_id: int, group_name: str) -> JSONObject:
262
255
  """执行分组与包相关逻辑。"""
263
256
  self._require_tag_id(tag_id)
@@ -274,9 +267,8 @@ class PackageTools(ToolBase):
274
267
  )
275
268
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "tag_id": tag_id, "result": result}
276
269
 
277
- return self._run(profile, runner)
270
+ return self._run(profile, runner, tool_name='创建分组分栏')
278
271
 
279
- @tool_cn_name("更新分组分栏")
280
272
  def package_group_update(self, *, profile: str, tag_id: int, group_id: int, group_name: str) -> JSONObject:
281
273
  """执行分组与包相关逻辑。"""
282
274
  self._require_tag_id(tag_id)
@@ -294,9 +286,8 @@ class PackageTools(ToolBase):
294
286
  )
295
287
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "tag_id": tag_id, "group_id": group_id, "result": result}
296
288
 
297
- return self._run(profile, runner)
289
+ return self._run(profile, runner, tool_name='更新分组分栏')
298
290
 
299
- @tool_cn_name("删除分组分栏")
300
291
  def package_group_delete(self, *, profile: str, tag_id: int, group_id: int) -> JSONObject:
301
292
  """执行分组与包相关逻辑。"""
302
293
  self._require_tag_id(tag_id)
@@ -306,9 +297,8 @@ class PackageTools(ToolBase):
306
297
  result = self.backend.request("DELETE", context, f"/tag/{tag_id}/group/{group_id}")
307
298
  return {"profile": profile, "ws_id": session_profile.selected_ws_id, "tag_id": tag_id, "group_id": group_id, "result": result}
308
299
 
309
- return self._run(profile, runner)
300
+ return self._run(profile, runner, tool_name='删除分组分栏')
310
301
 
311
- @tool_cn_name("删除分组")
312
302
  def package_delete(self, *, profile: str, tag_id: int, deleted_all_data: bool = False) -> JSONObject:
313
303
  """执行分组与包相关逻辑。"""
314
304
  self._require_tag_id(tag_id)
@@ -326,7 +316,7 @@ class PackageTools(ToolBase):
326
316
  target="app package and linked data",
327
317
  )
328
318
 
329
- return self._run(profile, runner)
319
+ return self._run(profile, runner, tool_name='删除分组')
330
320
 
331
321
  def _require_tag_id(self, tag_id: int) -> None:
332
322
  """执行内部辅助逻辑。"""