@qingflow-tech/qingflow-cli 1.1.39 → 1.1.40
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 +3 -3
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/qingflow_mcp/builder_facade/service.py +8 -8
- package/src/qingflow_mcp/server_cloud.py +89 -3
- package/src/qingflow_mcp/tools/ai_builder_tools.py +1 -59
- package/src/qingflow_mcp/tools/app_tools.py +15 -29
- package/src/qingflow_mcp/tools/approval_tools.py +16 -40
- package/src/qingflow_mcp/tools/auth_tools.py +1 -4
- package/src/qingflow_mcp/tools/base.py +16 -34
- package/src/qingflow_mcp/tools/code_block_tools.py +2 -5
- package/src/qingflow_mcp/tools/custom_button_tools.py +6 -11
- package/src/qingflow_mcp/tools/directory_tools.py +9 -16
- package/src/qingflow_mcp/tools/export_tools.py +5 -9
- package/src/qingflow_mcp/tools/feedback_tools.py +0 -2
- package/src/qingflow_mcp/tools/file_tools.py +3 -5
- package/src/qingflow_mcp/tools/import_tools.py +7 -13
- package/src/qingflow_mcp/tools/navigation_tools.py +12 -23
- package/src/qingflow_mcp/tools/package_tools.py +11 -21
- package/src/qingflow_mcp/tools/portal_tools.py +9 -17
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +18 -23
- package/src/qingflow_mcp/tools/record_tools.py +97 -53
- package/src/qingflow_mcp/tools/repository_dev_tools.py +4 -7
- package/src/qingflow_mcp/tools/resource_read_tools.py +6 -9
- package/src/qingflow_mcp/tools/role_tools.py +5 -9
- package/src/qingflow_mcp/tools/solution_tools.py +4 -16
- package/src/qingflow_mcp/tools/task_context_tools.py +6 -12
- package/src/qingflow_mcp/tools/task_tools.py +12 -29
- package/src/qingflow_mcp/tools/view_tools.py +23 -32
- package/src/qingflow_mcp/tools/workflow_tools.py +30 -47
- package/src/qingflow_mcp/tools/workspace_tools.py +5 -9
|
@@ -9,7 +9,7 @@ from ..config import DEFAULT_PROFILE
|
|
|
9
9
|
from ..errors import QingflowApiError, backend_code_int, backend_code_value_int, is_auth_like_error, message_looks_like_invalid_token, raise_tool_error
|
|
10
10
|
from ..json_types import JSONObject
|
|
11
11
|
from ..list_type_labels import get_record_list_type_label
|
|
12
|
-
from .base import ToolBase
|
|
12
|
+
from .base import ToolBase
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class ApprovalTools(ToolBase):
|
|
@@ -149,7 +149,6 @@ class ApprovalTools(ToolBase):
|
|
|
149
149
|
keyword=keyword,
|
|
150
150
|
)
|
|
151
151
|
|
|
152
|
-
@tool_cn_name("写评论")
|
|
153
152
|
def record_comment_write(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
154
153
|
"""执行记录相关逻辑。"""
|
|
155
154
|
raw = self.record_comment_add(profile=profile, app_key=app_key, apply_id=record_id, payload=payload)
|
|
@@ -160,7 +159,6 @@ class ApprovalTools(ToolBase):
|
|
|
160
159
|
selection={},
|
|
161
160
|
)
|
|
162
161
|
|
|
163
|
-
@tool_cn_name("评论提及")
|
|
164
162
|
def record_comment_mentions(
|
|
165
163
|
self,
|
|
166
164
|
*,
|
|
@@ -207,7 +205,6 @@ class ApprovalTools(ToolBase):
|
|
|
207
205
|
selection=selection,
|
|
208
206
|
)
|
|
209
207
|
|
|
210
|
-
@tool_cn_name("任务通过")
|
|
211
208
|
def task_approve(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any], fields: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
212
209
|
"""执行任务相关逻辑。"""
|
|
213
210
|
if fields:
|
|
@@ -229,7 +226,6 @@ class ApprovalTools(ToolBase):
|
|
|
229
226
|
human_review=True,
|
|
230
227
|
)
|
|
231
228
|
|
|
232
|
-
@tool_cn_name("任务拒绝")
|
|
233
229
|
def task_reject(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any], fields: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
234
230
|
"""执行任务相关逻辑。"""
|
|
235
231
|
if fields:
|
|
@@ -251,7 +247,6 @@ class ApprovalTools(ToolBase):
|
|
|
251
247
|
human_review=True,
|
|
252
248
|
)
|
|
253
249
|
|
|
254
|
-
@tool_cn_name("任务退回候选")
|
|
255
250
|
def task_rollback_candidates(self, *, profile: str, app_key: str, record_id: int, workflow_node_id: int) -> dict[str, Any]:
|
|
256
251
|
"""执行任务相关逻辑。"""
|
|
257
252
|
selection = {"app_key": app_key, "record_id": record_id, "workflow_node_id": workflow_node_id}
|
|
@@ -274,7 +269,6 @@ class ApprovalTools(ToolBase):
|
|
|
274
269
|
selection=selection,
|
|
275
270
|
)
|
|
276
271
|
|
|
277
|
-
@tool_cn_name("任务退回")
|
|
278
272
|
def task_rollback(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any], fields: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
279
273
|
"""执行任务相关逻辑。"""
|
|
280
274
|
if fields:
|
|
@@ -296,7 +290,6 @@ class ApprovalTools(ToolBase):
|
|
|
296
290
|
human_review=True,
|
|
297
291
|
)
|
|
298
292
|
|
|
299
|
-
@tool_cn_name("任务转交")
|
|
300
293
|
def task_transfer(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any], fields: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
301
294
|
"""执行任务相关逻辑。"""
|
|
302
295
|
if fields:
|
|
@@ -319,7 +312,6 @@ class ApprovalTools(ToolBase):
|
|
|
319
312
|
human_review=True,
|
|
320
313
|
)
|
|
321
314
|
|
|
322
|
-
@tool_cn_name("任务仅保存")
|
|
323
315
|
def task_save_only(
|
|
324
316
|
self,
|
|
325
317
|
*,
|
|
@@ -341,7 +333,6 @@ class ApprovalTools(ToolBase):
|
|
|
341
333
|
workflow_node_id=workflow_node_id,
|
|
342
334
|
)
|
|
343
335
|
|
|
344
|
-
@tool_cn_name("任务转交候选")
|
|
345
336
|
def task_transfer_candidates(
|
|
346
337
|
self,
|
|
347
338
|
*,
|
|
@@ -390,7 +381,6 @@ class ApprovalTools(ToolBase):
|
|
|
390
381
|
selection=selection,
|
|
391
382
|
)
|
|
392
383
|
|
|
393
|
-
@tool_cn_name("新增评论")
|
|
394
384
|
def record_comment_add(self, *, profile: str, app_key: str, apply_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
395
385
|
"""执行记录相关逻辑。"""
|
|
396
386
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -407,9 +397,8 @@ class ApprovalTools(ToolBase):
|
|
|
407
397
|
"request_route": self._request_route_payload(context),
|
|
408
398
|
}
|
|
409
399
|
|
|
410
|
-
return self._run(profile, runner)
|
|
400
|
+
return self._run(profile, runner, tool_name='新增评论')
|
|
411
401
|
|
|
412
|
-
@tool_cn_name("评论列表")
|
|
413
402
|
def record_comment_list(self, *, profile: str, app_key: str, apply_id: int, page_size: int = 20, list_type: int | None = None, page_num: int | None = 1) -> dict[str, Any]:
|
|
414
403
|
"""执行记录相关逻辑。"""
|
|
415
404
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -432,7 +421,7 @@ class ApprovalTools(ToolBase):
|
|
|
432
421
|
"request_route": self._request_route_payload(context),
|
|
433
422
|
}
|
|
434
423
|
|
|
435
|
-
raw = self._run(profile, runner)
|
|
424
|
+
raw = self._run(profile, runner, tool_name='评论列表')
|
|
436
425
|
items = _approval_page_items(raw.get("page"))
|
|
437
426
|
return self._public_page_response(
|
|
438
427
|
raw,
|
|
@@ -447,7 +436,6 @@ class ApprovalTools(ToolBase):
|
|
|
447
436
|
selection={"app_key": app_key, "record_id": apply_id, "list_type": list_type},
|
|
448
437
|
)
|
|
449
438
|
|
|
450
|
-
@tool_cn_name("评论提及候选")
|
|
451
439
|
def record_comment_mention_candidates(
|
|
452
440
|
self,
|
|
453
441
|
*,
|
|
@@ -480,9 +468,8 @@ class ApprovalTools(ToolBase):
|
|
|
480
468
|
"request_route": self._request_route_payload(context),
|
|
481
469
|
}
|
|
482
470
|
|
|
483
|
-
return self._run(profile, runner)
|
|
471
|
+
return self._run(profile, runner, tool_name='评论提及候选')
|
|
484
472
|
|
|
485
|
-
@tool_cn_name("评论标记已读")
|
|
486
473
|
def record_comment_mark_read(self, *, profile: str, app_key: str, apply_id: int) -> dict[str, Any]:
|
|
487
474
|
"""执行记录相关逻辑。"""
|
|
488
475
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -498,7 +485,7 @@ class ApprovalTools(ToolBase):
|
|
|
498
485
|
"request_route": self._request_route_payload(context),
|
|
499
486
|
}
|
|
500
487
|
|
|
501
|
-
raw = self._run(profile, runner)
|
|
488
|
+
raw = self._run(profile, runner, tool_name='评论标记已读')
|
|
502
489
|
return self._public_action_response(
|
|
503
490
|
raw,
|
|
504
491
|
action="record_comment_mark_read",
|
|
@@ -506,7 +493,6 @@ class ApprovalTools(ToolBase):
|
|
|
506
493
|
selection={},
|
|
507
494
|
)
|
|
508
495
|
|
|
509
|
-
@tool_cn_name("评论统计")
|
|
510
496
|
def record_comment_stats(self, *, profile: str, app_key: str, apply_id: int) -> dict[str, Any]:
|
|
511
497
|
"""执行记录相关逻辑。"""
|
|
512
498
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -522,9 +508,8 @@ class ApprovalTools(ToolBase):
|
|
|
522
508
|
"request_route": self._request_route_payload(context),
|
|
523
509
|
}
|
|
524
510
|
|
|
525
|
-
return self._run(profile, runner)
|
|
511
|
+
return self._run(profile, runner, tool_name='评论统计')
|
|
526
512
|
|
|
527
|
-
@tool_cn_name("记录通过")
|
|
528
513
|
def record_approve(self, *, profile: str, app_key: str, apply_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
529
514
|
"""执行记录相关逻辑。"""
|
|
530
515
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -544,9 +529,8 @@ class ApprovalTools(ToolBase):
|
|
|
544
529
|
"request_route": self._request_route_payload(context),
|
|
545
530
|
}
|
|
546
531
|
|
|
547
|
-
return self._run(profile, runner)
|
|
532
|
+
return self._run(profile, runner, tool_name='记录通过')
|
|
548
533
|
|
|
549
|
-
@tool_cn_name("记录拒绝")
|
|
550
534
|
def record_reject(self, *, profile: str, app_key: str, apply_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
551
535
|
"""执行记录相关逻辑。"""
|
|
552
536
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -566,9 +550,8 @@ class ApprovalTools(ToolBase):
|
|
|
566
550
|
"request_route": self._request_route_payload(context),
|
|
567
551
|
}
|
|
568
552
|
|
|
569
|
-
return self._run(profile, runner)
|
|
553
|
+
return self._run(profile, runner, tool_name='记录拒绝')
|
|
570
554
|
|
|
571
|
-
@tool_cn_name("记录退回候选")
|
|
572
555
|
def record_rollback_candidates(self, *, profile: str, app_key: str, apply_id: int, audit_node_id: int) -> dict[str, Any]:
|
|
573
556
|
"""执行记录相关逻辑。"""
|
|
574
557
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -591,9 +574,8 @@ class ApprovalTools(ToolBase):
|
|
|
591
574
|
"request_route": self._request_route_payload(context),
|
|
592
575
|
}
|
|
593
576
|
|
|
594
|
-
return self._run(profile, runner)
|
|
577
|
+
return self._run(profile, runner, tool_name='记录退回候选')
|
|
595
578
|
|
|
596
|
-
@tool_cn_name("记录退回")
|
|
597
579
|
def record_rollback(self, *, profile: str, app_key: str, apply_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
598
580
|
"""执行记录相关逻辑。"""
|
|
599
581
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -611,9 +593,8 @@ class ApprovalTools(ToolBase):
|
|
|
611
593
|
"request_route": self._request_route_payload(context),
|
|
612
594
|
}
|
|
613
595
|
|
|
614
|
-
return self._run(profile, runner)
|
|
596
|
+
return self._run(profile, runner, tool_name='记录退回')
|
|
615
597
|
|
|
616
|
-
@tool_cn_name("记录转交")
|
|
617
598
|
def record_transfer(self, *, profile: str, app_key: str, apply_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
618
599
|
"""执行记录相关逻辑。"""
|
|
619
600
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -631,9 +612,8 @@ class ApprovalTools(ToolBase):
|
|
|
631
612
|
"request_route": self._request_route_payload(context),
|
|
632
613
|
}
|
|
633
614
|
|
|
634
|
-
return self._run(profile, runner)
|
|
615
|
+
return self._run(profile, runner, tool_name='记录转交')
|
|
635
616
|
|
|
636
|
-
@tool_cn_name("记录转交候选")
|
|
637
617
|
def record_transfer_candidates(
|
|
638
618
|
self,
|
|
639
619
|
*,
|
|
@@ -664,9 +644,8 @@ class ApprovalTools(ToolBase):
|
|
|
664
644
|
"request_route": self._request_route_payload(context),
|
|
665
645
|
}
|
|
666
646
|
|
|
667
|
-
return self._run(profile, runner)
|
|
647
|
+
return self._run(profile, runner, tool_name='记录转交候选')
|
|
668
648
|
|
|
669
|
-
@tool_cn_name("记录改派信息")
|
|
670
649
|
def record_reassign_get(self, *, profile: str, app_key: str, apply_id: int) -> dict[str, Any]:
|
|
671
650
|
"""执行记录相关逻辑。"""
|
|
672
651
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -682,9 +661,8 @@ class ApprovalTools(ToolBase):
|
|
|
682
661
|
"request_route": self._request_route_payload(context),
|
|
683
662
|
}
|
|
684
663
|
|
|
685
|
-
return self._run(profile, runner)
|
|
664
|
+
return self._run(profile, runner, tool_name='记录改派信息')
|
|
686
665
|
|
|
687
|
-
@tool_cn_name("记录改派")
|
|
688
666
|
def record_reassign(self, *, profile: str, app_key: str, apply_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
689
667
|
"""执行记录相关逻辑。"""
|
|
690
668
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -701,9 +679,8 @@ class ApprovalTools(ToolBase):
|
|
|
701
679
|
"request_route": self._request_route_payload(context),
|
|
702
680
|
}
|
|
703
681
|
|
|
704
|
-
return self._run(profile, runner)
|
|
682
|
+
return self._run(profile, runner, tool_name='记录改派')
|
|
705
683
|
|
|
706
|
-
@tool_cn_name("会签候选")
|
|
707
684
|
def record_countersign_candidates(
|
|
708
685
|
self,
|
|
709
686
|
*,
|
|
@@ -734,9 +711,8 @@ class ApprovalTools(ToolBase):
|
|
|
734
711
|
"request_route": self._request_route_payload(context),
|
|
735
712
|
}
|
|
736
713
|
|
|
737
|
-
return self._run(profile, runner)
|
|
714
|
+
return self._run(profile, runner, tool_name='会签候选')
|
|
738
715
|
|
|
739
|
-
@tool_cn_name("会签")
|
|
740
716
|
def record_countersign(self, *, profile: str, app_key: str, apply_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
741
717
|
"""执行记录相关逻辑。"""
|
|
742
718
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -754,7 +730,7 @@ class ApprovalTools(ToolBase):
|
|
|
754
730
|
"request_route": self._request_route_payload(context),
|
|
755
731
|
}
|
|
756
732
|
|
|
757
|
-
return self._run(profile, runner)
|
|
733
|
+
return self._run(profile, runner, tool_name='会签')
|
|
758
734
|
|
|
759
735
|
def _request_route_payload(self, context) -> JSONObject: # type: ignore[no-untyped-def]
|
|
760
736
|
"""执行内部辅助逻辑。"""
|
|
@@ -17,7 +17,7 @@ from ..config import (
|
|
|
17
17
|
)
|
|
18
18
|
from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, raise_tool_error
|
|
19
19
|
from ..session_store import SessionStore
|
|
20
|
-
from .base import ToolBase
|
|
20
|
+
from .base import ToolBase
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class AuthTools(ToolBase):
|
|
@@ -75,7 +75,6 @@ class AuthTools(ToolBase):
|
|
|
75
75
|
def auth_logout(profile: str = DEFAULT_PROFILE, forget_persisted: bool = False) -> dict[str, Any]:
|
|
76
76
|
return self.auth_logout(profile=profile, forget_persisted=forget_persisted)
|
|
77
77
|
|
|
78
|
-
@tool_cn_name("凭证登录")
|
|
79
78
|
def auth_use_credential(
|
|
80
79
|
self,
|
|
81
80
|
*,
|
|
@@ -371,7 +370,6 @@ class AuthTools(ToolBase):
|
|
|
371
370
|
return False
|
|
372
371
|
return True
|
|
373
372
|
|
|
374
|
-
@tool_cn_name("我的身份")
|
|
375
373
|
def auth_whoami(self, *, profile: str = DEFAULT_PROFILE) -> dict[str, Any]:
|
|
376
374
|
"""执行认证与会话相关逻辑。"""
|
|
377
375
|
def build_response(
|
|
@@ -503,7 +501,6 @@ class AuthTools(ToolBase):
|
|
|
503
501
|
if error.looks_like_invalid_token():
|
|
504
502
|
raise
|
|
505
503
|
|
|
506
|
-
@tool_cn_name("退出登录")
|
|
507
504
|
def auth_logout(self, *, profile: str = DEFAULT_PROFILE, forget_persisted: bool = False) -> dict[str, Any]:
|
|
508
505
|
"""执行认证与会话相关逻辑。"""
|
|
509
506
|
if not self.sessions.has_profile(profile):
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import inspect
|
|
4
3
|
from contextvars import ContextVar
|
|
5
4
|
from typing import Any, Callable, TypeVar
|
|
6
5
|
|
|
@@ -20,17 +19,6 @@ T = TypeVar("T")
|
|
|
20
19
|
_RUN_DEPTH: ContextVar[int] = ContextVar("qingflow_mcp_tool_run_depth", default=0)
|
|
21
20
|
|
|
22
21
|
|
|
23
|
-
def tool_cn_name(name: str) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
|
|
24
|
-
"""为 tools 方法声明中文展示名(用于计费 extraInfo 记录)。"""
|
|
25
|
-
normalized = str(name).strip()
|
|
26
|
-
|
|
27
|
-
def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
28
|
-
setattr(func, "__tool_cn_name__", normalized)
|
|
29
|
-
return func
|
|
30
|
-
|
|
31
|
-
return decorator
|
|
32
|
-
|
|
33
|
-
|
|
34
22
|
class ToolBase:
|
|
35
23
|
def __init__(self, sessions: SessionStore, backend: BackendClient) -> None:
|
|
36
24
|
self.sessions = sessions
|
|
@@ -62,19 +50,26 @@ class ToolBase:
|
|
|
62
50
|
)
|
|
63
51
|
return session_profile, backend_session, context
|
|
64
52
|
|
|
65
|
-
def _run(
|
|
53
|
+
def _run(
|
|
54
|
+
self,
|
|
55
|
+
profile: str,
|
|
56
|
+
func: Callable[[SessionProfile, BackendRequestContext], T],
|
|
57
|
+
*,
|
|
58
|
+
require_workspace: bool = True,
|
|
59
|
+
tool_name: str,
|
|
60
|
+
) -> T:
|
|
66
61
|
depth = _RUN_DEPTH.get()
|
|
67
62
|
depth_token = _RUN_DEPTH.set(depth + 1)
|
|
68
63
|
is_top_level_call = depth == 0
|
|
69
64
|
session_profile: SessionProfile | None = None
|
|
70
65
|
backend_session: BackendSession | None = None
|
|
71
|
-
|
|
66
|
+
resolved_tool_name = self._normalize_tool_name(tool_name)
|
|
72
67
|
try:
|
|
73
68
|
session_profile, backend_session, context = self._require_context(profile, require_workspace=require_workspace)
|
|
74
69
|
if is_top_level_call:
|
|
75
70
|
self._charge_tool_call(
|
|
76
71
|
profile=profile,
|
|
77
|
-
tool_name=
|
|
72
|
+
tool_name=resolved_tool_name,
|
|
78
73
|
session_profile=session_profile,
|
|
79
74
|
context=context,
|
|
80
75
|
)
|
|
@@ -106,6 +101,12 @@ class ToolBase:
|
|
|
106
101
|
_RUN_DEPTH.reset(depth_token)
|
|
107
102
|
raise AssertionError("unreachable")
|
|
108
103
|
|
|
104
|
+
def _normalize_tool_name(self, tool_name: str) -> str:
|
|
105
|
+
normalized = str(tool_name or "").strip()
|
|
106
|
+
if not normalized:
|
|
107
|
+
raise_tool_error(QingflowApiError.config_error("tool_name is required for credit usage tracking"))
|
|
108
|
+
return normalized
|
|
109
|
+
|
|
109
110
|
def _handle_error(self, profile: str, error: QingflowApiError) -> None:
|
|
110
111
|
if error.looks_like_invalid_token():
|
|
111
112
|
cloud_context = current_cloud_context.get()
|
|
@@ -221,25 +222,6 @@ class ToolBase:
|
|
|
221
222
|
return None
|
|
222
223
|
return parsed if parsed > 0 else None
|
|
223
224
|
|
|
224
|
-
def _resolve_calling_tool_name(self) -> str:
|
|
225
|
-
frame = inspect.currentframe()
|
|
226
|
-
if frame is None:
|
|
227
|
-
return "unknown_tool"
|
|
228
|
-
caller = frame.f_back.f_back if frame.f_back is not None else None
|
|
229
|
-
try:
|
|
230
|
-
if caller is None:
|
|
231
|
-
return "unknown_tool"
|
|
232
|
-
name = caller.f_code.co_name
|
|
233
|
-
if not name:
|
|
234
|
-
return "unknown_tool"
|
|
235
|
-
method = getattr(self, name, None)
|
|
236
|
-
cn_name = getattr(method, "__tool_cn_name__", None)
|
|
237
|
-
if isinstance(cn_name, str) and cn_name.strip():
|
|
238
|
-
return cn_name.strip()
|
|
239
|
-
return name
|
|
240
|
-
finally:
|
|
241
|
-
del frame
|
|
242
|
-
|
|
243
225
|
def _charge_tool_call(
|
|
244
226
|
self,
|
|
245
227
|
*,
|
|
@@ -7,7 +7,6 @@ from mcp.server.fastmcp import FastMCP
|
|
|
7
7
|
from ..config import DEFAULT_PROFILE, DEFAULT_RECORD_LIST_TYPE
|
|
8
8
|
from ..errors import QingflowApiError, backend_code_int, backend_code_value_int, is_auth_like_error, message_looks_like_invalid_token, raise_tool_error
|
|
9
9
|
from ..json_types import JSONObject, JSONValue
|
|
10
|
-
from .base import tool_cn_name
|
|
11
10
|
from .record_tools import (
|
|
12
11
|
ATTACHMENT_QUE_TYPES,
|
|
13
12
|
DEPARTMENT_QUE_TYPES,
|
|
@@ -156,7 +155,6 @@ class CodeBlockTools(RecordTools):
|
|
|
156
155
|
output_profile=output_profile,
|
|
157
156
|
)
|
|
158
157
|
|
|
159
|
-
@tool_cn_name("代码块 Schema")
|
|
160
158
|
def record_code_block_schema_get_public(
|
|
161
159
|
self,
|
|
162
160
|
*,
|
|
@@ -263,9 +261,8 @@ class CodeBlockTools(RecordTools):
|
|
|
263
261
|
)
|
|
264
262
|
return response
|
|
265
263
|
|
|
266
|
-
return self._run_record_tool(profile, runner)
|
|
264
|
+
return self._run_record_tool(profile, runner, tool_name="代码块 Schema")
|
|
267
265
|
|
|
268
|
-
@tool_cn_name("运行代码块")
|
|
269
266
|
def record_code_block_run(
|
|
270
267
|
self,
|
|
271
268
|
*,
|
|
@@ -549,7 +546,7 @@ class CodeBlockTools(RecordTools):
|
|
|
549
546
|
}
|
|
550
547
|
return response
|
|
551
548
|
|
|
552
|
-
return self._run_record_tool(profile, runner)
|
|
549
|
+
return self._run_record_tool(profile, runner, tool_name="运行代码块")
|
|
553
550
|
|
|
554
551
|
def _resolve_code_block_field_for_run(self, selector: str | int, index: FieldIndex) -> FormField:
|
|
555
552
|
field_id = _coerce_count(selector)
|
|
@@ -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
|
|
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
|
|
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,
|