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,218 @@
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
+ """执行 scheduler_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
+ tool_tasks = []
174
+ tool_call_ids = []
175
+
176
+ for tool_call in tool_calls:
177
+ call_id: str = tool_call.get("id", "")
178
+ function: dict[str, Any] = tool_call.get("function", {})
179
+ function_name: str = function.get("name", "")
180
+ function_args_str: str = function.get("arguments", "{}")
181
+
182
+ logger.info(f"Agent 正在准备工具: {function_name}")
183
+
184
+ try:
185
+ function_args: dict[str, Any] = json.loads(function_args_str)
186
+ except json.JSONDecodeError:
187
+ function_args = {}
188
+
189
+ tool_call_ids.append(call_id)
190
+ tool_tasks.append(
191
+ tool_registry.execute_tool(function_name, function_args, context)
192
+ )
193
+
194
+ if tool_tasks:
195
+ logger.info(f"Agent 正在并发执行 {len(tool_tasks)} 个工具")
196
+ results = await asyncio.gather(*tool_tasks, return_exceptions=True)
197
+
198
+ for i, tool_result in enumerate(results):
199
+ call_id = tool_call_ids[i]
200
+ content_str: str = ""
201
+ if isinstance(tool_result, Exception):
202
+ content_str = f"错误: {str(tool_result)}"
203
+ else:
204
+ content_str = str(tool_result)
205
+
206
+ messages.append(
207
+ {
208
+ "role": "tool",
209
+ "tool_call_id": call_id,
210
+ "content": content_str,
211
+ }
212
+ )
213
+
214
+ except Exception as e:
215
+ logger.exception(f"Agent 执行失败: {e}")
216
+ return f"处理失败: {e}"
217
+
218
+ return "达到最大迭代次数"
@@ -0,0 +1,17 @@
1
+ # 定时任务助手
2
+
3
+ ## 能力
4
+ - **创建任务**:使用 Crontab 表达式创建定时任务
5
+ - **管理任务**:删除或修改现有的定时任务
6
+ - **查看任务**:列出当前所有活跃的定时任务
7
+
8
+ ## 适用场景
9
+ - 当用户需要定期执行某项操作时
10
+ - 当用户询问“每天早上8点提醒我...”或类似请求时
11
+ - 管理已有的定时任务
12
+
13
+ ## 参数说明
14
+ - `cron_expression`: Crontab 时间表达式(如 `0 8 * * *` 表示每天早上8点)
15
+ - `task_content`: 任务的具体内容描述
16
+ - `task_id`: 任务的唯一标识符
17
+ - `max_executions`: 最大执行次数(可选,默认无限)
@@ -0,0 +1,67 @@
1
+ 你是一个定时任务管理助手,专门帮助用户创建、管理定时任务。
2
+
3
+ ## 你可以做的
4
+
5
+ 1. **创建定时任务** → create_schedule_task
6
+ 2. **删除定时任务** → delete_schedule_task
7
+ 3. **修改定时任务** → update_schedule_task
8
+ 4. **查看所有任务** → list_schedule_tasks
9
+
10
+ ## crontab 表达式说明
11
+
12
+ crontab 格式:分 时 日 月 周
13
+
14
+ | 字段 | 含义 | 范围 |
15
+ |------|------|------|
16
+ | 第1个 | 分钟 | 0-59 |
17
+ | 第2个 | 小时 | 0-23 |
18
+ | 第3个 | 日期 | 1-31 |
19
+ | 第4个 | 月份 | 1-12 |
20
+ | 第5个 | 星期 | 0-6 (0=周日) |
21
+
22
+ ### 常用示例
23
+
24
+ - `* * * * *` - 每分钟执行
25
+ - `30 * * * *` - 每小时30分执行
26
+ - `0 8 * * *` - 每天早上8点执行
27
+ - `0 8 * * 1` - 每周一早上8点执行
28
+ - `0 8 1 * *` - 每月1号早上8点执行
29
+ - `*/5 * * * *` - 每5分钟执行
30
+ - `30 8 * * 1-5` - 工作日早上8点30分执行
31
+
32
+ ### 特殊字符
33
+
34
+ - `*` - 任意值
35
+ - `,` - 多个值(如 `1,3,5`)
36
+ - `-` - 范围(如 `1-5`)
37
+ - `/` - 间隔(如 `*/15` 表示每15分钟)
38
+
39
+ ## 执行次数限制
40
+
41
+ 使用 `max_executions` 参数可以限制任务执行次数:
42
+
43
+ - 不设置 → 无限执行
44
+ - `1` → 执行一次后自动删除
45
+ - `N` → 执行 N 次后自动删除
46
+
47
+ ## 任务名称
48
+
49
+ 建议给任务起一个有意义的名称,方便识别和管理。
50
+
51
+ ## 使用流程
52
+
53
+ 1. 用户提出需求
54
+ 2. 你选择合适的工具
55
+ 3. 用户可以查看当前任务列表
56
+ 4. 用户可以删除或修改任务
57
+
58
+ ## 注意事项
59
+
60
+ - 任务创建后会自动开始计时
61
+ - 修改任务不会重置执行计数
62
+ - 删除任务会立即停止执行
63
+ - 保持回答简洁明了
64
+
65
+ 如果用户需求不明确,请先询问用户澄清问题。
66
+
67
+ 如果问题涉及时间,立刻调用时间工具获取。
@@ -0,0 +1 @@
1
+ # Scheduler Agent Tools
@@ -0,0 +1,37 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "create_schedule_task",
5
+ "description": "创建一个定时执行的任务。支持 crontab 语法。可以指定要调用的工具及其参数、执行次数限制。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "task_name": {
10
+ "type": "string",
11
+ "description": "任务名称(用于标识,建议使用有意义的名称)"
12
+ },
13
+ "cron_expression": {
14
+ "type": "string",
15
+ "description": "crontab 表达式 (分 时 日 月 周)。例如 '* * * * *' 表示每分钟执行,'30 8 * * *' 表示每天 8:30 执行。"
16
+ },
17
+ "tool_name": {
18
+ "type": "string",
19
+ "description": "要定时调用的工具名称,例如 'get_current_time', 'send_message' 等。"
20
+ },
21
+ "tool_args": {
22
+ "type": "object",
23
+ "description": "调用工具时传递的参数对象 (JSON)。"
24
+ },
25
+ "max_executions": {
26
+ "type": "integer",
27
+ "description": "最大执行次数(可选)。设置为 1 表示执行一次后自动删除,设置为 N 表示执行 N 次后自动删除,不设置则无限执行。"
28
+ }
29
+ },
30
+ "required": [
31
+ "cron_expression",
32
+ "tool_name",
33
+ "tool_args"
34
+ ]
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,68 @@
1
+ from typing import Any, Dict
2
+ import uuid
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
+ """
10
+ 执行 create_schedule_task 工具
11
+ 创建一个定时执行的任务
12
+ """
13
+ task_name = args.get("task_name")
14
+ cron_expression = args.get("cron_expression")
15
+ tool_name = args.get("tool_name")
16
+ tool_args = args.get("tool_args", {})
17
+ max_executions = args.get("max_executions")
18
+
19
+ if max_executions is not None:
20
+ try:
21
+ max_executions = int(max_executions)
22
+ if max_executions < 1:
23
+ return "max_executions 必须大于 0"
24
+ except (ValueError, TypeError):
25
+ return "max_executions 必须是有效的整数"
26
+
27
+ task_id = f"task_{uuid.uuid4().hex[:8]}"
28
+ if task_name:
29
+ task_id = f"task_{task_name.lower().replace(' ', '_')}_{uuid.uuid4().hex[:4]}"
30
+
31
+ target_type = None
32
+ target_id = None
33
+
34
+ scheduler = context.get("scheduler")
35
+ if not scheduler:
36
+ return "调度器未在上下文中提供"
37
+
38
+ ai_client = context.get("ai_client")
39
+ if target_id is None and ai_client:
40
+ if ai_client.current_group_id:
41
+ target_id = ai_client.current_group_id
42
+ if not target_type:
43
+ target_type = "group"
44
+ elif ai_client.current_user_id:
45
+ target_id = ai_client.current_user_id
46
+ if not target_type:
47
+ target_type = "private"
48
+
49
+ if not target_type:
50
+ target_type = "group"
51
+
52
+ success = scheduler.add_task(
53
+ task_id=task_id,
54
+ tool_name=tool_name,
55
+ tool_args=tool_args,
56
+ cron_expression=cron_expression,
57
+ target_id=target_id,
58
+ target_type=target_type,
59
+ task_name=task_name,
60
+ max_executions=max_executions,
61
+ )
62
+
63
+ if success:
64
+ name_info = f" '{task_name}'" if task_name else ""
65
+ max_info = f",最多执行 {max_executions} 次" if max_executions else ""
66
+ return f"定时任务{name_info}已成功添加 (ID: {task_id})。\n将在 '{cron_expression}' 时间执行工具 '{tool_name}'{max_info}。"
67
+ else:
68
+ return "添加定时任务失败。请检查 crontab 表达式是否正确。"
@@ -0,0 +1,19 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "delete_schedule_task",
5
+ "description": "删除指定的定时任务。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "task_id": {
10
+ "type": "string",
11
+ "description": "要删除的任务 ID。可通过 list_schedule_tasks 查看所有任务及其 ID。"
12
+ }
13
+ },
14
+ "required": [
15
+ "task_id"
16
+ ]
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,26 @@
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
+ """
9
+ 执行 delete_schedule_task 工具
10
+ 删除指定的定时任务
11
+ """
12
+ task_id = args.get("task_id")
13
+
14
+ if not task_id:
15
+ "请提供要删除的任务 ID"
16
+
17
+ scheduler = context.get("scheduler")
18
+ if not scheduler:
19
+ return "调度器未在上下文中提供"
20
+
21
+ success = scheduler.remove_task(task_id)
22
+
23
+ if success:
24
+ return f"定时任务 '{task_id}' 已成功删除。"
25
+ else:
26
+ 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,11 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "list_schedule_tasks",
5
+ "description": "列出所有已创建的定时任务,包括任务 ID、名称、工具、表达式、执行次数等信息。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {}
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,47 @@
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
+ """
9
+ 执行 list_schedule_tasks 工具
10
+ 列出所有定时任务
11
+ """
12
+ scheduler = context.get("scheduler")
13
+ if not scheduler:
14
+ return "调度器未在上下文中提供"
15
+
16
+ tasks = scheduler.list_tasks()
17
+
18
+ if not tasks:
19
+ return "当前没有定时任务"
20
+
21
+ lines = ["定时任务列表:\n"]
22
+ for task_id, info in tasks.items():
23
+ task_name = info.get("task_name", "")
24
+ tool_name = info.get("tool_name", "")
25
+ cron = info.get("cron", "")
26
+ tool_args = info.get("tool_args", {})
27
+ max_exec = info.get("max_executions")
28
+ current_exec = info.get("current_executions", 0)
29
+
30
+ exec_info = ""
31
+ if max_exec is not None:
32
+ exec_info = f" ({current_exec}/{max_exec})"
33
+ else:
34
+ exec_info = f" ({current_exec}次)"
35
+
36
+ name_display = f"【{task_name}】" if task_name else ""
37
+ args_str = str(tool_args) if tool_args else "{}"
38
+
39
+ lines.append(f"- ID: {task_id}")
40
+ lines.append(f" 名称: {name_display}")
41
+ lines.append(f" 工具: {tool_name}")
42
+ lines.append(f" 表达式: {cron}")
43
+ lines.append(f" 参数: {args_str}")
44
+ lines.append(f" 已执行: {exec_info}")
45
+ lines.append("")
46
+
47
+ return "\n".join(lines)
@@ -0,0 +1,39 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "update_schedule_task",
5
+ "description": "修改已存在的定时任务。可修改 crontab 表达式、工具名称、工具参数、任务名称、最大执行次数。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "task_id": {
10
+ "type": "string",
11
+ "description": "要修改的任务 ID。可通过 list_schedule_tasks 查看所有任务及其 ID。"
12
+ },
13
+ "cron_expression": {
14
+ "type": "string",
15
+ "description": "新的 crontab 表达式 (分 时 日 月 周)。"
16
+ },
17
+ "tool_name": {
18
+ "type": "string",
19
+ "description": "新的工具名称。"
20
+ },
21
+ "tool_args": {
22
+ "type": "object",
23
+ "description": "新的工具参数 (JSON)。"
24
+ },
25
+ "task_name": {
26
+ "type": "string",
27
+ "description": "新的任务名称。"
28
+ },
29
+ "max_executions": {
30
+ "type": "integer",
31
+ "description": "新的最大执行次数(可选)。设置为 1 表示执行一次后自动删除,设置为 N 表示执行 N 次后自动删除,不设置则保持原值。"
32
+ }
33
+ },
34
+ "required": [
35
+ "task_id"
36
+ ]
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,46 @@
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
+ """
9
+ 执行 update_schedule_task 工具
10
+ 修改已存在的定时任务
11
+ """
12
+ task_id = args.get("task_id")
13
+ cron_expression = args.get("cron_expression")
14
+ tool_name = args.get("tool_name")
15
+ tool_args = args.get("tool_args")
16
+ task_name = args.get("task_name")
17
+ max_executions = args.get("max_executions")
18
+
19
+ if not task_id:
20
+ return "请提供要修改的任务 ID"
21
+
22
+ if max_executions is not None:
23
+ try:
24
+ max_executions = int(max_executions)
25
+ if max_executions < 1:
26
+ return "max_executions 必须大于 0"
27
+ except (ValueError, TypeError):
28
+ return "max_executions 必须是有效的整数"
29
+
30
+ scheduler = context.get("scheduler")
31
+ if not scheduler:
32
+ return "调度器未在上下文中提供"
33
+
34
+ success = scheduler.update_task(
35
+ task_id=task_id,
36
+ cron_expression=cron_expression,
37
+ tool_name=tool_name,
38
+ tool_args=tool_args,
39
+ task_name=task_name,
40
+ max_executions=max_executions,
41
+ )
42
+
43
+ if success:
44
+ return f"定时任务 '{task_id}' 已成功修改。"
45
+ else:
46
+ return "修改定时任务失败。可能任务不存在。"
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "social_agent",
5
+ "description": "社交媒体助手,提供 Bilibili、音乐等社交媒体内容的搜索和查询功能。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "prompt": {
10
+ "type": "string",
11
+ "description": "用户的搜索需求,例如:'搜索 Python 教学视频'、'找周杰伦的稻香歌词'"
12
+ }
13
+ },
14
+ "required": ["prompt"]
15
+ }
16
+ }
17
+ }