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,116 @@
1
+ """
2
+ Agent Registry - Agent 自动发现和注册系统
3
+ """
4
+
5
+ import json
6
+ import logging
7
+ from pathlib import Path
8
+ from typing import Any, Dict, List
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class AgentRegistry:
14
+ """Agent 注册表,自动发现和加载 agents"""
15
+
16
+ def __init__(self, agents_dir: str | Path | None = None):
17
+ if agents_dir is None:
18
+ self.agents_dir = Path(__file__).parent
19
+ else:
20
+ self.agents_dir = Path(agents_dir)
21
+
22
+ self._agents_schema: List[Dict[str, Any]] = []
23
+ self._agents_handlers: Dict[str, Any] = {}
24
+ self.load_agents()
25
+
26
+ def load_agents(self) -> None:
27
+ """自动发现和加载 agents"""
28
+ self._agents_schema = []
29
+ self._agents_handlers = {}
30
+
31
+ if not self.agents_dir.exists():
32
+ logger.warning(f"Agent 目录不存在: {self.agents_dir}")
33
+ return
34
+
35
+ for item in self.agents_dir.iterdir():
36
+ if item.is_dir() and not item.name.startswith("_"):
37
+ self._load_agent_from_dir(item)
38
+
39
+ agent_names = list(self._agents_handlers.keys())
40
+ logger.info(
41
+ f"成功加载了 {len(self._agents_schema)} 个 Agent: {', '.join(agent_names)}"
42
+ )
43
+
44
+ def _load_agent_from_dir(self, agent_dir: Path) -> None:
45
+ """从目录加载单个 agent"""
46
+ config_path = agent_dir / "config.json"
47
+ handler_path = agent_dir / "handler.py"
48
+
49
+ if not config_path.exists() or not handler_path.exists():
50
+ logger.debug(
51
+ f"[Agent加载] 目录 {agent_dir} 缺少 config.json 或 handler.py,跳过"
52
+ )
53
+ return
54
+
55
+ import importlib.util
56
+
57
+ try:
58
+ with open(config_path, "r", encoding="utf-8") as f:
59
+ config = json.load(f)
60
+
61
+ if "function" not in config or "name" not in config.get("function", {}):
62
+ logger.error(
63
+ f"[Agent错误] Agent 配置无效 {agent_dir}: 缺少 function.name"
64
+ )
65
+ return
66
+
67
+ agent_name = config["function"]["name"]
68
+ logger.debug(f"[Agent加载] 正在从 {agent_dir} 加载 Agent: {agent_name}")
69
+
70
+ spec = importlib.util.spec_from_file_location(
71
+ f"agents.{agent_name}", handler_path
72
+ )
73
+ if spec is None or spec.loader is None:
74
+ logger.error(f"从 {handler_path} 加载 Agent 处理器 spec 失败")
75
+ return
76
+
77
+ module = importlib.util.module_from_spec(spec)
78
+ spec.loader.exec_module(module)
79
+
80
+ if not hasattr(module, "execute"):
81
+ logger.error(f"Agent {agent_dir} 的处理器缺少 'execute' 函数")
82
+ return
83
+
84
+ self._agents_schema.append(config)
85
+ self._agents_handlers[agent_name] = module.execute
86
+
87
+ logger.debug(f"已加载 Agent: {agent_name}")
88
+
89
+ except Exception as e:
90
+ logger.error(f"从 {agent_dir} 加载 Agent 失败: {e}")
91
+
92
+ def get_agents_schema(self) -> List[Dict[str, Any]]:
93
+ """获取所有 agent 的 schema 定义(用于 OpenAI function calling)"""
94
+ return self._agents_schema
95
+
96
+ async def execute_agent(
97
+ self, agent_name: str, args: Dict[str, Any], context: Dict[str, Any]
98
+ ) -> str:
99
+ """执行 agent"""
100
+ handler = self._agents_handlers.get(agent_name)
101
+ if not handler:
102
+ return f"未找到 Agent: {agent_name}"
103
+
104
+ try:
105
+ import asyncio
106
+
107
+ start_time = asyncio.get_event_loop().time()
108
+ if hasattr(handler, "__call__"):
109
+ result = await handler(args, context)
110
+ duration = asyncio.get_event_loop().time() - start_time
111
+ logger.info(f"[Agent执行] {agent_name} 执行成功, 耗时={duration:.4f}s")
112
+ return str(result)
113
+ return f"Agent 处理器无效: {agent_name}"
114
+ except Exception as e:
115
+ logger.exception(f"[Agent异常] 执行 Agent {agent_name} 时出错")
116
+ return f"执行 Agent {agent_name} 时出错: {str(e)}"
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "entertainment_agent",
5
+ "description": "娱乐助手,提供 AI 绘画、学习答疑、星座运势、Minecraft 皮肤、小说阅读等娱乐功能。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "prompt": {
10
+ "type": "string",
11
+ "description": "用户的娱乐需求,例如:'画一只可爱的猫咪'、'白羊座今日运势'、'搜索斗破苍穹'"
12
+ }
13
+ },
14
+ "required": ["prompt"]
15
+ }
16
+ }
17
+ }
@@ -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
+ """执行 entertainment_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,25 @@
1
+ # 娱乐助手
2
+
3
+ ## 能力
4
+ - **AI 绘画**:根据描述生成图片
5
+ - **AI 学习助手**:解答学习问题,支持深度思考模式
6
+ - **星座运势**:查询十二星座的今日运势
7
+ - **文昌帝君**:调用文昌帝君工具查询升学运势
8
+ - **Minecraft 皮肤**:生成 Minecraft 玩家皮肤图片
9
+ - **小说搜索与阅读**:搜索网络小说并阅读章节内容
10
+ - **人间小句**:提供“在人间凑数的日子”中的幽默句子,带给用户轻松幽默的日常感悟
11
+
12
+ ## 适用场景
13
+ - 用户想要生成图片时
14
+ - 用户需要解答题目或学习辅导时
15
+ - 用户查询星座运势时
16
+ - 用户需要 Minecraft 皮肤时
17
+ - 用户想看小说时
18
+ - 用户查询人间评分时
19
+
20
+ ## 参数说明
21
+ - `prompt` (AI 绘画): 图片描述词,越详细越好
22
+ - `question` (学习助手): 具体的学习问题
23
+ - `astrology_name` (星座): 星座名称(如:白羊座)
24
+ - `username` (Minecraft): 玩家名称
25
+ - `novel_name` (小说): 小说名称
@@ -0,0 +1,20 @@
1
+ 你是一个娱乐助手,专门帮助用户获取各种娱乐内容和功能。
2
+
3
+ 你的任务是根据用户需求,选择合适的工具来完成任务:
4
+
5
+ 1. **AI 绘图** → ai_draw_one
6
+ 2. **学习答疑** → ai_study_helper
7
+ 3. **星座运势** → horoscope
8
+ 4. **Minecraft 皮肤** → minecraft_skin
9
+ 5. **小说阅读** → novel_search
10
+ 6. **人间小句** → renjian
11
+ 7. **文昌帝君** → wenchang_dijun
12
+
13
+ 注意事项:
14
+ - 对于 AI 生成的内容,可以适当调整参数获得更好效果
15
+ - 小说阅读支持分页
16
+ - 保持回答轻松友好的风格
17
+
18
+ 如果用户需求不明确,请先询问用户澄清问题。
19
+
20
+ 如果问题涉及时间,立刻调用时间工具获取。
@@ -0,0 +1 @@
1
+ # Entertainment Agent Tools
@@ -0,0 +1,34 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "ai_draw_one",
5
+ "description": "AI 绘图工具 (DrawOne)。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "prompt": {
10
+ "type": "string",
11
+ "description": "绘图提示词"
12
+ },
13
+ "model": {
14
+ "type": "string",
15
+ "description": "绘图模型 (例如: anylora, anything-v5, etc. 可选)"
16
+ },
17
+ "size": {
18
+ "type": "string",
19
+ "description": "比例 (例如 2:3)"
20
+ },
21
+ "target_id": {
22
+ "type": "integer",
23
+ "description": "发送目标的 ID"
24
+ },
25
+ "message_type": {
26
+ "type": "string",
27
+ "description": "消息类型 (group 或 private)",
28
+ "enum": ["group", "private"]
29
+ }
30
+ },
31
+ "required": ["prompt", "target_id", "message_type"]
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,62 @@
1
+ from typing import Any, Dict
2
+ import httpx
3
+ import logging
4
+ from pathlib import Path
5
+ import uuid
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
11
+ prompt = args.get("prompt")
12
+ model = args.get("model", "anything-v5") # 默认模型猜测
13
+ size = args.get("size", "1:1")
14
+ target_id = args.get("target_id")
15
+ message_type = args.get("message_type")
16
+
17
+ url = "https://api.xingzhige.com/API/DrawOne/"
18
+ params = {"prompt": prompt, "model": model, "size": size}
19
+
20
+ try:
21
+ async with httpx.AsyncClient(timeout=60.0) as client: # AI 绘画可能需要一些时间
22
+ response = await client.get(url, params=params)
23
+
24
+ try:
25
+ data = response.json()
26
+ except Exception:
27
+ return f"API 返回错误 (非JSON): {response.text[:100]}"
28
+
29
+ # 解析响应
30
+ # 文档说 "返回: Json"。它可能包含 "url" 或 "image" 字段。
31
+ # 我将假设是 'url' 或类似字段。
32
+ # 如果找不到 URL,我将返回 JSON 给用户以进行调试。
33
+
34
+ image_url = data.get("url") or data.get("image") or data.get("img")
35
+
36
+ if not image_url and "data" in data and isinstance(data["data"], str):
37
+ image_url = data["data"]
38
+
39
+ if not image_url:
40
+ return f"未找到图片链接: {data}"
41
+
42
+ # 下载图片
43
+ img_response = await client.get(image_url)
44
+ img_response.raise_for_status()
45
+
46
+ filename = f"ai_draw_{uuid.uuid4().hex[:8]}.jpg"
47
+ filepath = Path.cwd() / "img" / filename
48
+ filepath.parent.mkdir(exist_ok=True)
49
+
50
+ with open(filepath, "wb") as f:
51
+ f.write(img_response.content)
52
+
53
+ send_image_callback = context.get("send_image_callback")
54
+ if send_image_callback:
55
+ await send_image_callback(target_id, message_type, str(filepath))
56
+ return f"AI 绘图已发送给 {message_type} {target_id}"
57
+ else:
58
+ return "发送图片回调未设置"
59
+
60
+ except Exception as e:
61
+ logger.exception(f"AI 绘图失败: {e}")
62
+ return f"AI 绘图失败: {e}"
@@ -0,0 +1,22 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "ai_study_helper",
5
+ "description": "AI 学习助手/解题工具。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "question": {
10
+ "type": "string",
11
+ "description": "问题内容"
12
+ },
13
+ "content": {
14
+ "type": "string",
15
+ "description": "是否开启深度思考 (yes/no)",
16
+ "enum": ["yes", "no"]
17
+ }
18
+ },
19
+ "required": ["question"]
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
+ question = args.get("question")
10
+ content = args.get("content", "yes")
11
+
12
+ url = "https://api.jkyai.top/API/wnjtzs.php"
13
+
14
+ try:
15
+ async with httpx.AsyncClient(timeout=60.0) as client:
16
+ response = await client.get(
17
+ url, params={"question": question, "content": content, "type": "json"}
18
+ )
19
+ response.raise_for_status()
20
+ data = response.json()
21
+
22
+ # 格式化
23
+ status = data.get("status")
24
+ if status != "success":
25
+ return f"AI 响应失败: {status}"
26
+
27
+ q = data.get("question", "")
28
+ ans = data.get("answer", "")
29
+ model = data.get("model", "")
30
+
31
+ return f"🤖 AI 解答 ({model}):\n❓ 问题: {q}\n💡 答案: {ans}"
32
+
33
+ except Exception as e:
34
+ logger.exception(f"AI 助手请求失败: {e}")
35
+ return f"AI 助手请求失败: {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,24 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "horoscope",
5
+ "description": "获取指定星座的运势信息,支持今日、本周、本月和本年的运势查询。返回综合运势、健康、爱情、财运、工作等详细运势信息,包括运势评分、运势描述、幸运色、幸运数字等。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "constellation": {
10
+ "type": "string",
11
+ "description": "星座名称(中文或英文)",
12
+ "enum": ["白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座", "水瓶座", "双鱼座", "aries", "taurus", "gemini", "cancer", "leo", "virgo", "libra", "scorpio", "sagittarius", "capricorn", "aquarius", "pisces"]
13
+ },
14
+ "time_type": {
15
+ "type": "string",
16
+ "description": "运势时间类型",
17
+ "enum": ["today", "week", "month", "year", "今日", "本周", "本月", "本年"],
18
+ "default": "today"
19
+ }
20
+ },
21
+ "required": ["constellation"]
22
+ }
23
+ }
24
+ }