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,131 @@
1
+ """注入攻击回复生成器
2
+
3
+ 用于根据 undefined 人设生成简短的嘲讽性回复
4
+ """
5
+
6
+ import logging
7
+ import httpx
8
+ from typing import Any
9
+ from pathlib import Path
10
+
11
+ from .config import SecurityModelConfig
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ # 加载系统提示词
16
+ PROMPT_PATH = Path("res/prompts/injection_response_agent.txt")
17
+ try:
18
+ INJECTION_RESPONSE_SYSTEM_PROMPT = PROMPT_PATH.read_text(encoding="utf-8")
19
+ except Exception as e:
20
+ logger.error(f"加载注入回复提示词失败: {e}")
21
+ INJECTION_RESPONSE_SYSTEM_PROMPT = "你是一个充满敌意的、说话带刺的 AI 助手。"
22
+
23
+
24
+ class InjectionResponseAgent:
25
+ """注入攻击回复生成器"""
26
+
27
+ def __init__(self, security_config: SecurityModelConfig) -> None:
28
+ """初始化回复生成器
29
+
30
+ 参数:
31
+ security_config: 安全模型配置
32
+ """
33
+ self.security_config = security_config
34
+ self._http_client = httpx.AsyncClient(timeout=120.0)
35
+
36
+ async def generate_response(self, user_message: str) -> str:
37
+ """生成嘲讽性回复
38
+
39
+ 参数:
40
+ user_message: 用户的原始消息
41
+
42
+ 返回:
43
+ 生成的嘲讽性回复
44
+ """
45
+ try:
46
+ # 构造请求
47
+ request_body = self._build_request_body(
48
+ messages=[
49
+ {"role": "system", "content": INJECTION_RESPONSE_SYSTEM_PROMPT},
50
+ {
51
+ "role": "user",
52
+ "content": f"<user_message>{user_message}</user_message>",
53
+ },
54
+ ],
55
+ max_tokens=self.security_config.max_tokens,
56
+ )
57
+
58
+ response = await self._http_client.post(
59
+ self.security_config.api_url,
60
+ headers={
61
+ "Authorization": f"Bearer {self.security_config.api_key}",
62
+ "Content-Type": "application/json",
63
+ },
64
+ json=request_body,
65
+ )
66
+ response.raise_for_status()
67
+ result = response.json()
68
+ content = self._extract_choices_content(result).strip()
69
+
70
+ # 去除所有换行符,确保 XML 格式正确
71
+ content = content.replace("\n", " ").replace("\r", " ")
72
+ # 去除多余空格
73
+ content = " ".join(content.split())
74
+
75
+ logger.debug(f"生成的嘲讽回复: {content}")
76
+
77
+ return content if content else "无聊。"
78
+ except Exception as e:
79
+ logger.exception(f"生成嘲讽回复失败: {e}")
80
+ # 失败时返回默认回复
81
+ return "有病?"
82
+
83
+ def _build_request_body(
84
+ self,
85
+ messages: list[dict[str, str]],
86
+ max_tokens: int,
87
+ ) -> dict[str, Any]:
88
+ """构建请求体"""
89
+ body: dict[str, Any] = {
90
+ "model": self.security_config.model_name,
91
+ "messages": messages,
92
+ "max_tokens": max_tokens,
93
+ "temperature": 0.7, # 稍微高一点的温度,让回复更有变化
94
+ }
95
+
96
+ # 添加 thinking 参数(如果启用)
97
+ if self.security_config.thinking_enabled:
98
+ body["thinking"] = {
99
+ "type": "enabled",
100
+ "budget_tokens": self.security_config.thinking_budget_tokens,
101
+ }
102
+ else:
103
+ # 禁用 thinking
104
+ body["thinking"] = {"enabled": False, "budget_tokens": 0}
105
+
106
+ return body
107
+
108
+ def _extract_choices_content(self, result: dict[str, Any]) -> str:
109
+ """从 API 响应中提取 choices 的内容"""
110
+ # 尝试从标准 OpenAI 格式提取
111
+ if "choices" in result and len(result["choices"]) > 0:
112
+ content = result["choices"][0]["message"]["content"]
113
+ if isinstance(content, str):
114
+ return content
115
+ return str(content)
116
+
117
+ # 尝试从 data.choices 提取
118
+ if "data" in result and isinstance(result["data"], dict):
119
+ data = result["data"]
120
+ if "choices" in data and len(data["choices"]) > 0:
121
+ content = data["choices"][0]["message"]["content"]
122
+ if isinstance(content, str):
123
+ return content
124
+ return str(content)
125
+
126
+ # 如果都失败,抛出错误
127
+ raise KeyError(f"无法从 API 响应中提取 choices 内容: {result}")
128
+
129
+ async def close(self) -> None:
130
+ """关闭 HTTP 客户端"""
131
+ await self._http_client.aclose()
Undefined/main.py ADDED
@@ -0,0 +1,126 @@
1
+ """程序入口"""
2
+
3
+ import asyncio
4
+ import logging
5
+ import os
6
+ import sys
7
+ from logging.handlers import RotatingFileHandler
8
+ from pathlib import Path
9
+
10
+ from dotenv import load_dotenv
11
+
12
+ from .ai import AIClient
13
+ from .config import get_config
14
+ from .faq import FAQStorage
15
+ from .handlers import MessageHandler
16
+ from .memory import MemoryStorage
17
+ from .scheduled_task_storage import ScheduledTaskStorage
18
+ from .end_summary_storage import EndSummaryStorage
19
+ from .onebot import OneBotClient
20
+
21
+
22
+ def setup_logging() -> None:
23
+ """设置日志(控制台 + 文件轮转)"""
24
+ load_dotenv()
25
+ log_level = os.getenv("LOG_LEVEL", "INFO").upper()
26
+ level = getattr(logging, log_level, logging.INFO)
27
+
28
+ # 日志格式
29
+ log_format = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
30
+ formatter = logging.Formatter(log_format)
31
+
32
+ # 根日志器
33
+ root_logger = logging.getLogger()
34
+ root_logger.setLevel(level)
35
+
36
+ # 控制台处理器
37
+ console_handler = logging.StreamHandler(sys.stdout)
38
+ console_handler.setFormatter(formatter)
39
+ root_logger.addHandler(console_handler)
40
+
41
+ # 日志文件配置
42
+ log_file_path = os.getenv("LOG_FILE_PATH", "logs/bot.log")
43
+ log_max_size = (
44
+ int(os.getenv("LOG_MAX_SIZE_MB", "10")) * 1024 * 1024
45
+ ) # 兆字节 -> 字节
46
+ log_backup_count = int(os.getenv("LOG_BACKUP_COUNT", "5"))
47
+
48
+ # 确保日志目录存在
49
+ log_dir = Path(log_file_path).parent
50
+ log_dir.mkdir(parents=True, exist_ok=True)
51
+
52
+ file_handler = RotatingFileHandler(
53
+ log_file_path,
54
+ maxBytes=log_max_size,
55
+ backupCount=log_backup_count,
56
+ encoding="utf-8",
57
+ )
58
+ file_handler.setFormatter(formatter)
59
+ root_logger.addHandler(file_handler)
60
+
61
+ logging.info(
62
+ f"[启动] 日志系统初始化完成。级别: {log_level}, 文件: {log_file_path} "
63
+ f"(最大 {log_max_size // 1024 // 1024}MB, 保留 {log_backup_count} 份)"
64
+ )
65
+
66
+
67
+ async def main() -> None:
68
+ """主函数"""
69
+ setup_logging()
70
+ logger = logging.getLogger(__name__)
71
+ logger.info("[启动] 正在初始化 Undefined 机器人...")
72
+
73
+ try:
74
+ config = get_config()
75
+ logger.info(f"[配置] 机器人 QQ: {config.bot_qq}")
76
+ logger.info(f"[配置] 超级管理员: {config.superadmin_qq}")
77
+ logger.info(f"[配置] 管理员 QQ 列表: {config.admin_qqs}")
78
+ except ValueError as e:
79
+ logger.error(f"[配置错误] 加载配置失败: {e}")
80
+ sys.exit(1)
81
+
82
+ # 初始化组件
83
+ logger.info("[初始化] 正在加载核心组件...")
84
+ try:
85
+ onebot = OneBotClient(config.onebot_ws_url, config.onebot_token)
86
+ memory_storage = MemoryStorage(max_memories=100)
87
+ task_storage = ScheduledTaskStorage()
88
+ end_summary_storage = EndSummaryStorage()
89
+ ai = AIClient(
90
+ config.chat_model,
91
+ config.vision_model,
92
+ config.agent_model,
93
+ memory_storage,
94
+ end_summary_storage,
95
+ )
96
+ faq_storage = FAQStorage()
97
+
98
+ handler = MessageHandler(config, onebot, ai, faq_storage, task_storage)
99
+ onebot.set_message_handler(handler.handle_message)
100
+ logger.info("[初始化] 核心组件加载完成")
101
+ except Exception as e:
102
+ logger.exception(f"[初始化错误] 组件初始化期间发生异常: {e}")
103
+ sys.exit(1)
104
+
105
+ logger.info("[启动] 机器人已准备就绪,开始连接 OneBot 服务...")
106
+
107
+ try:
108
+ await onebot.run_with_reconnect()
109
+ except KeyboardInterrupt:
110
+ logger.info("[退出] 收到退出信号 (Ctrl+C)")
111
+ except Exception as e:
112
+ logger.exception(f"[异常] 运行期间发生未捕获的错误: {e}")
113
+ finally:
114
+ logger.info("[清理] 正在关闭机器人并释放资源...")
115
+ await onebot.disconnect()
116
+ await ai.close()
117
+ logger.info("[退出] 机器人已停止运行")
118
+
119
+
120
+ def run() -> None:
121
+ """运行入口"""
122
+ asyncio.run(main())
123
+
124
+
125
+ if __name__ == "__main__":
126
+ run()
Undefined/memory.py ADDED
@@ -0,0 +1,120 @@
1
+ """AI 记忆存储管理模块"""
2
+
3
+ import json
4
+ import logging
5
+ from dataclasses import dataclass, asdict
6
+ from datetime import datetime
7
+ from pathlib import Path
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ # 记忆数据存储路径
12
+ MEMORY_FILE_PATH = Path("data/memory.json")
13
+
14
+
15
+ @dataclass
16
+ class Memory:
17
+ """单条记忆数据"""
18
+
19
+ fact: str # 记忆内容
20
+ created_at: str # 创建时间
21
+
22
+
23
+ class MemoryStorage:
24
+ """AI 记忆存储管理器"""
25
+
26
+ def __init__(self, max_memories: int = 100) -> None:
27
+ """初始化记忆存储
28
+
29
+ 参数:
30
+ max_memories: 最大记忆数量
31
+ """
32
+ self.max_memories = max_memories
33
+ self._memories: list[Memory] = []
34
+ self._load()
35
+
36
+ def _load(self) -> None:
37
+ """从文件加载记忆"""
38
+ if not MEMORY_FILE_PATH.exists():
39
+ self._memories = []
40
+ return
41
+
42
+ try:
43
+ with open(MEMORY_FILE_PATH, "r", encoding="utf-8") as f:
44
+ data = json.load(f)
45
+ self._memories = [Memory(**item) for item in data]
46
+ logger.info(f"已加载 {len(self._memories)} 条记忆")
47
+ except Exception as e:
48
+ logger.warning(f"加载记忆失败: {e}")
49
+ self._memories = []
50
+
51
+ def _save(self) -> None:
52
+ """保存记忆到文件"""
53
+ try:
54
+ MEMORY_FILE_PATH.parent.mkdir(parents=True, exist_ok=True)
55
+ with open(MEMORY_FILE_PATH, "w", encoding="utf-8") as f:
56
+ json.dump(
57
+ [asdict(m) for m in self._memories], f, ensure_ascii=False, indent=2
58
+ )
59
+ logger.debug(f"已保存 {len(self._memories)} 条记忆")
60
+ except Exception as e:
61
+ logger.error(f"保存记忆失败: {e}")
62
+
63
+ def add(self, fact: str) -> bool:
64
+ """添加一条记忆
65
+
66
+ 参数:
67
+ fact: 记忆内容
68
+
69
+ 返回:
70
+ 是否添加成功
71
+ """
72
+ if not fact or not fact.strip():
73
+ logger.warning("尝试添加空记忆,已忽略")
74
+ return False
75
+
76
+ # 检查是否已存在相同记忆
77
+ for existing in self._memories:
78
+ if existing.fact == fact.strip():
79
+ logger.debug(f"记忆已存在,忽略: {fact[:50]}...")
80
+ return False
81
+
82
+ memory = Memory(
83
+ fact=fact.strip(), created_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
84
+ )
85
+
86
+ # 添加到列表末尾
87
+ self._memories.append(memory)
88
+
89
+ # 如果超过上限,移除最旧的(最早的)
90
+ if len(self._memories) > self.max_memories:
91
+ removed = self._memories.pop(0)
92
+ logger.info(f"记忆数量超过上限,移除最旧记忆: {removed.fact[:50]}...")
93
+
94
+ self._save()
95
+ logger.info(
96
+ f"已添加记忆: {fact[:50]}... (当前 {len(self._memories)}/{self.max_memories})"
97
+ )
98
+ return True
99
+
100
+ def get_all(self) -> list[Memory]:
101
+ """获取所有记忆
102
+
103
+ 返回:
104
+ 记忆列表(按时间顺序,最早的在前)
105
+ """
106
+ return self._memories.copy()
107
+
108
+ def clear(self) -> None:
109
+ """清空所有记忆"""
110
+ self._memories = []
111
+ self._save()
112
+ logger.info("已清空所有记忆")
113
+
114
+ def count(self) -> int:
115
+ """获取记忆数量
116
+
117
+ 返回:
118
+ 当前记忆数量
119
+ """
120
+ return len(self._memories)