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,141 @@
1
+ from typing import Any, Dict
2
+ import logging
3
+ import httpx
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ # 星座名称映射(中文 -> 英文)
8
+ CONSTELLATION_MAP = {
9
+ "白羊座": "aries",
10
+ "金牛座": "taurus",
11
+ "双子座": "gemini",
12
+ "巨蟹座": "cancer",
13
+ "狮子座": "leo",
14
+ "处女座": "virgo",
15
+ "天秤座": "libra",
16
+ "天蝎座": "scorpio",
17
+ "射手座": "sagittarius",
18
+ "摩羯座": "capricorn",
19
+ "水瓶座": "aquarius",
20
+ "双鱼座": "pisces",
21
+ }
22
+
23
+ # 时间类型映射(中文 -> 英文)
24
+ TIME_TYPE_MAP = {
25
+ "今日": "today",
26
+ "本周": "week",
27
+ "本月": "month",
28
+ "本年": "year",
29
+ }
30
+
31
+ # 星座星级显示
32
+ STAR_MAP = {1: "★", 2: "★★", 3: "★★★", 4: "★★★★", 5: "★★★★★"}
33
+
34
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
35
+ constellation = args.get("constellation")
36
+ time_type = args.get("time_type", "today")
37
+
38
+ if not constellation:
39
+ return "❌ 星座不能为空"
40
+
41
+ # 转换星座名称为英文
42
+ constellation_en = CONSTELLATION_MAP.get(constellation, constellation)
43
+ if constellation_en not in CONSTELLATION_MAP.values():
44
+ return f"❌ 不支持的星座: {constellation}\n支持的星座: {', '.join(CONSTELLATION_MAP.keys())}"
45
+
46
+ # 转换时间类型为英文
47
+ time_type_en = TIME_TYPE_MAP.get(time_type, time_type)
48
+ if time_type_en not in TIME_TYPE_MAP.values():
49
+ return f"❌ 不支持的时间类型: {time_type}\n支持的时间类型: {', '.join(TIME_TYPE_MAP.keys())}"
50
+
51
+ try:
52
+ async with httpx.AsyncClient(timeout=10.0) as client:
53
+ params = {
54
+ "type": constellation_en,
55
+ "time": time_type_en
56
+ }
57
+ logger.info(f"获取星座运势: {constellation} ({constellation_en}), 时间: {time_type} ({time_type_en})")
58
+
59
+ response = await client.get("https://v2.xxapi.cn/api/horoscope", params=params)
60
+ response.raise_for_status()
61
+ data = response.json()
62
+
63
+ if data.get("code") != 200:
64
+ return f"获取运势失败: {data.get('msg')}"
65
+
66
+ fortune_data = data.get("data", {})
67
+
68
+ # 格式化运势信息
69
+ title = fortune_data.get("title", constellation)
70
+ time_text = fortune_data.get("type", time_type)
71
+ short_comment = fortune_data.get("shortcomment", "")
72
+ date_text = fortune_data.get("time", "")
73
+
74
+ # 运势评分
75
+ fortune = fortune_data.get("fortune", {})
76
+ fortune_stars = {
77
+ "综合": STAR_MAP.get(fortune.get("all", 0), ""),
78
+ "健康": STAR_MAP.get(fortune.get("health", 0), ""),
79
+ "爱情": STAR_MAP.get(fortune.get("love", 0), ""),
80
+ "财运": STAR_MAP.get(fortune.get("money", 0), ""),
81
+ "工作": STAR_MAP.get(fortune.get("work", 0), ""),
82
+ }
83
+
84
+ # 运势指数
85
+ index = fortune_data.get("index", {})
86
+
87
+ # 运势文本
88
+ fortunetext = fortune_data.get("fortunetext", {})
89
+
90
+ # 幸运信息
91
+ lucky_color = fortune_data.get("luckycolor", "")
92
+ lucky_constellation = fortune_data.get("luckyconstellation", "")
93
+ lucky_number = fortune_data.get("luckynumber", "")
94
+
95
+ # 宜忌
96
+ todo = fortune_data.get("todo", {})
97
+ todo_yi = todo.get("ji", "")
98
+ todo_ji = todo.get("yi", "")
99
+
100
+ # 构建结果
101
+ result = f"【{title} {time_text}】{date_text}\n"
102
+ result += f"短评:{short_comment}\n\n"
103
+
104
+ result += "【运势评分】\n"
105
+ for name, stars in fortune_stars.items():
106
+ result += f"{name}:{stars}\n"
107
+ result += "\n"
108
+
109
+ result += "【运势指数】\n"
110
+ for name, value in index.items():
111
+ result += f"{name}:{value}\n"
112
+ result += "\n"
113
+
114
+ result += "【运势详情】\n"
115
+ for name, text in fortunetext.items():
116
+ result += f"{name}:{text}\n"
117
+ result += "\n"
118
+
119
+ result += "【幸运信息】\n"
120
+ result += f"幸运色:{lucky_color}\n"
121
+ result += f"幸运星座:{lucky_constellation}\n"
122
+ result += f"幸运数字:{lucky_number}\n"
123
+ result += "\n"
124
+
125
+ if todo_yi or todo_ji:
126
+ result += "【宜忌】\n"
127
+ if todo_yi:
128
+ result += f"宜:{todo_yi}\n"
129
+ if todo_ji:
130
+ result += f"忌:{todo_ji}\n"
131
+
132
+ return result
133
+
134
+ except httpx.TimeoutException:
135
+ return "获取运势超时,请稍后重试"
136
+ except httpx.HTTPStatusError as e:
137
+ logger.error(f"HTTP 错误: {e}")
138
+ return f"获取运势失败: {e}"
139
+ except Exception as e:
140
+ logger.exception(f"获取星座运势失败: {e}")
141
+ return f"获取运势失败: {e}"
@@ -0,0 +1,43 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "minecraft_skin",
5
+ "description": "获取 Minecraft 玩家皮肤/头像。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "正版 ID"
12
+ },
13
+ "type": {
14
+ "type": "string",
15
+ "description": "渲染部位 (头像, 头颅, 身体, 皮肤, 披风)",
16
+ "enum": ["头像", "头颅", "身体", "皮肤", "披风"]
17
+ },
18
+ "overlay": {
19
+ "type": "boolean",
20
+ "description": "是否渲染多层皮肤"
21
+ },
22
+ "size": {
23
+ "type": "integer",
24
+ "description": "头像大小 (1-512)"
25
+ },
26
+ "scale": {
27
+ "type": "integer",
28
+ "description": "体型大小 (1-10)"
29
+ },
30
+ "target_id": {
31
+ "type": "integer",
32
+ "description": "发送目标的 ID (群号或 QQ 号)"
33
+ },
34
+ "message_type": {
35
+ "type": "string",
36
+ "description": "消息类型 (group 或 private)",
37
+ "enum": ["group", "private"]
38
+ }
39
+ },
40
+ "required": ["name", "target_id", "message_type"]
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,55 @@
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
+ name = args.get("name")
12
+ render_type = args.get("type", "头像")
13
+ overlay = args.get("overlay", True)
14
+ size = args.get("size", 160)
15
+ scale = args.get("scale", 6)
16
+ target_id = args.get("target_id")
17
+ message_type = args.get("message_type")
18
+
19
+ url = "https://api.xingzhige.com/API/get_Minecraft_skins/"
20
+ params = {
21
+ "name": name,
22
+ "type": render_type,
23
+ "overlay": str(overlay).lower(),
24
+ "size": size,
25
+ "scale": scale,
26
+ }
27
+
28
+ try:
29
+ async with httpx.AsyncClient(timeout=30.0) as client:
30
+ response = await client.get(url, params=params)
31
+
32
+ # 检查内容类型
33
+ content_type = response.headers.get("content-type", "")
34
+
35
+ if "application/json" in content_type:
36
+ return f"获取失败: {response.text}"
37
+
38
+ # 假设是图片
39
+ filename = f"mc_skin_{uuid.uuid4().hex[:8]}.png"
40
+ filepath = Path.cwd() / "img" / filename
41
+ filepath.parent.mkdir(exist_ok=True)
42
+
43
+ with open(filepath, "wb") as f:
44
+ f.write(response.content)
45
+
46
+ send_image_callback = context.get("send_image_callback")
47
+ if send_image_callback:
48
+ await send_image_callback(target_id, message_type, str(filepath))
49
+ return f"Minecraft 皮肤/头像已发送给 {message_type} {target_id}"
50
+ else:
51
+ return "发送图片回调未设置,图片已保存但无法发送。"
52
+
53
+ except Exception as e:
54
+ logger.exception(f"Minecraft 皮肤获取失败: {e}")
55
+ return f"Minecraft 皮肤获取失败: {e}"
@@ -0,0 +1,25 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "novel_search",
5
+ "description": "小说搜索与阅读。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "小说名 (搜索用)"
12
+ },
13
+ "href": {
14
+ "type": "string",
15
+ "description": "章节链接/ID (阅读用)"
16
+ },
17
+ "num": {
18
+ "type": "string",
19
+ "description": "页码 (阅读用)"
20
+ }
21
+ },
22
+ "required": []
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,31 @@
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
+ name = args.get("name")
10
+ href = args.get("href")
11
+ num = args.get("num")
12
+
13
+ url = "https://api.jkyai.top/API/fqmfxs.php"
14
+ params = {}
15
+ if name:
16
+ params["name"] = name
17
+ if href:
18
+ params["href"] = href
19
+ if num:
20
+ params["num"] = num
21
+
22
+ try:
23
+ async with httpx.AsyncClient(timeout=15.0) as client:
24
+ response = await client.get(url, params=params)
25
+
26
+ # API 返回文本
27
+ return response.text
28
+
29
+ except Exception as e:
30
+ logger.exception(f"小说工具操作失败: {e}")
31
+ return f"小说工具操作失败: {e}"
@@ -0,0 +1,12 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "renjian",
5
+ "description": "随机返回“在人间凑数的日子”中的幽默句子,带给用户轻松幽默的日常感悟。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {},
9
+ "required": []
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,30 @@
1
+ from typing import Any, Dict
2
+ import logging
3
+ import httpx
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
8
+ try:
9
+ async with httpx.AsyncClient(timeout=10.0) as client:
10
+ logger.info("获取人间凑数语录")
11
+
12
+ response = await client.get("https://v2.xxapi.cn/api/renjian")
13
+ response.raise_for_status()
14
+ data = response.json()
15
+
16
+ if data.get("code") != 200:
17
+ return f"获取语录失败: {data.get('msg')}"
18
+
19
+ quote = data.get("data", "")
20
+
21
+ return f"【在人间凑数的日子】\n{quote}"
22
+
23
+ except httpx.TimeoutException:
24
+ return "请求超时,请稍后重试"
25
+ except httpx.HTTPStatusError as e:
26
+ logger.error(f"HTTP 错误: {e}")
27
+ return f"获取语录失败: {e}"
28
+ except Exception as e:
29
+ logger.exception(f"获取语录失败: {e}")
30
+ return f"获取语录失败: {e}"
@@ -0,0 +1,12 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "wenchang_dijun",
5
+ "description": "文昌帝君灵签抽签工具,随机抽取文昌帝君签文,适用于求签、运势查询和文化应用。返回签文、诗句、签号和签文图片。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {},
9
+ "required": []
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,44 @@
1
+ from typing import Any, Dict
2
+ import logging
3
+ import httpx
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
8
+ try:
9
+ async with httpx.AsyncClient(timeout=10.0) as client:
10
+ logger.info("抽取文昌帝君灵签")
11
+
12
+ response = await client.get("https://v2.xxapi.cn/api/wenchangdijunrandom")
13
+ response.raise_for_status()
14
+ data = response.json()
15
+
16
+ if data.get("code") != 200:
17
+ return f"抽签失败: {data.get('msg')}"
18
+
19
+ fortune_data = data.get("data", {})
20
+ title = fortune_data.get("title", "")
21
+ poem = fortune_data.get("poem", "")
22
+ content = fortune_data.get("content", "")
23
+ pic = fortune_data.get("pic", "")
24
+ fortune_id = fortune_data.get("id", "")
25
+
26
+ result = "【文昌帝君灵签】\n"
27
+ result += f"签号:{fortune_id}\n"
28
+ result += f"签名:{title}\n\n"
29
+ result += f"【签诗】\n{poem}\n\n"
30
+ result += f"【签文】\n{content}\n"
31
+
32
+ if pic:
33
+ result += f"\n签文图片:{pic}"
34
+
35
+ return result
36
+
37
+ except httpx.TimeoutException:
38
+ return "请求超时,请稍后重试"
39
+ except httpx.HTTPStatusError as e:
40
+ logger.error(f"HTTP 错误: {e}")
41
+ return f"抽签失败: {e}"
42
+ except Exception as e:
43
+ logger.exception(f"文昌帝君抽签失败: {e}")
44
+ return f"抽签失败: {e}"
@@ -0,0 +1 @@
1
+ # File Analysis Agent - 支持解析各种文件格式
@@ -0,0 +1,21 @@
1
+ {
2
+ "type": "function",
3
+ "function": {
4
+ "name": "file_analysis_agent",
5
+ "description": "文件分析助手,支持解析各种文件格式:文档(PDF、Word、PPT、Excel)、代码、压缩包、图片、音频、视频等。参数为 URL 或 file_id(QQ 内的文件 ID)。",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "file_source": {
10
+ "type": "string",
11
+ "description": "文件源,可以是 URL 或 QQ 的 file_id"
12
+ },
13
+ "prompt": {
14
+ "type": "string",
15
+ "description": "额外的分析需求,例如:'提取所有邮件地址'、'统计代码行数'、'解压并查看内容'"
16
+ }
17
+ },
18
+ "required": ["file_source"]
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,248 @@
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
+
26
+ 遍历 tools 目录,读取 config.json 和 handler.py,
27
+ 将合法的工具注册到内存中。
28
+ """
29
+ if not self.tools_dir.exists():
30
+ logger.warning(f"Agent 工具目录不存在: {self.tools_dir}")
31
+ return
32
+
33
+ for item in self.tools_dir.iterdir():
34
+ if item.is_dir() and not item.name.startswith("_"):
35
+ self._load_tool_from_dir(item)
36
+
37
+ logger.info(
38
+ f"Agent 加载了 {len(self._tools_schema)} 个工具: {list(self._tools_handlers.keys())}"
39
+ )
40
+
41
+ def _load_tool_from_dir(self, tool_dir: Path) -> None:
42
+ """从目录加载工具"""
43
+ config_path: Path = tool_dir / "config.json"
44
+ handler_path: Path = tool_dir / "handler.py"
45
+
46
+ if not config_path.exists() or not handler_path.exists():
47
+ return
48
+
49
+ try:
50
+ with open(config_path, "r", encoding="utf-8") as f:
51
+ config: dict[str, Any] = json.load(f)
52
+
53
+ if "function" not in config or "name" not in config.get("function", {}):
54
+ return
55
+
56
+ tool_name: str = config["function"]["name"]
57
+
58
+ spec = importlib.util.spec_from_file_location(
59
+ f"agent_tools.{tool_name}", handler_path
60
+ )
61
+ if spec is None or spec.loader is None:
62
+ return
63
+
64
+ module = importlib.util.module_from_spec(spec)
65
+ spec.loader.exec_module(module)
66
+
67
+ if not hasattr(module, "execute"):
68
+ return
69
+
70
+ self._tools_schema.append(config)
71
+ self._tools_handlers[tool_name] = module.execute
72
+
73
+ except Exception as e:
74
+ logger.error(f"从 {tool_dir} 加载工具失败: {e}")
75
+
76
+ def get_tools_schema(self) -> list[dict[str, Any]]:
77
+ """获取工具 schema
78
+
79
+ 返回:
80
+ OpenAI function calling 格式的工具定义列表
81
+ """
82
+ return self._tools_schema
83
+
84
+ async def execute_tool(
85
+ self, tool_name: str, args: dict[str, Any], context: dict[str, Any]
86
+ ) -> str:
87
+ """执行工具
88
+
89
+ 参数:
90
+ tool_name: 工具名称
91
+ args: 工具参数
92
+ context: 执行上下文
93
+
94
+ 返回:
95
+ 工具执行结果字符串
96
+ """
97
+ handler = self._tools_handlers.get(tool_name)
98
+ if not handler:
99
+ return f"未找到工具: {tool_name}"
100
+
101
+ try:
102
+ if asyncio.iscoroutinefunction(handler):
103
+ result = await handler(args, context)
104
+ else:
105
+ result = handler(args, context)
106
+ return str(result)
107
+ except Exception as e:
108
+ logger.exception(f"执行工具 {tool_name} 时出错")
109
+ return f"执行工具 {tool_name} 时出错: {str(e)}"
110
+
111
+
112
+ async def _load_prompt() -> str:
113
+ """从 prompt.md 文件加载系统提示词"""
114
+ prompt_path: Path = Path(__file__).parent / "prompt.md"
115
+ if prompt_path.exists():
116
+ async with aiofiles.open(prompt_path, "r", encoding="utf-8") as f:
117
+ return await f.read()
118
+ return _get_default_prompt()
119
+
120
+
121
+ def _get_default_prompt() -> str:
122
+ """默认提示词"""
123
+ return "你是一个专业的文件分析助手..."
124
+
125
+
126
+ async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
127
+ """执行 file_analysis_agent"""
128
+ file_source: str = args.get("file_source", "")
129
+ user_prompt: str = args.get("prompt", "")
130
+
131
+ if not file_source:
132
+ return "请提供文件 URL 或 file_id"
133
+
134
+ agent_tools_dir: Path = Path(__file__).parent / "tools"
135
+ tool_registry = AgentToolRegistry(agent_tools_dir)
136
+
137
+ tools: list[dict[str, Any]] = tool_registry.get_tools_schema()
138
+
139
+ ai_client = context.get("ai_client")
140
+ if not ai_client:
141
+ return "AI client 未在上下文中提供"
142
+
143
+ agent_config = ai_client.agent_config
144
+
145
+ system_prompt: str = await _load_prompt()
146
+
147
+ if user_prompt:
148
+ user_content = f"文件源:{file_source}\n\n用户需求:{user_prompt}"
149
+ else:
150
+ user_content = f"请分析这个文件:{file_source}"
151
+
152
+ messages: list[dict[str, Any]] = [
153
+ {"role": "system", "content": system_prompt},
154
+ {"role": "user", "content": user_content},
155
+ ]
156
+
157
+ max_iterations: int = 30
158
+ iteration: int = 0
159
+
160
+ while iteration < max_iterations:
161
+ iteration += 1
162
+
163
+ try:
164
+ # 1. 调用 AI 模型获取决策 (Action)
165
+ # 模型根据当前的 message history (包含用户需求、之前的 Action 和 Observation)
166
+ # 决定是调用工具 (Action) 还是输出最终回复 (Final Answer)
167
+ response = await ai_client._http_client.post(
168
+ agent_config.api_url,
169
+ headers={
170
+ "Authorization": f"Bearer {agent_config.api_key}",
171
+ "Content-Type": "application/json",
172
+ },
173
+ json=ai_client._build_request_body(
174
+ model_config=agent_config,
175
+ messages=messages,
176
+ max_tokens=agent_config.max_tokens,
177
+ tools=tools if tools else None,
178
+ tool_choice="auto",
179
+ ),
180
+ )
181
+ response.raise_for_status()
182
+ result: dict[str, Any] = response.json()
183
+
184
+ choice: dict[str, Any] = result.get("choices", [{}])[0]
185
+ message: dict[str, Any] = choice.get("message", {})
186
+ content: str = message.get("content") or ""
187
+ tool_calls: list[dict[str, Any]] = message.get("tool_calls", [])
188
+
189
+ # 兼容性处理:如果 content 不为空但有 tool_calls,清空 content 以避免模型自言自语
190
+ if content.strip() and tool_calls:
191
+ content = ""
192
+
193
+ # 2. 如果模型没有调用工具,说明任务已完成或需要进一步交互
194
+ if not tool_calls:
195
+ return content
196
+
197
+ # 将模型的决策添加到历史记录
198
+ messages.append(
199
+ {"role": "assistant", "content": content, "tool_calls": tool_calls}
200
+ )
201
+
202
+ # 3. 执行模型选择的工具 (Observation)
203
+ tool_tasks = []
204
+ tool_call_ids = []
205
+
206
+ for tool_call in tool_calls:
207
+ call_id: str = tool_call.get("id", "")
208
+ function: dict[str, Any] = tool_call.get("function", {})
209
+ function_name: str = function.get("name", "")
210
+ function_args_str: str = function.get("arguments", "{}")
211
+
212
+ logger.info(f"Agent 正在准备工具: {function_name}")
213
+
214
+ try:
215
+ function_args: dict[str, Any] = json.loads(function_args_str)
216
+ except json.JSONDecodeError:
217
+ function_args = {}
218
+
219
+ tool_call_ids.append(call_id)
220
+ tool_tasks.append(
221
+ tool_registry.execute_tool(function_name, function_args, context)
222
+ )
223
+
224
+ if tool_tasks:
225
+ logger.info(f"Agent 正在并发执行 {len(tool_tasks)} 个工具")
226
+ results = await asyncio.gather(*tool_tasks, return_exceptions=True)
227
+
228
+ for i, tool_result in enumerate(results):
229
+ call_id = tool_call_ids[i]
230
+ content_str: str = ""
231
+ if isinstance(tool_result, Exception):
232
+ content_str = f"错误: {str(tool_result)}"
233
+ else:
234
+ content_str = str(tool_result)
235
+
236
+ messages.append(
237
+ {
238
+ "role": "tool",
239
+ "tool_call_id": call_id,
240
+ "content": content_str,
241
+ }
242
+ )
243
+
244
+ except Exception as e:
245
+ logger.exception(f"Agent 执行失败: {e}")
246
+ return f"处理失败: {e}"
247
+
248
+ return "达到最大迭代次数"