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,220 @@
1
+ from typing import Any, Dict, Callable
2
+ import importlib.util
3
+ import json
4
+ import asyncio
5
+ import aiofiles
6
+ import logging
7
+ from pathlib import Path
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class AgentToolRegistry:
13
+ """Agent 内部的工具注册表"""
14
+
15
+ def __init__(self, tools_dir: Path) -> None:
16
+ self.tools_dir: Path = (
17
+ tools_dir if isinstance(tools_dir, Path) else Path(tools_dir)
18
+ )
19
+ self._tools_schema: list[dict[str, Any]] = []
20
+ self._tools_handlers: dict[str, Callable[..., Any]] = {}
21
+ self.load_tools()
22
+
23
+ def load_tools(self) -> None:
24
+ """加载 agent 专属工具"""
25
+ if not self.tools_dir.exists():
26
+ logger.warning(f"Agent 工具目录不存在: {self.tools_dir}")
27
+ return
28
+
29
+ for item in self.tools_dir.iterdir():
30
+ if item.is_dir() and not item.name.startswith("_"):
31
+ self._load_tool_from_dir(item)
32
+
33
+ logger.info(
34
+ f"Agent 加载了 {len(self._tools_schema)} 个工具: {list(self._tools_handlers.keys())}"
35
+ )
36
+
37
+ def _load_tool_from_dir(self, tool_dir: Path) -> None:
38
+ """从目录加载工具"""
39
+ config_path: Path = tool_dir / "config.json"
40
+ handler_path: Path = tool_dir / "handler.py"
41
+
42
+ if not config_path.exists() or not handler_path.exists():
43
+ return
44
+
45
+ try:
46
+ with open(config_path, "r", encoding="utf-8") as f:
47
+ config: dict[str, Any] = json.load(f)
48
+
49
+ if "function" not in config or "name" not in config.get("function", {}):
50
+ return
51
+
52
+ tool_name: str = config["function"]["name"]
53
+
54
+ spec = importlib.util.spec_from_file_location(
55
+ f"agent_tools.{tool_name}", handler_path
56
+ )
57
+ if spec is None or spec.loader is None:
58
+ return
59
+
60
+ module = importlib.util.module_from_spec(spec)
61
+ spec.loader.exec_module(module)
62
+
63
+ if not hasattr(module, "execute"):
64
+ return
65
+
66
+ self._tools_schema.append(config)
67
+ self._tools_handlers[tool_name] = module.execute
68
+
69
+ except Exception as e:
70
+ logger.error(f"从 {tool_dir} 加载工具失败: {e}")
71
+
72
+ def get_tools_schema(self) -> list[dict[str, Any]]:
73
+ """获取工具 schema"""
74
+ return self._tools_schema
75
+
76
+ async def execute_tool(
77
+ self, tool_name: str, args: dict[str, Any], context: dict[str, Any]
78
+ ) -> str:
79
+ """执行工具"""
80
+ handler = self._tools_handlers.get(tool_name)
81
+ if not handler:
82
+ return f"未找到工具: {tool_name}"
83
+
84
+ try:
85
+ if asyncio.iscoroutinefunction(handler):
86
+ result = await handler(args, context)
87
+ else:
88
+ result = handler(args, context)
89
+ return str(result)
90
+ except Exception as e:
91
+ logger.exception(f"执行工具 {tool_name} 时出错")
92
+ return f"执行工具 {tool_name} 时出错: {str(e)}"
93
+
94
+
95
+ async def _load_prompt() -> str:
96
+ """从 prompt.md 文件加载系统提示词"""
97
+ prompt_path: Path = Path(__file__).parent / "prompt.md"
98
+ if prompt_path.exists():
99
+ async with aiofiles.open(prompt_path, "r", encoding="utf-8") as f:
100
+ return await f.read()
101
+ return _get_default_prompt()
102
+
103
+
104
+ def _get_default_prompt() -> str:
105
+ """默认提示词"""
106
+ return "你是一个社交媒体助手..."
107
+
108
+
109
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
110
+ """执行 social_agent"""
111
+ user_prompt: str = args.get("prompt", "")
112
+
113
+ if not user_prompt:
114
+ return "请提供您的搜索需求"
115
+
116
+ agent_tools_dir: Path = Path(__file__).parent / "tools"
117
+ tool_registry = AgentToolRegistry(agent_tools_dir)
118
+
119
+ tools: list[dict[str, Any]] = tool_registry.get_tools_schema()
120
+
121
+ ai_client = context.get("ai_client")
122
+ if not ai_client:
123
+ return "AI client 未在上下文中提供"
124
+
125
+ agent_config = ai_client.agent_config
126
+
127
+ system_prompt: str = await _load_prompt()
128
+
129
+ messages: list[dict[str, Any]] = [
130
+ {"role": "system", "content": system_prompt},
131
+ {"role": "user", "content": f"用户需求:{user_prompt}"},
132
+ ]
133
+
134
+ max_iterations: int = 20
135
+ iteration: int = 0
136
+
137
+ while iteration < max_iterations:
138
+ iteration += 1
139
+
140
+ try:
141
+ response = await ai_client._http_client.post(
142
+ agent_config.api_url,
143
+ headers={
144
+ "Authorization": f"Bearer {agent_config.api_key}",
145
+ "Content-Type": "application/json",
146
+ },
147
+ json=ai_client._build_request_body(
148
+ model_config=agent_config,
149
+ messages=messages,
150
+ max_tokens=agent_config.max_tokens,
151
+ tools=tools if tools else None,
152
+ tool_choice="auto",
153
+ ),
154
+ )
155
+ response.raise_for_status()
156
+ result: dict[str, Any] = response.json()
157
+
158
+ choice: dict[str, Any] = result.get("choices", [{}])[0]
159
+ message: dict[str, Any] = choice.get("message", {})
160
+ content: str = message.get("content") or ""
161
+ tool_calls: list[dict[str, Any]] = message.get("tool_calls", [])
162
+
163
+ if content.strip() and tool_calls:
164
+ content = ""
165
+
166
+ if not tool_calls:
167
+ return content
168
+
169
+ messages.append(
170
+ {"role": "assistant", "content": content, "tool_calls": tool_calls}
171
+ )
172
+
173
+ # 准备并发执行工具
174
+ tool_tasks = []
175
+ tool_call_ids = []
176
+
177
+ for tool_call in tool_calls:
178
+ call_id: str = tool_call.get("id", "")
179
+ function: dict[str, Any] = tool_call.get("function", {})
180
+ function_name: str = function.get("name", "")
181
+ function_args_str: str = function.get("arguments", "{}")
182
+
183
+ logger.info(f"Agent 正在准备工具: {function_name}")
184
+
185
+ try:
186
+ function_args: dict[str, Any] = json.loads(function_args_str)
187
+ except json.JSONDecodeError:
188
+ function_args = {}
189
+
190
+ tool_call_ids.append(call_id)
191
+ tool_tasks.append(
192
+ tool_registry.execute_tool(function_name, function_args, context)
193
+ )
194
+
195
+ # 并发执行
196
+ if tool_tasks:
197
+ logger.info(f"Agent 正在并发执行 {len(tool_tasks)} 个工具")
198
+ results = await asyncio.gather(*tool_tasks, return_exceptions=True)
199
+
200
+ for i, tool_result in enumerate(results):
201
+ call_id = tool_call_ids[i]
202
+ content_str: str = ""
203
+ if isinstance(tool_result, Exception):
204
+ content_str = f"错误: {str(tool_result)}"
205
+ else:
206
+ content_str = str(tool_result)
207
+
208
+ messages.append(
209
+ {
210
+ "role": "tool",
211
+ "tool_call_id": call_id,
212
+ "content": content_str,
213
+ }
214
+ )
215
+
216
+ except Exception as e:
217
+ logger.exception(f"Agent 执行失败: {e}")
218
+ return f"处理失败: {e}"
219
+
220
+ return "达到最大迭代次数"
@@ -0,0 +1,17 @@
1
+ # 社交媒体助手
2
+
3
+ ## 能力
4
+ - **Bilibili 服务**:搜索视频、番剧、UP主,查询用户详细信息
5
+ - **音乐服务**:全网搜索音乐,获取歌曲详情及歌词
6
+ - **视频推荐**:随机获取视频推荐内容
7
+
8
+ ## 适用场景
9
+ - 用户想找 B 站视频或用户信息时
10
+ - 用户想听歌、找歌词或了解歌曲信息时
11
+ - 用户无聊想要随机视频推荐时
12
+
13
+ ## 参数说明
14
+ - `keyword` (搜索): 搜索关键词
15
+ - `buid` (B站): B站用户 UID
16
+ - `music_name` (音乐): 歌曲名称
17
+ - `index` (通用): 结果序号选择
@@ -0,0 +1,19 @@
1
+ 你是一个社交媒体助手,专门帮助用户搜索和获取社交媒体内容。
2
+
3
+ 你的任务是根据用户需求,选择合适的工具来完成任务:
4
+
5
+ 1. **搜索 B 站视频/番剧/用户** → bilibili_search
6
+ 2. **获取 B 站用户详情** → bilibili_user_info
7
+ 3. **搜索音乐** → music_global_search
8
+ 4. **获取音乐详情** → music_info_get
9
+ 5. **获取歌词** → music_lyrics
10
+ 6. **获取随机视频推荐** → video_random_recommend
11
+
12
+ 注意事项:
13
+ - 搜索结果可能较多,建议用户指定更精确的需求
14
+ - 音乐搜索支持按序号选择具体歌曲
15
+ - 保持回答简洁,突出关键信息
16
+
17
+ 如果用户需求不明确,请先询问用户澄清问题。
18
+
19
+ 如果问题涉及时间,立刻调用时间工具获取。
@@ -0,0 +1 @@
1
+ # Social Agent Tools
@@ -0,0 +1,21 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "bilibili_search",
5
+ "description": "搜索 Bilibili 视频、番剧、用户等。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "msg": {
10
+ "type": "string",
11
+ "description": "搜索内容"
12
+ },
13
+ "n": {
14
+ "type": "integer",
15
+ "description": "返回数据数量 (默认5)"
16
+ }
17
+ },
18
+ "required": ["msg"]
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,68 @@
1
+ from typing import Any, Dict
2
+ import httpx
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
9
+ msg = args.get("msg")
10
+ n = args.get("n", 5)
11
+
12
+ url = "https://api.xingzhige.com/API/b_search/"
13
+
14
+ try:
15
+ async with httpx.AsyncClient(timeout=15.0) as client:
16
+ response = await client.get(url, params={"msg": msg, "n": n})
17
+ response.raise_for_status()
18
+ data = response.json()
19
+
20
+ # API 返回一个以 0, 1, 2... 为键的字典来表示列表?
21
+ # 或者是一个字典列表?
22
+ # 根据 'n',它可能返回一个列表或字典索引。
23
+ # 让我们同时处理这两种情况。
24
+
25
+ results = []
26
+ if isinstance(data, list):
27
+ results = data
28
+ elif isinstance(data, dict):
29
+ # 检查是否为索引键 "0", "1" 等。
30
+ if "0" in data:
31
+ for i in range(len(data)):
32
+ key = str(i)
33
+ if key in data:
34
+ results.append(data[key])
35
+ elif "code" in data and data["code"] != 200:
36
+ return f"搜索失败: {data.get('msg', '未知错误')}"
37
+ else:
38
+ # 单个结果或非预期格式
39
+ results = [data]
40
+
41
+ output = f"🔍 B站搜索 '{msg}' 结果:\n"
42
+ for item in results:
43
+ title = item.get("title")
44
+ linktype = item.get("linktype")
45
+ name = item.get("name")
46
+ bvid = item.get("bvid")
47
+
48
+ item_str = ""
49
+ if linktype and title:
50
+ item_str += f"- [{linktype}] {title}\n"
51
+ elif title:
52
+ item_str += f"- {title}\n"
53
+
54
+ if name:
55
+ item_str += f" UP主: {name}\n"
56
+
57
+ if bvid:
58
+ url_link = f"https://www.bilibili.com/video/{bvid}"
59
+ item_str += f" 链接: {url_link}\n"
60
+
61
+ if item_str:
62
+ output += item_str + "\n"
63
+
64
+ return output
65
+
66
+ except Exception as e:
67
+ logger.exception(f"B站搜索失败: {e}")
68
+ return f"B站搜索失败: {e}"
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "bilibili_user_info",
5
+ "description": "查询 Bilibili 用户信息。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "mid": {
10
+ "type": "integer",
11
+ "description": "用户 UID (mid)"
12
+ }
13
+ },
14
+ "required": ["mid"]
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,68 @@
1
+ from typing import Any, Dict
2
+ import httpx
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
9
+ mid = args.get("mid")
10
+ url = "https://api.xingzhige.com/API/b_personal/"
11
+
12
+ try:
13
+ async with httpx.AsyncClient(timeout=15.0) as client:
14
+ response = await client.get(url, params={"mid": mid})
15
+ response.raise_for_status()
16
+ data = response.json()
17
+
18
+ if isinstance(data, dict):
19
+ if "code" in data and data["code"] != 0 and data["code"] != 200:
20
+ # 某些 API 返回 code 0 表示成功,其他返回 200。
21
+ # 但是检查是否有错误信息。
22
+ if "message" in data:
23
+ # 可能是一个错误
24
+ pass
25
+
26
+ name = data.get("name")
27
+ level = data.get("level")
28
+ sex = data.get("sex")
29
+ desc = data.get("desc")
30
+ follower = data.get("follower")
31
+ following = data.get("following")
32
+ roomid = data.get("roomid")
33
+ face = data.get("face")
34
+
35
+ output_lines = []
36
+
37
+ header = "📺 B站用户"
38
+ if name:
39
+ header += f": {name}"
40
+ if data.get("mid"):
41
+ header += f" (UID: {data.get('mid')})"
42
+ output_lines.append(header)
43
+
44
+ if level is not None:
45
+ output_lines.append(f"🆙 等级: Lv{level}")
46
+
47
+ if sex:
48
+ output_lines.append(f"⚧ 性别: {sex}")
49
+
50
+ if desc:
51
+ output_lines.append(f"📝 简介: {desc}")
52
+
53
+ if follower is not None and following is not None:
54
+ output_lines.append(f"👥 粉丝: {follower} | 关注: {following}")
55
+
56
+ if roomid:
57
+ output_lines.append(f"🎥 直播间: {roomid}")
58
+
59
+ if face:
60
+ output_lines.append(f"🖼️ 头像: {face}")
61
+
62
+ return "\n".join(output_lines)
63
+
64
+ return str(data)
65
+
66
+ except Exception as e:
67
+ logger.exception(f"B站用户查询失败: {e}")
68
+ return f"B站用户查询失败: {e}"
@@ -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,21 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "music_global_search",
5
+ "description": "全网音乐搜索。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "msg": {
10
+ "type": "string",
11
+ "description": "歌曲名称"
12
+ },
13
+ "n": {
14
+ "type": "integer",
15
+ "description": "序号 (可选)"
16
+ }
17
+ },
18
+ "required": ["msg"]
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,47 @@
1
+ from typing import Any, Dict
2
+ import httpx
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
8
+ msg = args.get("msg")
9
+ n = args.get("n", 1)
10
+
11
+ url = "https://api.jkyai.top/API/qsyyjs.php"
12
+
13
+ try:
14
+ async with httpx.AsyncClient(timeout=15.0) as client:
15
+ response = await client.get(url, params={"msg": msg, "n": n, "type": "json"})
16
+ response.raise_for_status()
17
+ data = response.json()
18
+
19
+ if isinstance(data, dict):
20
+ output_lines = []
21
+
22
+ title = data.get("title")
23
+ if title:
24
+ output_lines.append(f"🎵 音乐搜索: {title}")
25
+
26
+ singer = data.get("singer")
27
+ if singer:
28
+ output_lines.append(f"👤 歌手: {singer}")
29
+
30
+ music_url = data.get("music")
31
+ if music_url:
32
+ output_lines.append(f"🔗 链接: {music_url}")
33
+
34
+ cover = data.get("cover")
35
+ if cover:
36
+ output_lines.append(f"🖼️ 封面: {cover}")
37
+
38
+ if output_lines:
39
+ return "\n".join(output_lines)
40
+ else:
41
+ return "未找到相关音乐信息。"
42
+
43
+ return str(data)
44
+
45
+ except Exception as e:
46
+ logger.exception(f"音乐搜索失败: {e}")
47
+ return f"音乐搜索失败: {e}"
@@ -0,0 +1,22 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "music_info_get",
5
+ "description": "获取音乐详细信息 (通过 ID)。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "id": {
10
+ "type": "string",
11
+ "description": "歌曲 ID"
12
+ },
13
+ "type": {
14
+ "type": "string",
15
+ "description": "音乐平台 (wy, qq, kw, mg, qi)",
16
+ "enum": ["wy", "qq", "kw", "mg", "qi"]
17
+ }
18
+ },
19
+ "required": ["id", "type"]
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,35 @@
1
+ from typing import Any, Dict
2
+ import httpx
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
9
+ song_id = args.get("id")
10
+ platform = args.get("type")
11
+
12
+ url = "https://api.jkyai.top/API/yyjhss.php"
13
+
14
+ try:
15
+ async with httpx.AsyncClient(timeout=15.0) as client:
16
+ response = await client.get(url, params={"id": song_id, "type": platform})
17
+ response.raise_for_status()
18
+ data = response.json()
19
+
20
+ # 数据结构: code, msg, data{name, artist, url, ...}
21
+ if data.get("code") == 1:
22
+ info = data.get("data", {})
23
+ return (
24
+ f"🎵 歌曲信息: {info.get('name')}\n"
25
+ f"👤 歌手: {info.get('artist')}\n"
26
+ f"💿 专辑: {info.get('album')}\n"
27
+ f"🔗 链接: {info.get('url')}\n"
28
+ f"🖼️ 图片: {info.get('pic')}"
29
+ )
30
+ else:
31
+ return f"获取失败: {data.get('msg')}"
32
+
33
+ except Exception as e:
34
+ logger.exception(f"获取歌曲详情失败: {e}")
35
+ return f"获取歌曲详情失败: {e}"
@@ -0,0 +1,22 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "music_lyrics",
5
+ "description": "获取歌曲歌词。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "id": {
10
+ "type": "string",
11
+ "description": "歌曲 ID"
12
+ },
13
+ "msg": {
14
+ "type": "string",
15
+ "description": "音乐平台 (qq, wy, kw, qi)",
16
+ "enum": ["qq", "wy", "kw", "qi"]
17
+ }
18
+ },
19
+ "required": ["id", "msg"]
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,26 @@
1
+ from typing import Any, Dict
2
+ import httpx
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
9
+ song_id = args.get("id")
10
+ platform = args.get("msg")
11
+
12
+ url = "https://api.jkyai.top/API/jhlrcgc.php"
13
+
14
+ try:
15
+ async with httpx.AsyncClient(timeout=15.0) as client:
16
+ response = await client.get(
17
+ url, params={"id": song_id, "msg": platform, "type": "text"}
18
+ )
19
+ # API 文档说明 type 是可选的,默认为 text。
20
+ # 如果是 text,它可能直接返回歌词。
21
+
22
+ return f"🎵 歌词内容:\n{response.text}"
23
+
24
+ except Exception as e:
25
+ logger.exception(f"获取歌词失败: {e}")
26
+ return f"获取歌词失败: {e}"
@@ -0,0 +1,21 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "video_random_recommend",
5
+ "description": "获取随机视频推荐(返回视频链接)。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "target_id": {
10
+ "type": "integer",
11
+ "description": "目标 ID (用于日志记录)"
12
+ },
13
+ "message_type": {
14
+ "type": "string",
15
+ "description": "消息类型 (group 或 private)"
16
+ }
17
+ },
18
+ "required": []
19
+ }
20
+ }
21
+ }