Undefined-bot 2.1.0__py3-none-any.whl

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 (211) hide show
  1. Undefined/__init__.py +3 -0
  2. Undefined/__main__.py +6 -0
  3. Undefined/ai.py +1215 -0
  4. Undefined/config.py +371 -0
  5. Undefined/end_summary_storage.py +48 -0
  6. Undefined/faq.py +244 -0
  7. Undefined/handlers.py +1247 -0
  8. Undefined/injection_response_agent.py +131 -0
  9. Undefined/main.py +126 -0
  10. Undefined/memory.py +120 -0
  11. Undefined/onebot.py +512 -0
  12. Undefined/rate_limit.py +130 -0
  13. Undefined/render.py +123 -0
  14. Undefined/scheduled_task_storage.py +88 -0
  15. Undefined/services/__init__.py +1 -0
  16. Undefined/services/queue_manager.py +206 -0
  17. Undefined/skills/README.md +53 -0
  18. Undefined/skills/__init__.py +10 -0
  19. Undefined/skills/agents/README.md +144 -0
  20. Undefined/skills/agents/__init__.py +116 -0
  21. Undefined/skills/agents/entertainment_agent/config.json +17 -0
  22. Undefined/skills/agents/entertainment_agent/handler.py +220 -0
  23. Undefined/skills/agents/entertainment_agent/intro.md +25 -0
  24. Undefined/skills/agents/entertainment_agent/prompt.md +20 -0
  25. Undefined/skills/agents/entertainment_agent/tools/__init__.py +1 -0
  26. Undefined/skills/agents/entertainment_agent/tools/ai_draw_one/config.json +34 -0
  27. Undefined/skills/agents/entertainment_agent/tools/ai_draw_one/handler.py +62 -0
  28. Undefined/skills/agents/entertainment_agent/tools/ai_study_helper/config.json +22 -0
  29. Undefined/skills/agents/entertainment_agent/tools/ai_study_helper/handler.py +35 -0
  30. Undefined/skills/agents/entertainment_agent/tools/get_current_time/config.json +12 -0
  31. Undefined/skills/agents/entertainment_agent/tools/get_current_time/handler.py +5 -0
  32. Undefined/skills/agents/entertainment_agent/tools/horoscope/config.json +24 -0
  33. Undefined/skills/agents/entertainment_agent/tools/horoscope/handler.py +141 -0
  34. Undefined/skills/agents/entertainment_agent/tools/minecraft_skin/config.json +43 -0
  35. Undefined/skills/agents/entertainment_agent/tools/minecraft_skin/handler.py +55 -0
  36. Undefined/skills/agents/entertainment_agent/tools/novel_search/config.json +25 -0
  37. Undefined/skills/agents/entertainment_agent/tools/novel_search/handler.py +31 -0
  38. Undefined/skills/agents/entertainment_agent/tools/renjian/config.json +12 -0
  39. Undefined/skills/agents/entertainment_agent/tools/renjian/handler.py +30 -0
  40. Undefined/skills/agents/entertainment_agent/tools/wenchang_dijun/config.json +12 -0
  41. Undefined/skills/agents/entertainment_agent/tools/wenchang_dijun/handler.py +44 -0
  42. Undefined/skills/agents/file_analysis_agent/__init__.py +1 -0
  43. Undefined/skills/agents/file_analysis_agent/config.json +21 -0
  44. Undefined/skills/agents/file_analysis_agent/handler.py +248 -0
  45. Undefined/skills/agents/file_analysis_agent/intro.md +22 -0
  46. Undefined/skills/agents/file_analysis_agent/prompt.md +36 -0
  47. Undefined/skills/agents/file_analysis_agent/tools/__init__.py +1 -0
  48. Undefined/skills/agents/file_analysis_agent/tools/analyze_code/config.json +17 -0
  49. Undefined/skills/agents/file_analysis_agent/tools/analyze_code/handler.py +427 -0
  50. Undefined/skills/agents/file_analysis_agent/tools/analyze_multimodal/config.json +25 -0
  51. Undefined/skills/agents/file_analysis_agent/tools/analyze_multimodal/handler.py +178 -0
  52. Undefined/skills/agents/file_analysis_agent/tools/cleanup_temp/config.json +16 -0
  53. Undefined/skills/agents/file_analysis_agent/tools/cleanup_temp/handler.py +35 -0
  54. Undefined/skills/agents/file_analysis_agent/tools/detect_file_type/config.json +17 -0
  55. Undefined/skills/agents/file_analysis_agent/tools/detect_file_type/handler.py +221 -0
  56. Undefined/skills/agents/file_analysis_agent/tools/download_file/config.json +21 -0
  57. Undefined/skills/agents/file_analysis_agent/tools/download_file/handler.py +124 -0
  58. Undefined/skills/agents/file_analysis_agent/tools/extract_archive/config.json +25 -0
  59. Undefined/skills/agents/file_analysis_agent/tools/extract_archive/handler.py +190 -0
  60. Undefined/skills/agents/file_analysis_agent/tools/extract_docx/config.json +17 -0
  61. Undefined/skills/agents/file_analysis_agent/tools/extract_docx/handler.py +78 -0
  62. Undefined/skills/agents/file_analysis_agent/tools/extract_pdf/config.json +21 -0
  63. Undefined/skills/agents/file_analysis_agent/tools/extract_pdf/handler.py +67 -0
  64. Undefined/skills/agents/file_analysis_agent/tools/extract_pptx/config.json +17 -0
  65. Undefined/skills/agents/file_analysis_agent/tools/extract_pptx/handler.py +73 -0
  66. Undefined/skills/agents/file_analysis_agent/tools/extract_xlsx/config.json +17 -0
  67. Undefined/skills/agents/file_analysis_agent/tools/extract_xlsx/handler.py +101 -0
  68. Undefined/skills/agents/file_analysis_agent/tools/get_current_time/config.json +12 -0
  69. Undefined/skills/agents/file_analysis_agent/tools/get_current_time/handler.py +5 -0
  70. Undefined/skills/agents/file_analysis_agent/tools/read_text_file/config.json +21 -0
  71. Undefined/skills/agents/file_analysis_agent/tools/read_text_file/handler.py +90 -0
  72. Undefined/skills/agents/info_agent/config.json +17 -0
  73. Undefined/skills/agents/info_agent/handler.py +220 -0
  74. Undefined/skills/agents/info_agent/intro.md +22 -0
  75. Undefined/skills/agents/info_agent/prompt.md +27 -0
  76. Undefined/skills/agents/info_agent/tools/__init__.py +1 -0
  77. Undefined/skills/agents/info_agent/tools/baiduhot/config.json +18 -0
  78. Undefined/skills/agents/info_agent/tools/baiduhot/handler.py +49 -0
  79. Undefined/skills/agents/info_agent/tools/base64/config.json +22 -0
  80. Undefined/skills/agents/info_agent/tools/base64/handler.py +44 -0
  81. Undefined/skills/agents/info_agent/tools/douyinhot/config.json +18 -0
  82. Undefined/skills/agents/info_agent/tools/douyinhot/handler.py +53 -0
  83. Undefined/skills/agents/info_agent/tools/get_current_time/config.json +12 -0
  84. Undefined/skills/agents/info_agent/tools/get_current_time/handler.py +5 -0
  85. Undefined/skills/agents/info_agent/tools/gold_price/config.json +12 -0
  86. Undefined/skills/agents/info_agent/tools/gold_price/handler.py +58 -0
  87. Undefined/skills/agents/info_agent/tools/hash/config.json +22 -0
  88. Undefined/skills/agents/info_agent/tools/hash/handler.py +43 -0
  89. Undefined/skills/agents/info_agent/tools/history/config.json +12 -0
  90. Undefined/skills/agents/info_agent/tools/history/handler.py +37 -0
  91. Undefined/skills/agents/info_agent/tools/net_check/config.json +17 -0
  92. Undefined/skills/agents/info_agent/tools/net_check/handler.py +117 -0
  93. Undefined/skills/agents/info_agent/tools/news_tencent/config.json +17 -0
  94. Undefined/skills/agents/info_agent/tools/news_tencent/handler.py +38 -0
  95. Undefined/skills/agents/info_agent/tools/qq_level_query/config.json +29 -0
  96. Undefined/skills/agents/info_agent/tools/qq_level_query/handler.py +48 -0
  97. Undefined/skills/agents/info_agent/tools/speed/config.json +17 -0
  98. Undefined/skills/agents/info_agent/tools/speed/handler.py +37 -0
  99. Undefined/skills/agents/info_agent/tools/tcping/config.json +21 -0
  100. Undefined/skills/agents/info_agent/tools/tcping/handler.py +53 -0
  101. Undefined/skills/agents/info_agent/tools/weather_query/config.json +22 -0
  102. Undefined/skills/agents/info_agent/tools/weather_query/handler.py +207 -0
  103. Undefined/skills/agents/info_agent/tools/weibohot/config.json +18 -0
  104. Undefined/skills/agents/info_agent/tools/weibohot/handler.py +49 -0
  105. Undefined/skills/agents/info_agent/tools/whois/config.json +17 -0
  106. Undefined/skills/agents/info_agent/tools/whois/handler.py +63 -0
  107. Undefined/skills/agents/naga_code_analysis_agent/config.json +17 -0
  108. Undefined/skills/agents/naga_code_analysis_agent/handler.py +222 -0
  109. Undefined/skills/agents/naga_code_analysis_agent/intro.md +17 -0
  110. Undefined/skills/agents/naga_code_analysis_agent/prompt.md +19 -0
  111. Undefined/skills/agents/naga_code_analysis_agent/tools/__init__.py +1 -0
  112. Undefined/skills/agents/naga_code_analysis_agent/tools/get_current_time/config.json +12 -0
  113. Undefined/skills/agents/naga_code_analysis_agent/tools/get_current_time/handler.py +5 -0
  114. Undefined/skills/agents/naga_code_analysis_agent/tools/glob/config.json +17 -0
  115. Undefined/skills/agents/naga_code_analysis_agent/tools/glob/handler.py +37 -0
  116. Undefined/skills/agents/naga_code_analysis_agent/tools/list_directory/config.json +17 -0
  117. Undefined/skills/agents/naga_code_analysis_agent/tools/list_directory/handler.py +31 -0
  118. Undefined/skills/agents/naga_code_analysis_agent/tools/read_file/config.json +17 -0
  119. Undefined/skills/agents/naga_code_analysis_agent/tools/read_file/handler.py +66 -0
  120. Undefined/skills/agents/naga_code_analysis_agent/tools/read_naga_intro/config.json +12 -0
  121. Undefined/skills/agents/naga_code_analysis_agent/tools/read_naga_intro/handler.py +327 -0
  122. Undefined/skills/agents/naga_code_analysis_agent/tools/search_file_content/config.json +25 -0
  123. Undefined/skills/agents/naga_code_analysis_agent/tools/search_file_content/handler.py +46 -0
  124. Undefined/skills/agents/scheduler_agent/__init__.py +1 -0
  125. Undefined/skills/agents/scheduler_agent/config.json +17 -0
  126. Undefined/skills/agents/scheduler_agent/handler.py +218 -0
  127. Undefined/skills/agents/scheduler_agent/intro.md +17 -0
  128. Undefined/skills/agents/scheduler_agent/prompt.md +67 -0
  129. Undefined/skills/agents/scheduler_agent/tools/__init__.py +1 -0
  130. Undefined/skills/agents/scheduler_agent/tools/create_schedule_task/config.json +37 -0
  131. Undefined/skills/agents/scheduler_agent/tools/create_schedule_task/handler.py +68 -0
  132. Undefined/skills/agents/scheduler_agent/tools/delete_schedule_task/config.json +19 -0
  133. Undefined/skills/agents/scheduler_agent/tools/delete_schedule_task/handler.py +26 -0
  134. Undefined/skills/agents/scheduler_agent/tools/get_current_time/config.json +12 -0
  135. Undefined/skills/agents/scheduler_agent/tools/get_current_time/handler.py +5 -0
  136. Undefined/skills/agents/scheduler_agent/tools/list_schedule_tasks/config.json +11 -0
  137. Undefined/skills/agents/scheduler_agent/tools/list_schedule_tasks/handler.py +47 -0
  138. Undefined/skills/agents/scheduler_agent/tools/update_schedule_task/config.json +39 -0
  139. Undefined/skills/agents/scheduler_agent/tools/update_schedule_task/handler.py +46 -0
  140. Undefined/skills/agents/social_agent/config.json +17 -0
  141. Undefined/skills/agents/social_agent/handler.py +220 -0
  142. Undefined/skills/agents/social_agent/intro.md +17 -0
  143. Undefined/skills/agents/social_agent/prompt.md +19 -0
  144. Undefined/skills/agents/social_agent/tools/__init__.py +1 -0
  145. Undefined/skills/agents/social_agent/tools/bilibili_search/config.json +21 -0
  146. Undefined/skills/agents/social_agent/tools/bilibili_search/handler.py +68 -0
  147. Undefined/skills/agents/social_agent/tools/bilibili_user_info/config.json +17 -0
  148. Undefined/skills/agents/social_agent/tools/bilibili_user_info/handler.py +68 -0
  149. Undefined/skills/agents/social_agent/tools/get_current_time/config.json +12 -0
  150. Undefined/skills/agents/social_agent/tools/get_current_time/handler.py +5 -0
  151. Undefined/skills/agents/social_agent/tools/music_global_search/config.json +21 -0
  152. Undefined/skills/agents/social_agent/tools/music_global_search/handler.py +47 -0
  153. Undefined/skills/agents/social_agent/tools/music_info_get/config.json +22 -0
  154. Undefined/skills/agents/social_agent/tools/music_info_get/handler.py +35 -0
  155. Undefined/skills/agents/social_agent/tools/music_lyrics/config.json +22 -0
  156. Undefined/skills/agents/social_agent/tools/music_lyrics/handler.py +26 -0
  157. Undefined/skills/agents/social_agent/tools/video_random_recommend/config.json +21 -0
  158. Undefined/skills/agents/social_agent/tools/video_random_recommend/handler.py +21 -0
  159. Undefined/skills/agents/web_agent/config.json +17 -0
  160. Undefined/skills/agents/web_agent/handler.py +221 -0
  161. Undefined/skills/agents/web_agent/intro.md +14 -0
  162. Undefined/skills/agents/web_agent/prompt.md +16 -0
  163. Undefined/skills/agents/web_agent/tools/__init__.py +1 -0
  164. Undefined/skills/agents/web_agent/tools/crawl_webpage/config.json +21 -0
  165. Undefined/skills/agents/web_agent/tools/crawl_webpage/handler.py +102 -0
  166. Undefined/skills/agents/web_agent/tools/get_current_time/config.json +12 -0
  167. Undefined/skills/agents/web_agent/tools/get_current_time/handler.py +5 -0
  168. Undefined/skills/agents/web_agent/tools/web_search/config.json +21 -0
  169. Undefined/skills/agents/web_agent/tools/web_search/handler.py +29 -0
  170. Undefined/skills/tools/README.md +85 -0
  171. Undefined/skills/tools/__init__.py +120 -0
  172. Undefined/skills/tools/debug/config.json +17 -0
  173. Undefined/skills/tools/debug/handler.py +35 -0
  174. Undefined/skills/tools/end/config.json +17 -0
  175. Undefined/skills/tools/end/handler.py +24 -0
  176. Undefined/skills/tools/get_current_time/config.json +12 -0
  177. Undefined/skills/tools/get_current_time/handler.py +5 -0
  178. Undefined/skills/tools/get_forward_msg/config.json +17 -0
  179. Undefined/skills/tools/get_forward_msg/handler.py +131 -0
  180. Undefined/skills/tools/get_group_member_info/config.json +38 -0
  181. Undefined/skills/tools/get_group_member_info/handler.py +142 -0
  182. Undefined/skills/tools/get_messages_by_time/config.json +30 -0
  183. Undefined/skills/tools/get_messages_by_time/handler.py +128 -0
  184. Undefined/skills/tools/get_picture/config.json +45 -0
  185. Undefined/skills/tools/get_picture/handler.py +191 -0
  186. Undefined/skills/tools/get_recent_messages/config.json +30 -0
  187. Undefined/skills/tools/get_recent_messages/handler.py +88 -0
  188. Undefined/skills/tools/qq_like/config.json +22 -0
  189. Undefined/skills/tools/qq_like/handler.py +58 -0
  190. Undefined/skills/tools/render_html/config.json +26 -0
  191. Undefined/skills/tools/render_html/handler.py +39 -0
  192. Undefined/skills/tools/render_latex/config.json +26 -0
  193. Undefined/skills/tools/render_latex/handler.py +78 -0
  194. Undefined/skills/tools/render_markdown/config.json +26 -0
  195. Undefined/skills/tools/render_markdown/handler.py +63 -0
  196. Undefined/skills/tools/save_memory/config.json +17 -0
  197. Undefined/skills/tools/save_memory/handler.py +17 -0
  198. Undefined/skills/tools/send_message/config.json +21 -0
  199. Undefined/skills/tools/send_message/handler.py +60 -0
  200. Undefined/skills/tools/send_private_message/config.json +21 -0
  201. Undefined/skills/tools/send_private_message/handler.py +35 -0
  202. Undefined/utils/__init__.py +0 -0
  203. Undefined/utils/common.py +186 -0
  204. Undefined/utils/history.py +284 -0
  205. Undefined/utils/scheduler.py +286 -0
  206. Undefined/utils/sender.py +140 -0
  207. undefined_bot-2.1.0.dist-info/METADATA +259 -0
  208. undefined_bot-2.1.0.dist-info/RECORD +211 -0
  209. undefined_bot-2.1.0.dist-info/WHEEL +4 -0
  210. undefined_bot-2.1.0.dist-info/entry_points.txt +2 -0
  211. undefined_bot-2.1.0.dist-info/licenses/LICENSE +7 -0
@@ -0,0 +1,120 @@
1
+ import json
2
+ import logging
3
+ import importlib.util
4
+ import asyncio
5
+ from pathlib import Path
6
+ from typing import Dict, Any, List, Callable, Awaitable
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class ToolRegistry:
12
+ def __init__(self, tools_dir: str | Path | None = None):
13
+ if tools_dir is None:
14
+ # 默认为此文件所在的目录
15
+ self.tools_dir = Path(__file__).parent
16
+ else:
17
+ self.tools_dir = Path(tools_dir)
18
+
19
+ self._tools_schema: List[Dict[str, Any]] = []
20
+ self._tools_handlers: Dict[
21
+ str, Callable[[Dict[str, Any], Dict[str, Any]], Awaitable[Any]]
22
+ ] = {}
23
+ self.load_tools()
24
+
25
+ def load_tools(self) -> None:
26
+ """从 tools 目录发现并加载工具。"""
27
+ self._tools_schema = []
28
+ self._tools_handlers = {}
29
+
30
+ if not self.tools_dir.exists():
31
+ logger.warning(f"工具目录不存在: {self.tools_dir}")
32
+ return
33
+
34
+ for item in self.tools_dir.iterdir():
35
+ if item.is_dir() and not item.name.startswith("_"):
36
+ self._load_tool_from_dir(item)
37
+
38
+ tool_names = list(self._tools_handlers.keys())
39
+ logger.info(
40
+ f"成功加载了 {len(self._tools_schema)} 个工具: {', '.join(tool_names)}"
41
+ )
42
+
43
+ def _load_tool_from_dir(self, tool_dir: Path) -> None:
44
+ """从目录加载单个工具。"""
45
+ config_path = tool_dir / "config.json"
46
+ handler_path = tool_dir / "handler.py"
47
+
48
+ if not config_path.exists() or not handler_path.exists():
49
+ logger.debug(
50
+ f"[工具加载] 目录 {tool_dir} 缺少 config.json 或 handler.py,跳过"
51
+ )
52
+ return
53
+
54
+ # 加载配置
55
+ try:
56
+ with open(config_path, "r", encoding="utf-8") as f:
57
+ config = json.load(f)
58
+
59
+ # 基本验证
60
+ if "name" not in config.get("function", {}):
61
+ logger.error(f"[工具错误] 工具配置无效 {tool_dir}: 缺少 function.name")
62
+ return
63
+
64
+ tool_name = config["function"]["name"]
65
+ logger.debug(f"[工具加载] 正在从 {tool_dir} 加载工具: {tool_name}")
66
+
67
+ except Exception as e:
68
+ logger.error(f"[工具错误] 从 {tool_dir} 加载工具配置失败: {e}")
69
+ return
70
+
71
+ # 加载处理器
72
+ try:
73
+ spec = importlib.util.spec_from_file_location(
74
+ f"tools.{tool_name}", handler_path
75
+ )
76
+ if spec is None or spec.loader is None:
77
+ logger.error(f"从 {handler_path} 加载工具处理器 spec 失败")
78
+ return
79
+
80
+ module = importlib.util.module_from_spec(spec)
81
+ spec.loader.exec_module(module)
82
+
83
+ if not hasattr(module, "execute"):
84
+ logger.error(f"工具 {tool_dir} 的处理器缺少 'execute' 函数")
85
+ return
86
+
87
+ self._tools_schema.append(config)
88
+ self._tools_handlers[tool_name] = module.execute
89
+
90
+ except Exception as e:
91
+ logger.error(f"从 {tool_dir} 加载工具处理器失败: {e}")
92
+
93
+ def get_tools_schema(self) -> List[Dict[str, Any]]:
94
+ """返回 AI 模型的工具定义列表。"""
95
+ return self._tools_schema
96
+
97
+ async def execute_tool(
98
+ self, tool_name: str, args: Dict[str, Any], context: Dict[str, Any]
99
+ ) -> str:
100
+ """根据名称执行工具。"""
101
+ handler = self._tools_handlers.get(tool_name)
102
+ if not handler:
103
+ return f"未找到工具: {tool_name}"
104
+
105
+ try:
106
+ # 检查处理器是否为协程
107
+ start_time = asyncio.get_event_loop().time()
108
+ if asyncio.iscoroutinefunction(handler):
109
+ result = await handler(args, context)
110
+ else:
111
+ # 我们预期工具是异步的,但也支持同步以防万一
112
+ # 注意:我们的类型提示是 Awaitable,所以这只是为了安全
113
+ result = handler(args, context)
114
+
115
+ duration = asyncio.get_event_loop().time() - start_time
116
+ logger.info(f"[工具执行] {tool_name} 执行成功, 耗时={duration:.4f}s")
117
+ return str(result)
118
+ except Exception as e:
119
+ logger.exception(f"[工具异常] 执行工具 {tool_name} 时出错")
120
+ return f"执行工具 {tool_name} 时出错: {str(e)}"
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "debug",
5
+ "description": "记录调试信息,用于输出决策过程、思维路径、工具调用和结果等。仅在调试模式下使用(通过 debug:on 启用)。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "content": {
10
+ "type": "string",
11
+ "description": "调试信息内容,包括触发条件判断、上下文分析、最终决策理由等"
12
+ }
13
+ },
14
+ "required": ["content"]
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,35 @@
1
+ import logging
2
+ import uuid
3
+ from pathlib import Path
4
+ from typing import Any, Dict
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ # 调试数据保存目录
9
+ DEBUG_DIR = Path("data/debug")
10
+
11
+
12
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
13
+ """执行 debug 工具,保存调试信息到文本文件"""
14
+ content = args.get("content", "")
15
+ if not content:
16
+ return "调试内容不能为空"
17
+
18
+ # 确保目录存在
19
+ DEBUG_DIR.mkdir(parents=True, exist_ok=True)
20
+
21
+ # 生成 UUID 作为文件名
22
+ file_uuid = uuid.uuid4()
23
+ filename = f"{file_uuid}.txt"
24
+ filepath = DEBUG_DIR / filename
25
+
26
+ # 保存到文件
27
+ try:
28
+ with open(filepath, "w", encoding="utf-8") as f:
29
+ f.write(content)
30
+
31
+ logger.info(f"调试信息已保存到: {filepath}")
32
+ return f"调试信息已保存(UUID: {file_uuid})"
33
+ except Exception as e:
34
+ logger.error(f"保存调试信息失败: {e}")
35
+ return f"保存失败: {e}"
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "end",
5
+ "description": "结束对话。发送完所有消息后,必须且只能调用一次此工具来结束对话。如果这次做了什么或以后可能要做什么,必须填写summary参数记录下来。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "summary": {
10
+ "type": "string",
11
+ "description": "记录这次做了什么或以后可能要做什么。如果只是end了不做事,不需要填写。如果做了什么或以后可能要做什么,必须填写。最多保留100条记录。"
12
+ }
13
+ },
14
+ "required": []
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,24 @@
1
+ from typing import Any, Dict
2
+ import logging
3
+
4
+ logger = logging.getLogger(__name__)
5
+
6
+
7
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
8
+ summary = args.get("summary", "")
9
+ if summary:
10
+ end_summaries = context.get("end_summaries")
11
+ if end_summaries is not None:
12
+ end_summaries.append(summary)
13
+ logger.info(f"保存end记录: {summary[:50]}...")
14
+
15
+ # 持久化保存
16
+ end_summary_storage = context.get("end_summary_storage")
17
+ if end_summary_storage:
18
+ # 转换 deque 为 list 进行序列化
19
+ end_summary_storage.save(list(end_summaries))
20
+
21
+ # 通知调用方对话应结束
22
+ context["conversation_ended"] = True
23
+
24
+ return "对话已结束"
@@ -0,0 +1,12 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "get_current_time",
5
+ "description": "获取当前系统时间。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {},
9
+ "required": []
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,5 @@
1
+ from typing import Any, Dict
2
+ from datetime import datetime
3
+
4
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
5
+ return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "get_forward_msg",
5
+ "description": "获取合并转发消息的详情内容。当你在聊天记录中看到 [合并转发: ID] 时,可以使用此工具获取其包含的具体消息列表。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "message_id": {
10
+ "type": "string",
11
+ "description": "合并转发消息的 ID"
12
+ }
13
+ },
14
+ "required": ["message_id"]
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,131 @@
1
+ from typing import Any, Dict
2
+ from datetime import datetime
3
+ import logging
4
+ import json
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+
9
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
10
+ message_id = args.get("message_id")
11
+ if not message_id:
12
+ return "错误:message_id 不能为空"
13
+
14
+ get_forward_msg_callback = context.get("get_forward_msg_callback")
15
+ if not get_forward_msg_callback:
16
+ return "错误:获取合并转发消息的回调未设置"
17
+
18
+ try:
19
+ nodes = await get_forward_msg_callback(message_id)
20
+ if not nodes:
21
+ return "未能获取到合并转发消息的内容或内容为空"
22
+
23
+ logger.info(f"成功获取合并转发内容,节点数: {len(nodes)}")
24
+
25
+ formatted_messages = []
26
+ for i, node in enumerate(nodes):
27
+ # 记录第一个节点的结构用于调试
28
+ if i == 0:
29
+ logger.debug(
30
+ f"合并转发节点示例结构: {json.dumps(node, ensure_ascii=False)[:500]}"
31
+ )
32
+
33
+ sender = node.get("sender") or {}
34
+ # 兼容有些实现直接把发送者信息放在节点根部
35
+ sender_name = (
36
+ sender.get("nickname")
37
+ or node.get("nickname")
38
+ or sender.get("card")
39
+ or node.get("card")
40
+ or "未知用户"
41
+ )
42
+ sender_id = sender.get("user_id") or node.get("user_id") or "未知ID"
43
+
44
+ node_time = node.get("time")
45
+ if node_time:
46
+ try:
47
+ timestamp = datetime.fromtimestamp(float(node_time)).strftime(
48
+ "%Y-%m-%d %H:%M:%S"
49
+ )
50
+ except (ValueError, TypeError):
51
+ timestamp = str(node_time)
52
+ else:
53
+ timestamp = "未知时间"
54
+
55
+ # 激进的内容提取:尝试所有可能的字段
56
+ raw_content = (
57
+ node.get("content") or node.get("message") or node.get("raw_message")
58
+ )
59
+
60
+ text_parts = []
61
+ if raw_content is None:
62
+ text_parts.append("(消息内容字段缺失)")
63
+ elif isinstance(raw_content, str):
64
+ text_parts.append(raw_content)
65
+ elif isinstance(raw_content, dict):
66
+ # 单个消息段
67
+ raw_content = [raw_content]
68
+
69
+ if isinstance(raw_content, list):
70
+ for segment in raw_content:
71
+ if isinstance(segment, str):
72
+ text_parts.append(segment)
73
+ continue
74
+ if not isinstance(segment, dict):
75
+ continue
76
+
77
+ seg_type = segment.get("type")
78
+ seg_data = segment.get("data", {})
79
+
80
+ if seg_type == "text":
81
+ text_parts.append(seg_data.get("text", ""))
82
+ elif seg_type == "at":
83
+ qq = seg_data.get("qq", "")
84
+ text_parts.append(f"[@ {qq}]")
85
+ elif seg_type == "image":
86
+ file = seg_data.get("file", "") or seg_data.get("url", "")
87
+ text_parts.append(f"[图片: {file}]")
88
+ elif seg_type == "forward":
89
+ inner_id = seg_data.get("id")
90
+ text_parts.append(f"[合并转发: {inner_id}]")
91
+ elif seg_type == "reply":
92
+ text_parts.append("[引用]")
93
+ elif seg_type == "face":
94
+ text_parts.append("[表情]")
95
+ elif seg_type == "json":
96
+ # 尝试从 JSON 中提取描述
97
+ try:
98
+ j_data = json.loads(seg_data.get("data", "{}"))
99
+ desc = (
100
+ j_data.get("meta", {})
101
+ .get("detail", {})
102
+ .get("desc", "JSON消息")
103
+ )
104
+ text_parts.append(f"[{desc}]")
105
+ except Exception:
106
+ text_parts.append("[JSON消息]")
107
+ elif seg_type == "xml":
108
+ text_parts.append("[XML消息]")
109
+ elif seg_type:
110
+ text_parts.append(f"[{seg_type}]")
111
+
112
+ text = "".join(text_parts).strip()
113
+ if not text:
114
+ # 如果还是空,把整个节点键名返回给 AI 辅助判断
115
+ keys = list(node.keys())
116
+ text = f"(无法解析内容,节点键名: {keys})"
117
+
118
+ # 格式:XML 标准化
119
+ formatted_messages.append(f"""<message sender="{sender_name}" sender_id="{sender_id}" location="合并转发" time="{timestamp}">
120
+ <content>{text}</content>
121
+ </message>""")
122
+
123
+ result = "\n---\n".join(formatted_messages)
124
+ logger.info(
125
+ f"get_forward_msg 处理完成,返回数据样例 (前500字符): {result[:500]}..."
126
+ )
127
+ return result
128
+
129
+ except Exception as e:
130
+ logger.exception(f"解析合并转发消息时出错: {e}")
131
+ return f"解析合并转发消息时出错: {str(e)}"
@@ -0,0 +1,38 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "get_group_member_info",
5
+ "description": "获取群聊成员的详细信息。可以指定要获取的字段和字段数目,支持获取:群昵称、QQ昵称、QQ号(cqid)、加群时间、入群时间戳、等级、活跃度、最后发言时间、最后活跃时间戳、历史消息数量等。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "group_id": {
10
+ "type": "integer",
11
+ "description": "群号"
12
+ },
13
+ "user_id": {
14
+ "type": "integer",
15
+ "description": "群成员的QQ号"
16
+ },
17
+ "fields": {
18
+ "type": "array",
19
+ "description": "指定要获取的字段列表。可选字段:nickname(QQ昵称)、card(群昵称)、user_id(QQ号)、join_time(加群时间)、last_sent_time(最后发言时间)、level(等级)、role(角色)、unfriendly(是否不友好)、title(头衔)、title_expire_time(头衔过期时间)、shut_up_timestamp(禁言截止时间)",
20
+ "items": {
21
+ "type": "string",
22
+ "enum": ["nickname", "card", "user_id", "join_time", "last_sent_time", "level", "role", "unfriendly", "title", "title_expire_time", "shut_up_timestamp"]
23
+ }
24
+ },
25
+ "limit": {
26
+ "type": "integer",
27
+ "description": "限制返回的字段数量(当 fields 未指定时有效),默认返回所有字段"
28
+ },
29
+ "no_cache": {
30
+ "type": "boolean",
31
+ "description": "是否不使用缓存获取最新信息,默认 false",
32
+ "default": false
33
+ }
34
+ },
35
+ "required": ["group_id", "user_id"]
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,142 @@
1
+ from typing import Any, Dict
2
+ import logging
3
+ from datetime import datetime
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ FIELD_MAPPING = {
8
+ "nickname": "QQ昵称",
9
+ "card": "群昵称",
10
+ "user_id": "QQ号",
11
+ "join_time": "加群时间",
12
+ "last_sent_time": "最后发言时间",
13
+ "level": "等级",
14
+ "role": "角色",
15
+ "unfriendly": "是否不友好",
16
+ "title": "头衔",
17
+ "title_expire_time": "头衔过期时间",
18
+ "shut_up_timestamp": "禁言截止时间",
19
+ }
20
+
21
+
22
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
23
+ """获取群聊成员的详细信息
24
+
25
+ 参数:
26
+ args: 工具参数,包含 group_id、user_id、fields、limit、no_cache
27
+ context: 工具上下文,包含 onebot_client 等回调函数
28
+
29
+ 返回:
30
+ 群成员详细信息描述
31
+ """
32
+ group_id = args.get("group_id")
33
+ user_id = args.get("user_id")
34
+ fields = args.get("fields")
35
+ limit = args.get("limit")
36
+ no_cache = args.get("no_cache", False)
37
+
38
+ if group_id is None:
39
+ return "请提供群号(group_id参数)"
40
+ if user_id is None:
41
+ return "请提供要查询的群成员QQ号(user_id参数)"
42
+
43
+ try:
44
+ group_id = int(group_id)
45
+ user_id = int(user_id)
46
+ except (ValueError, TypeError):
47
+ return "参数类型错误:group_id 和 user_id 必须是整数"
48
+
49
+ onebot_client = context.get("onebot_client")
50
+ if not onebot_client:
51
+ return "获取群成员信息功能不可用(OneBot 客户端未设置)"
52
+
53
+ try:
54
+ member_info = await onebot_client.get_group_member_info(
55
+ group_id, user_id, no_cache
56
+ )
57
+
58
+ if not member_info:
59
+ return f"未找到群 {group_id} 中 QQ {user_id} 的成员信息,可能该用户已退群或群号不正确"
60
+
61
+ result_parts = []
62
+ nickname = member_info.get("nickname", "")
63
+ card = member_info.get("card", "")
64
+
65
+ result_parts.append(f"【群成员信息】群号: {group_id}")
66
+
67
+ display_name = card if card else nickname
68
+ if display_name:
69
+ result_parts.append(f"昵称: {display_name}")
70
+
71
+ if fields:
72
+ for field in fields:
73
+ if field in FIELD_MAPPING:
74
+ value = member_info.get(field)
75
+ if value is not None:
76
+ if field in [
77
+ "join_time",
78
+ "last_sent_time",
79
+ "title_expire_time",
80
+ "shut_up_timestamp",
81
+ ]:
82
+ try:
83
+ if isinstance(value, (int, float)):
84
+ dt = datetime.fromtimestamp(value)
85
+ value = dt.strftime("%Y-%m-%d %H:%M:%S")
86
+ except (ValueError, TypeError, OSError):
87
+ pass
88
+ elif field == "role":
89
+ role_map = {
90
+ "owner": "群主",
91
+ "admin": "管理员",
92
+ "member": "成员",
93
+ }
94
+ value = role_map.get(str(value), str(value))
95
+ elif field == "unfriendly":
96
+ value = "是" if value else "否"
97
+ result_parts.append(f"{FIELD_MAPPING[field]}: {value}")
98
+ else:
99
+ for field, display_name_field in FIELD_MAPPING.items():
100
+ value = member_info.get(field)
101
+ if value is not None:
102
+ if field in [
103
+ "join_time",
104
+ "last_sent_time",
105
+ "title_expire_time",
106
+ "shut_up_timestamp",
107
+ ]:
108
+ try:
109
+ if isinstance(value, (int, float)):
110
+ dt = datetime.fromtimestamp(value)
111
+ value = dt.strftime("%Y-%m-%d %H:%M:%S")
112
+ except (ValueError, TypeError, OSError):
113
+ pass
114
+ elif field == "role":
115
+ role_map = {
116
+ "owner": "群主",
117
+ "admin": "管理员",
118
+ "member": "成员",
119
+ }
120
+ value = role_map.get(str(value), str(value))
121
+ elif field == "unfriendly":
122
+ value = "是" if value else "否"
123
+ result_parts.append(f"{display_name_field}: {value}")
124
+
125
+ if limit and len(result_parts) > limit:
126
+ result_parts = result_parts[:limit]
127
+
128
+ result_str = "\n".join(result_parts)
129
+ return f"{result_str}\n✅ 信息获取成功"
130
+
131
+ except Exception as e:
132
+ logger.exception(f"获取群成员信息失败: {e}")
133
+ error_msg = str(e)
134
+
135
+ if "retcode=100" in error_msg:
136
+ return "获取失败:群号或QQ号不存在"
137
+ elif "retcode=140" in error_msg:
138
+ return "获取失败:无法获取非好友的群成员信息"
139
+ elif "retcode=150" in error_msg:
140
+ return "获取失败:群成员信息获取频率过高"
141
+ else:
142
+ return f"获取失败:{error_msg}"
@@ -0,0 +1,30 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "get_messages_by_time",
5
+ "description": "根据时间范围检索消息。用于查找特定时间段内的聊天记录。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "chat_id": {
10
+ "type": "string",
11
+ "description": "聊天ID(群号或QQ号)"
12
+ },
13
+ "type": {
14
+ "type": "string",
15
+ "description": "聊天类型(group 或 private)",
16
+ "enum": ["group", "private"]
17
+ },
18
+ "start_time": {
19
+ "type": "string",
20
+ "description": "开始时间(格式:YYYY-MM-DD HH:MM:SS,例如:2025-12-29 10:00:00)"
21
+ },
22
+ "end_time": {
23
+ "type": "string",
24
+ "description": "结束时间(格式:YYYY-MM-DD HH:MM:SS,例如:2025-12-29 12:00:00)"
25
+ }
26
+ },
27
+ "required": ["chat_id", "type", "start_time", "end_time"]
28
+ }
29
+ }
30
+ }