AstrBot 4.5.1__py3-none-any.whl → 4.5.3__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 (244) hide show
  1. astrbot/api/__init__.py +10 -11
  2. astrbot/api/event/__init__.py +5 -6
  3. astrbot/api/event/filter/__init__.py +37 -36
  4. astrbot/api/platform/__init__.py +7 -8
  5. astrbot/api/provider/__init__.py +7 -7
  6. astrbot/api/star/__init__.py +3 -4
  7. astrbot/api/util/__init__.py +2 -2
  8. astrbot/cli/__main__.py +5 -5
  9. astrbot/cli/commands/__init__.py +3 -3
  10. astrbot/cli/commands/cmd_conf.py +19 -16
  11. astrbot/cli/commands/cmd_init.py +3 -2
  12. astrbot/cli/commands/cmd_plug.py +8 -10
  13. astrbot/cli/commands/cmd_run.py +5 -6
  14. astrbot/cli/utils/__init__.py +6 -6
  15. astrbot/cli/utils/basic.py +14 -14
  16. astrbot/cli/utils/plugin.py +24 -15
  17. astrbot/cli/utils/version_comparator.py +10 -12
  18. astrbot/core/__init__.py +8 -6
  19. astrbot/core/agent/agent.py +3 -2
  20. astrbot/core/agent/handoff.py +6 -2
  21. astrbot/core/agent/hooks.py +9 -6
  22. astrbot/core/agent/mcp_client.py +50 -15
  23. astrbot/core/agent/message.py +168 -0
  24. astrbot/core/agent/response.py +2 -1
  25. astrbot/core/agent/run_context.py +2 -3
  26. astrbot/core/agent/runners/base.py +10 -13
  27. astrbot/core/agent/runners/tool_loop_agent_runner.py +52 -51
  28. astrbot/core/agent/tool.py +60 -41
  29. astrbot/core/agent/tool_executor.py +9 -3
  30. astrbot/core/astr_agent_context.py +3 -1
  31. astrbot/core/astrbot_config_mgr.py +29 -9
  32. astrbot/core/config/__init__.py +2 -2
  33. astrbot/core/config/astrbot_config.py +28 -26
  34. astrbot/core/config/default.py +4 -6
  35. astrbot/core/conversation_mgr.py +105 -36
  36. astrbot/core/core_lifecycle.py +68 -54
  37. astrbot/core/db/__init__.py +33 -18
  38. astrbot/core/db/migration/helper.py +12 -10
  39. astrbot/core/db/migration/migra_3_to_4.py +53 -34
  40. astrbot/core/db/migration/migra_45_to_46.py +1 -1
  41. astrbot/core/db/migration/shared_preferences_v3.py +2 -1
  42. astrbot/core/db/migration/sqlite_v3.py +26 -23
  43. astrbot/core/db/po.py +27 -18
  44. astrbot/core/db/sqlite.py +74 -45
  45. astrbot/core/db/vec_db/base.py +10 -14
  46. astrbot/core/db/vec_db/faiss_impl/document_storage.py +90 -77
  47. astrbot/core/db/vec_db/faiss_impl/embedding_storage.py +9 -3
  48. astrbot/core/db/vec_db/faiss_impl/vec_db.py +36 -31
  49. astrbot/core/event_bus.py +8 -6
  50. astrbot/core/file_token_service.py +6 -5
  51. astrbot/core/initial_loader.py +7 -5
  52. astrbot/core/knowledge_base/chunking/__init__.py +1 -3
  53. astrbot/core/knowledge_base/chunking/base.py +1 -0
  54. astrbot/core/knowledge_base/chunking/fixed_size.py +2 -0
  55. astrbot/core/knowledge_base/chunking/recursive.py +16 -10
  56. astrbot/core/knowledge_base/kb_db_sqlite.py +50 -48
  57. astrbot/core/knowledge_base/kb_helper.py +30 -17
  58. astrbot/core/knowledge_base/kb_mgr.py +6 -7
  59. astrbot/core/knowledge_base/models.py +10 -4
  60. astrbot/core/knowledge_base/parsers/__init__.py +3 -5
  61. astrbot/core/knowledge_base/parsers/base.py +1 -0
  62. astrbot/core/knowledge_base/parsers/markitdown_parser.py +2 -1
  63. astrbot/core/knowledge_base/parsers/pdf_parser.py +2 -1
  64. astrbot/core/knowledge_base/parsers/text_parser.py +1 -0
  65. astrbot/core/knowledge_base/parsers/util.py +1 -1
  66. astrbot/core/knowledge_base/retrieval/__init__.py +6 -8
  67. astrbot/core/knowledge_base/retrieval/manager.py +17 -14
  68. astrbot/core/knowledge_base/retrieval/rank_fusion.py +7 -3
  69. astrbot/core/knowledge_base/retrieval/sparse_retriever.py +11 -5
  70. astrbot/core/log.py +21 -13
  71. astrbot/core/message/components.py +123 -217
  72. astrbot/core/message/message_event_result.py +24 -24
  73. astrbot/core/persona_mgr.py +20 -11
  74. astrbot/core/pipeline/__init__.py +7 -7
  75. astrbot/core/pipeline/content_safety_check/stage.py +13 -9
  76. astrbot/core/pipeline/content_safety_check/strategies/__init__.py +1 -2
  77. astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py +12 -13
  78. astrbot/core/pipeline/content_safety_check/strategies/keywords.py +1 -0
  79. astrbot/core/pipeline/content_safety_check/strategies/strategy.py +6 -6
  80. astrbot/core/pipeline/context.py +4 -1
  81. astrbot/core/pipeline/context_utils.py +77 -7
  82. astrbot/core/pipeline/preprocess_stage/stage.py +12 -9
  83. astrbot/core/pipeline/process_stage/method/llm_request.py +125 -72
  84. astrbot/core/pipeline/process_stage/method/star_request.py +19 -17
  85. astrbot/core/pipeline/process_stage/stage.py +13 -10
  86. astrbot/core/pipeline/process_stage/utils.py +6 -5
  87. astrbot/core/pipeline/rate_limit_check/stage.py +37 -36
  88. astrbot/core/pipeline/respond/stage.py +23 -20
  89. astrbot/core/pipeline/result_decorate/stage.py +31 -23
  90. astrbot/core/pipeline/scheduler.py +12 -8
  91. astrbot/core/pipeline/session_status_check/stage.py +12 -8
  92. astrbot/core/pipeline/stage.py +10 -4
  93. astrbot/core/pipeline/waking_check/stage.py +24 -18
  94. astrbot/core/pipeline/whitelist_check/stage.py +10 -7
  95. astrbot/core/platform/__init__.py +6 -6
  96. astrbot/core/platform/astr_message_event.py +76 -110
  97. astrbot/core/platform/astrbot_message.py +11 -13
  98. astrbot/core/platform/manager.py +16 -15
  99. astrbot/core/platform/message_session.py +5 -3
  100. astrbot/core/platform/platform.py +16 -24
  101. astrbot/core/platform/platform_metadata.py +4 -4
  102. astrbot/core/platform/register.py +8 -8
  103. astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +23 -15
  104. astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +51 -33
  105. astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py +42 -27
  106. astrbot/core/platform/sources/dingtalk/dingtalk_event.py +7 -3
  107. astrbot/core/platform/sources/discord/client.py +9 -6
  108. astrbot/core/platform/sources/discord/components.py +18 -14
  109. astrbot/core/platform/sources/discord/discord_platform_adapter.py +45 -30
  110. astrbot/core/platform/sources/discord/discord_platform_event.py +38 -30
  111. astrbot/core/platform/sources/lark/lark_adapter.py +23 -17
  112. astrbot/core/platform/sources/lark/lark_event.py +21 -14
  113. astrbot/core/platform/sources/misskey/misskey_adapter.py +107 -67
  114. astrbot/core/platform/sources/misskey/misskey_api.py +153 -129
  115. astrbot/core/platform/sources/misskey/misskey_event.py +20 -15
  116. astrbot/core/platform/sources/misskey/misskey_utils.py +74 -62
  117. astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py +63 -44
  118. astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py +41 -26
  119. astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py +36 -17
  120. astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_event.py +3 -1
  121. astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_server.py +12 -7
  122. astrbot/core/platform/sources/satori/satori_adapter.py +56 -38
  123. astrbot/core/platform/sources/satori/satori_event.py +34 -25
  124. astrbot/core/platform/sources/slack/client.py +11 -9
  125. astrbot/core/platform/sources/slack/slack_adapter.py +52 -36
  126. astrbot/core/platform/sources/slack/slack_event.py +34 -24
  127. astrbot/core/platform/sources/telegram/tg_adapter.py +38 -18
  128. astrbot/core/platform/sources/telegram/tg_event.py +32 -18
  129. astrbot/core/platform/sources/webchat/webchat_adapter.py +27 -17
  130. astrbot/core/platform/sources/webchat/webchat_event.py +14 -10
  131. astrbot/core/platform/sources/wechatpadpro/wechatpadpro_adapter.py +115 -120
  132. astrbot/core/platform/sources/wechatpadpro/wechatpadpro_message_event.py +9 -8
  133. astrbot/core/platform/sources/wechatpadpro/xml_data_parser.py +15 -16
  134. astrbot/core/platform/sources/wecom/wecom_adapter.py +35 -18
  135. astrbot/core/platform/sources/wecom/wecom_event.py +55 -48
  136. astrbot/core/platform/sources/wecom/wecom_kf.py +34 -44
  137. astrbot/core/platform/sources/wecom/wecom_kf_message.py +26 -10
  138. astrbot/core/platform/sources/wecom_ai_bot/WXBizJsonMsgCrypt.py +18 -10
  139. astrbot/core/platform/sources/wecom_ai_bot/__init__.py +3 -5
  140. astrbot/core/platform/sources/wecom_ai_bot/ierror.py +0 -1
  141. astrbot/core/platform/sources/wecom_ai_bot/wecomai_adapter.py +61 -37
  142. astrbot/core/platform/sources/wecom_ai_bot/wecomai_api.py +67 -28
  143. astrbot/core/platform/sources/wecom_ai_bot/wecomai_event.py +8 -9
  144. astrbot/core/platform/sources/wecom_ai_bot/wecomai_queue_mgr.py +18 -9
  145. astrbot/core/platform/sources/wecom_ai_bot/wecomai_server.py +14 -12
  146. astrbot/core/platform/sources/wecom_ai_bot/wecomai_utils.py +22 -12
  147. astrbot/core/platform/sources/weixin_official_account/weixin_offacc_adapter.py +40 -26
  148. astrbot/core/platform/sources/weixin_official_account/weixin_offacc_event.py +47 -45
  149. astrbot/core/platform_message_history_mgr.py +5 -3
  150. astrbot/core/provider/__init__.py +2 -3
  151. astrbot/core/provider/entites.py +8 -8
  152. astrbot/core/provider/entities.py +61 -75
  153. astrbot/core/provider/func_tool_manager.py +59 -55
  154. astrbot/core/provider/manager.py +32 -22
  155. astrbot/core/provider/provider.py +72 -46
  156. astrbot/core/provider/register.py +7 -7
  157. astrbot/core/provider/sources/anthropic_source.py +48 -30
  158. astrbot/core/provider/sources/azure_tts_source.py +17 -13
  159. astrbot/core/provider/sources/coze_api_client.py +27 -17
  160. astrbot/core/provider/sources/coze_source.py +104 -87
  161. astrbot/core/provider/sources/dashscope_source.py +18 -11
  162. astrbot/core/provider/sources/dashscope_tts.py +36 -23
  163. astrbot/core/provider/sources/dify_source.py +25 -20
  164. astrbot/core/provider/sources/edge_tts_source.py +21 -17
  165. astrbot/core/provider/sources/fishaudio_tts_api_source.py +22 -14
  166. astrbot/core/provider/sources/gemini_embedding_source.py +12 -13
  167. astrbot/core/provider/sources/gemini_source.py +72 -58
  168. astrbot/core/provider/sources/gemini_tts_source.py +8 -6
  169. astrbot/core/provider/sources/gsv_selfhosted_source.py +17 -14
  170. astrbot/core/provider/sources/gsvi_tts_source.py +11 -7
  171. astrbot/core/provider/sources/minimax_tts_api_source.py +50 -40
  172. astrbot/core/provider/sources/openai_embedding_source.py +6 -8
  173. astrbot/core/provider/sources/openai_source.py +77 -69
  174. astrbot/core/provider/sources/openai_tts_api_source.py +14 -6
  175. astrbot/core/provider/sources/sensevoice_selfhosted_source.py +13 -11
  176. astrbot/core/provider/sources/vllm_rerank_source.py +10 -4
  177. astrbot/core/provider/sources/volcengine_tts.py +38 -31
  178. astrbot/core/provider/sources/whisper_api_source.py +14 -12
  179. astrbot/core/provider/sources/whisper_selfhosted_source.py +15 -11
  180. astrbot/core/provider/sources/xinference_rerank_source.py +16 -8
  181. astrbot/core/provider/sources/xinference_stt_provider.py +35 -25
  182. astrbot/core/star/__init__.py +16 -11
  183. astrbot/core/star/config.py +10 -15
  184. astrbot/core/star/context.py +97 -75
  185. astrbot/core/star/filter/__init__.py +4 -3
  186. astrbot/core/star/filter/command.py +30 -28
  187. astrbot/core/star/filter/command_group.py +27 -24
  188. astrbot/core/star/filter/custom_filter.py +6 -5
  189. astrbot/core/star/filter/event_message_type.py +4 -2
  190. astrbot/core/star/filter/permission.py +4 -2
  191. astrbot/core/star/filter/platform_adapter_type.py +4 -2
  192. astrbot/core/star/filter/regex.py +4 -2
  193. astrbot/core/star/register/__init__.py +19 -19
  194. astrbot/core/star/register/star.py +6 -2
  195. astrbot/core/star/register/star_handler.py +96 -73
  196. astrbot/core/star/session_llm_manager.py +48 -14
  197. astrbot/core/star/session_plugin_manager.py +29 -15
  198. astrbot/core/star/star.py +1 -2
  199. astrbot/core/star/star_handler.py +13 -8
  200. astrbot/core/star/star_manager.py +151 -59
  201. astrbot/core/star/star_tools.py +44 -37
  202. astrbot/core/star/updator.py +10 -10
  203. astrbot/core/umop_config_router.py +10 -4
  204. astrbot/core/updator.py +13 -5
  205. astrbot/core/utils/astrbot_path.py +3 -5
  206. astrbot/core/utils/dify_api_client.py +33 -15
  207. astrbot/core/utils/io.py +66 -42
  208. astrbot/core/utils/log_pipe.py +1 -1
  209. astrbot/core/utils/metrics.py +7 -7
  210. astrbot/core/utils/path_util.py +15 -16
  211. astrbot/core/utils/pip_installer.py +5 -5
  212. astrbot/core/utils/session_waiter.py +19 -20
  213. astrbot/core/utils/shared_preferences.py +45 -20
  214. astrbot/core/utils/t2i/__init__.py +4 -1
  215. astrbot/core/utils/t2i/network_strategy.py +35 -26
  216. astrbot/core/utils/t2i/renderer.py +11 -5
  217. astrbot/core/utils/t2i/template_manager.py +14 -15
  218. astrbot/core/utils/tencent_record_helper.py +19 -13
  219. astrbot/core/utils/version_comparator.py +10 -13
  220. astrbot/core/zip_updator.py +43 -40
  221. astrbot/dashboard/routes/__init__.py +18 -18
  222. astrbot/dashboard/routes/auth.py +10 -8
  223. astrbot/dashboard/routes/chat.py +30 -21
  224. astrbot/dashboard/routes/config.py +92 -75
  225. astrbot/dashboard/routes/conversation.py +46 -39
  226. astrbot/dashboard/routes/file.py +4 -2
  227. astrbot/dashboard/routes/knowledge_base.py +47 -40
  228. astrbot/dashboard/routes/log.py +9 -4
  229. astrbot/dashboard/routes/persona.py +19 -16
  230. astrbot/dashboard/routes/plugin.py +69 -55
  231. astrbot/dashboard/routes/route.py +3 -1
  232. astrbot/dashboard/routes/session_management.py +130 -116
  233. astrbot/dashboard/routes/stat.py +34 -34
  234. astrbot/dashboard/routes/t2i.py +15 -12
  235. astrbot/dashboard/routes/tools.py +56 -53
  236. astrbot/dashboard/routes/update.py +32 -28
  237. astrbot/dashboard/server.py +30 -26
  238. astrbot/dashboard/utils.py +8 -4
  239. {astrbot-4.5.1.dist-info → astrbot-4.5.3.dist-info}/METADATA +2 -1
  240. astrbot-4.5.3.dist-info/RECORD +261 -0
  241. astrbot-4.5.1.dist-info/RECORD +0 -260
  242. {astrbot-4.5.1.dist-info → astrbot-4.5.3.dist-info}/WHEEL +0 -0
  243. {astrbot-4.5.1.dist-info → astrbot-4.5.3.dist-info}/entry_points.txt +0 -0
  244. {astrbot-4.5.1.dist-info → astrbot-4.5.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,10 +1,13 @@
1
- import traceback
2
1
  import json
3
- from .route import Route, Response, RouteContext
4
- from astrbot.core import logger
2
+ import traceback
3
+
5
4
  from quart import request
6
- from astrbot.core.db import BaseDatabase
5
+
6
+ from astrbot.core import logger
7
7
  from astrbot.core.core_lifecycle import AstrBotCoreLifecycle
8
+ from astrbot.core.db import BaseDatabase
9
+
10
+ from .route import Response, Route, RouteContext
8
11
 
9
12
 
10
13
  class ConversationRoute(Route):
@@ -55,12 +58,10 @@ class ConversationRoute(Route):
55
58
  exclude_platforms.split(",") if exclude_platforms else []
56
59
  )
57
60
 
58
- if page < 1:
59
- page = 1
61
+ page = max(page, 1)
60
62
  if page_size < 1:
61
63
  page_size = 20
62
- if page_size > 100:
63
- page_size = 100
64
+ page_size = min(page_size, 100)
64
65
 
65
66
  try:
66
67
  (
@@ -76,8 +77,8 @@ class ConversationRoute(Route):
76
77
  exclude_platforms=exclude_platform_list,
77
78
  )
78
79
  except Exception as e:
79
- logger.error(f"数据库查询出错: {str(e)}\n{traceback.format_exc()}")
80
- return Response().error(f"数据库查询出错: {str(e)}").__dict__
80
+ logger.error(f"数据库查询出错: {e!s}\n{traceback.format_exc()}")
81
+ return Response().error(f"数据库查询出错: {e!s}").__dict__
81
82
 
82
83
  # 计算总页数
83
84
  total_pages = (
@@ -96,9 +97,9 @@ class ConversationRoute(Route):
96
97
  return Response().ok(result).__dict__
97
98
 
98
99
  except Exception as e:
99
- error_msg = f"获取对话列表失败: {str(e)}\n{traceback.format_exc()}"
100
+ error_msg = f"获取对话列表失败: {e!s}\n{traceback.format_exc()}"
100
101
  logger.error(error_msg)
101
- return Response().error(f"获取对话列表失败: {str(e)}").__dict__
102
+ return Response().error(f"获取对话列表失败: {e!s}").__dict__
102
103
 
103
104
  async def get_conv_detail(self):
104
105
  """获取指定对话详情(通过POST请求)"""
@@ -111,7 +112,8 @@ class ConversationRoute(Route):
111
112
  return Response().error("缺少必要参数: user_id 和 cid").__dict__
112
113
 
113
114
  conversation = await self.conv_mgr.get_conversation(
114
- unified_msg_origin=user_id, conversation_id=cid
115
+ unified_msg_origin=user_id,
116
+ conversation_id=cid,
115
117
  )
116
118
  if not conversation:
117
119
  return Response().error("对话不存在").__dict__
@@ -127,14 +129,14 @@ class ConversationRoute(Route):
127
129
  "history": conversation.history,
128
130
  "created_at": conversation.created_at,
129
131
  "updated_at": conversation.updated_at,
130
- }
132
+ },
131
133
  )
132
134
  .__dict__
133
135
  )
134
136
 
135
137
  except Exception as e:
136
- logger.error(f"获取对话详情失败: {str(e)}\n{traceback.format_exc()}")
137
- return Response().error(f"获取对话详情失败: {str(e)}").__dict__
138
+ logger.error(f"获取对话详情失败: {e!s}\n{traceback.format_exc()}")
139
+ return Response().error(f"获取对话详情失败: {e!s}").__dict__
138
140
 
139
141
  async def upd_conv(self):
140
142
  """更新对话信息(标题和角色ID)"""
@@ -148,7 +150,8 @@ class ConversationRoute(Route):
148
150
  if not user_id or not cid:
149
151
  return Response().error("缺少必要参数: user_id 和 cid").__dict__
150
152
  conversation = await self.conv_mgr.get_conversation(
151
- unified_msg_origin=user_id, conversation_id=cid
153
+ unified_msg_origin=user_id,
154
+ conversation_id=cid,
152
155
  )
153
156
  if not conversation:
154
157
  return Response().error("对话不存在").__dict__
@@ -162,8 +165,8 @@ class ConversationRoute(Route):
162
165
  return Response().ok({"message": "对话信息更新成功"}).__dict__
163
166
 
164
167
  except Exception as e:
165
- logger.error(f"更新对话信息失败: {str(e)}\n{traceback.format_exc()}")
166
- return Response().error(f"更新对话信息失败: {str(e)}").__dict__
168
+ logger.error(f"更新对话信息失败: {e!s}\n{traceback.format_exc()}")
169
+ return Response().error(f"更新对话信息失败: {e!s}").__dict__
167
170
 
168
171
  async def del_conv(self):
169
172
  """删除对话"""
@@ -188,17 +191,18 @@ class ConversationRoute(Route):
188
191
 
189
192
  if not user_id or not cid:
190
193
  failed_items.append(
191
- f"user_id:{user_id}, cid:{cid} - 缺少必要参数"
194
+ f"user_id:{user_id}, cid:{cid} - 缺少必要参数",
192
195
  )
193
196
  continue
194
197
 
195
198
  try:
196
199
  await self.core_lifecycle.conversation_manager.delete_conversation(
197
- unified_msg_origin=user_id, conversation_id=cid
200
+ unified_msg_origin=user_id,
201
+ conversation_id=cid,
198
202
  )
199
203
  deleted_count += 1
200
204
  except Exception as e:
201
- failed_items.append(f"user_id:{user_id}, cid:{cid} - {str(e)}")
205
+ failed_items.append(f"user_id:{user_id}, cid:{cid} - {e!s}")
202
206
 
203
207
  message = f"成功删除 {deleted_count} 个对话"
204
208
  if failed_items:
@@ -212,26 +216,26 @@ class ConversationRoute(Route):
212
216
  "deleted_count": deleted_count,
213
217
  "failed_count": len(failed_items),
214
218
  "failed_items": failed_items,
215
- }
219
+ },
216
220
  )
217
221
  .__dict__
218
222
  )
219
- else:
220
- # 单个删除
221
- user_id = data.get("user_id")
222
- cid = data.get("cid")
223
+ # 单个删除
224
+ user_id = data.get("user_id")
225
+ cid = data.get("cid")
223
226
 
224
- if not user_id or not cid:
225
- return Response().error("缺少必要参数: user_id 和 cid").__dict__
227
+ if not user_id or not cid:
228
+ return Response().error("缺少必要参数: user_id 和 cid").__dict__
226
229
 
227
- await self.core_lifecycle.conversation_manager.delete_conversation(
228
- unified_msg_origin=user_id, conversation_id=cid
229
- )
230
- return Response().ok({"message": "对话删除成功"}).__dict__
230
+ await self.core_lifecycle.conversation_manager.delete_conversation(
231
+ unified_msg_origin=user_id,
232
+ conversation_id=cid,
233
+ )
234
+ return Response().ok({"message": "对话删除成功"}).__dict__
231
235
 
232
236
  except Exception as e:
233
- logger.error(f"删除对话失败: {str(e)}\n{traceback.format_exc()}")
234
- return Response().error(f"删除对话失败: {str(e)}").__dict__
237
+ logger.error(f"删除对话失败: {e!s}\n{traceback.format_exc()}")
238
+ return Response().error(f"删除对话失败: {e!s}").__dict__
235
239
 
236
240
  async def update_history(self):
237
241
  """更新对话历史内容"""
@@ -260,7 +264,8 @@ class ConversationRoute(Route):
260
264
  )
261
265
 
262
266
  conversation = await self.conv_mgr.get_conversation(
263
- unified_msg_origin=user_id, conversation_id=cid
267
+ unified_msg_origin=user_id,
268
+ conversation_id=cid,
264
269
  )
265
270
  if not conversation:
266
271
  return Response().error("对话不存在").__dict__
@@ -268,11 +273,13 @@ class ConversationRoute(Route):
268
273
  history = json.loads(history) if isinstance(history, str) else history
269
274
 
270
275
  await self.conv_mgr.update_conversation(
271
- unified_msg_origin=user_id, conversation_id=cid, history=history
276
+ unified_msg_origin=user_id,
277
+ conversation_id=cid,
278
+ history=history,
272
279
  )
273
280
 
274
281
  return Response().ok({"message": "对话历史更新成功"}).__dict__
275
282
 
276
283
  except Exception as e:
277
- logger.error(f"更新对话历史失败: {str(e)}\n{traceback.format_exc()}")
278
- return Response().error(f"更新对话历史失败: {str(e)}").__dict__
284
+ logger.error(f"更新对话历史失败: {e!s}\n{traceback.format_exc()}")
285
+ return Response().error(f"更新对话历史失败: {e!s}").__dict__
@@ -1,8 +1,10 @@
1
- from .route import Route, RouteContext
2
- from astrbot import logger
3
1
  from quart import abort, send_file
2
+
3
+ from astrbot import logger
4
4
  from astrbot.core import file_token_service
5
5
 
6
+ from .route import Route, RouteContext
7
+
6
8
 
7
9
  class FileRoute(Route):
8
10
  def __init__(
@@ -1,17 +1,20 @@
1
1
  """知识库管理 API 路由"""
2
2
 
3
- import uuid
4
- import aiofiles
3
+ import asyncio
5
4
  import os
6
5
  import traceback
7
- import asyncio
6
+ import uuid
7
+
8
+ import aiofiles
8
9
  from quart import request
10
+
9
11
  from astrbot.core import logger
10
12
  from astrbot.core.core_lifecycle import AstrBotCoreLifecycle
11
- from .route import Route, Response, RouteContext
12
- from ..utils import generate_tsne_visualization
13
13
  from astrbot.core.provider.provider import EmbeddingProvider, RerankProvider
14
14
 
15
+ from ..utils import generate_tsne_visualization
16
+ from .route import Response, Route, RouteContext
17
+
15
18
 
16
19
  class KnowledgeBaseRoute(Route):
17
20
  """知识库管理路由
@@ -108,7 +111,7 @@ class KnowledgeBaseRoute(Route):
108
111
  "stage": "parsing",
109
112
  "current": 0,
110
113
  "total": 100,
111
- }
114
+ },
112
115
  )
113
116
 
114
117
  # 创建进度回调函数
@@ -122,7 +125,7 @@ class KnowledgeBaseRoute(Route):
122
125
  "stage": stage,
123
126
  "current": current,
124
127
  "total": total,
125
- }
128
+ },
126
129
  )
127
130
 
128
131
  doc = await kb_helper.upload_document(
@@ -141,7 +144,7 @@ class KnowledgeBaseRoute(Route):
141
144
  except Exception as e:
142
145
  logger.error(f"上传文档 {file_info['file_name']} 失败: {e}")
143
146
  failed_docs.append(
144
- {"file_name": file_info["file_name"], "error": str(e)}
147
+ {"file_name": file_info["file_name"], "error": str(e)},
145
148
  )
146
149
 
147
150
  # 更新任务完成状态
@@ -202,7 +205,7 @@ class KnowledgeBaseRoute(Route):
202
205
  except Exception as e:
203
206
  logger.error(f"获取知识库列表失败: {e}")
204
207
  logger.error(traceback.format_exc())
205
- return Response().error(f"获取知识库列表失败: {str(e)}").__dict__
208
+ return Response().error(f"获取知识库列表失败: {e!s}").__dict__
206
209
 
207
210
  async def create_kb(self):
208
211
  """创建知识库
@@ -240,7 +243,7 @@ class KnowledgeBaseRoute(Route):
240
243
  if not embedding_provider_id:
241
244
  return Response().error("缺少参数 embedding_provider_id").__dict__
242
245
  prv = await kb_manager.provider_manager.get_provider_by_id(
243
- embedding_provider_id
246
+ embedding_provider_id,
244
247
  ) # type: ignore
245
248
  if not prv or not isinstance(prv, EmbeddingProvider):
246
249
  return (
@@ -250,15 +253,15 @@ class KnowledgeBaseRoute(Route):
250
253
  vec = await prv.get_embedding("astrbot")
251
254
  if len(vec) != prv.get_dim():
252
255
  raise ValueError(
253
- f"嵌入向量维度不匹配,实际是 {len(vec)},然而配置是 {prv.get_dim()}"
256
+ f"嵌入向量维度不匹配,实际是 {len(vec)},然而配置是 {prv.get_dim()}",
254
257
  )
255
258
  except Exception as e:
256
- return Response().error(f"测试嵌入模型失败: {str(e)}").__dict__
259
+ return Response().error(f"测试嵌入模型失败: {e!s}").__dict__
257
260
  # pre-check rerank
258
261
  if rerank_provider_id:
259
262
  rerank_prv: RerankProvider = (
260
263
  await kb_manager.provider_manager.get_provider_by_id(
261
- rerank_provider_id
264
+ rerank_provider_id,
262
265
  )
263
266
  ) # type: ignore
264
267
  if not rerank_prv:
@@ -266,14 +269,15 @@ class KnowledgeBaseRoute(Route):
266
269
  # 检查重排序模型可用性
267
270
  try:
268
271
  res = await rerank_prv.rerank(
269
- query="astrbot", documents=["astrbot knowledge base"]
272
+ query="astrbot",
273
+ documents=["astrbot knowledge base"],
270
274
  )
271
275
  if not res:
272
276
  raise ValueError("重排序模型返回结果异常")
273
277
  except Exception as e:
274
278
  return (
275
279
  Response()
276
- .error(f"测试重排序模型失败: {str(e)},请检查控制台日志输出。")
280
+ .error(f"测试重排序模型失败: {e!s},请检查控制台日志输出。")
277
281
  .__dict__
278
282
  )
279
283
 
@@ -298,7 +302,7 @@ class KnowledgeBaseRoute(Route):
298
302
  except Exception as e:
299
303
  logger.error(f"创建知识库失败: {e}")
300
304
  logger.error(traceback.format_exc())
301
- return Response().error(f"创建知识库失败: {str(e)}").__dict__
305
+ return Response().error(f"创建知识库失败: {e!s}").__dict__
302
306
 
303
307
  async def get_kb(self):
304
308
  """获取知识库详情
@@ -324,7 +328,7 @@ class KnowledgeBaseRoute(Route):
324
328
  except Exception as e:
325
329
  logger.error(f"获取知识库详情失败: {e}")
326
330
  logger.error(traceback.format_exc())
327
- return Response().error(f"获取知识库详情失败: {str(e)}").__dict__
331
+ return Response().error(f"获取知识库详情失败: {e!s}").__dict__
328
332
 
329
333
  async def update_kb(self):
330
334
  """更新知识库
@@ -404,7 +408,7 @@ class KnowledgeBaseRoute(Route):
404
408
  except Exception as e:
405
409
  logger.error(f"更新知识库失败: {e}")
406
410
  logger.error(traceback.format_exc())
407
- return Response().error(f"更新知识库失败: {str(e)}").__dict__
411
+ return Response().error(f"更新知识库失败: {e!s}").__dict__
408
412
 
409
413
  async def delete_kb(self):
410
414
  """删除知识库
@@ -431,7 +435,7 @@ class KnowledgeBaseRoute(Route):
431
435
  except Exception as e:
432
436
  logger.error(f"删除知识库失败: {e}")
433
437
  logger.error(traceback.format_exc())
434
- return Response().error(f"删除知识库失败: {str(e)}").__dict__
438
+ return Response().error(f"删除知识库失败: {e!s}").__dict__
435
439
 
436
440
  async def get_kb_stats(self):
437
441
  """获取知识库统计信息
@@ -466,7 +470,7 @@ class KnowledgeBaseRoute(Route):
466
470
  except Exception as e:
467
471
  logger.error(f"获取知识库统计失败: {e}")
468
472
  logger.error(traceback.format_exc())
469
- return Response().error(f"获取知识库统计失败: {str(e)}").__dict__
473
+ return Response().error(f"获取知识库统计失败: {e!s}").__dict__
470
474
 
471
475
  # ===== 文档管理 API =====
472
476
 
@@ -508,7 +512,7 @@ class KnowledgeBaseRoute(Route):
508
512
  except Exception as e:
509
513
  logger.error(f"获取文档列表失败: {e}")
510
514
  logger.error(traceback.format_exc())
511
- return Response().error(f"获取文档列表失败: {str(e)}").__dict__
515
+ return Response().error(f"获取文档列表失败: {e!s}").__dict__
512
516
 
513
517
  async def upload_document(self):
514
518
  """上传文档
@@ -597,7 +601,7 @@ class KnowledgeBaseRoute(Route):
597
601
  "file_name": file_name,
598
602
  "file_content": file_content,
599
603
  "file_type": file_type,
600
- }
604
+ },
601
605
  )
602
606
  finally:
603
607
  # 清理临时文件
@@ -630,7 +634,7 @@ class KnowledgeBaseRoute(Route):
630
634
  batch_size=batch_size,
631
635
  tasks_limit=tasks_limit,
632
636
  max_retries=max_retries,
633
- )
637
+ ),
634
638
  )
635
639
 
636
640
  return (
@@ -640,7 +644,7 @@ class KnowledgeBaseRoute(Route):
640
644
  "task_id": task_id,
641
645
  "file_count": len(files_to_upload),
642
646
  "message": "task created, processing in background",
643
- }
647
+ },
644
648
  )
645
649
  .__dict__
646
650
  )
@@ -650,7 +654,7 @@ class KnowledgeBaseRoute(Route):
650
654
  except Exception as e:
651
655
  logger.error(f"上传文档失败: {e}")
652
656
  logger.error(traceback.format_exc())
653
- return Response().error(f"上传文档失败: {str(e)}").__dict__
657
+ return Response().error(f"上传文档失败: {e!s}").__dict__
654
658
 
655
659
  async def get_upload_progress(self):
656
660
  """获取上传进度和结果
@@ -703,7 +707,7 @@ class KnowledgeBaseRoute(Route):
703
707
  except Exception as e:
704
708
  logger.error(f"获取上传进度失败: {e}")
705
709
  logger.error(traceback.format_exc())
706
- return Response().error(f"获取上传进度失败: {str(e)}").__dict__
710
+ return Response().error(f"获取上传进度失败: {e!s}").__dict__
707
711
 
708
712
  async def get_document(self):
709
713
  """获取文档详情
@@ -734,7 +738,7 @@ class KnowledgeBaseRoute(Route):
734
738
  except Exception as e:
735
739
  logger.error(f"获取文档详情失败: {e}")
736
740
  logger.error(traceback.format_exc())
737
- return Response().error(f"获取文档详情失败: {str(e)}").__dict__
741
+ return Response().error(f"获取文档详情失败: {e!s}").__dict__
738
742
 
739
743
  async def delete_document(self):
740
744
  """删除文档
@@ -766,7 +770,7 @@ class KnowledgeBaseRoute(Route):
766
770
  except Exception as e:
767
771
  logger.error(f"删除文档失败: {e}")
768
772
  logger.error(traceback.format_exc())
769
- return Response().error(f"删除文档失败: {str(e)}").__dict__
773
+ return Response().error(f"删除文档失败: {e!s}").__dict__
770
774
 
771
775
  async def delete_chunk(self):
772
776
  """删除文本块
@@ -801,7 +805,7 @@ class KnowledgeBaseRoute(Route):
801
805
  except Exception as e:
802
806
  logger.error(f"删除文本块失败: {e}")
803
807
  logger.error(traceback.format_exc())
804
- return Response().error(f"删除文本块失败: {str(e)}").__dict__
808
+ return Response().error(f"删除文本块失败: {e!s}").__dict__
805
809
 
806
810
  async def list_chunks(self):
807
811
  """获取块列表
@@ -827,7 +831,9 @@ class KnowledgeBaseRoute(Route):
827
831
  if not kb_helper:
828
832
  return Response().error("知识库不存在").__dict__
829
833
  chunk_list = await kb_helper.get_chunks_by_doc_id(
830
- doc_id=doc_id, offset=offset, limit=limit
834
+ doc_id=doc_id,
835
+ offset=offset,
836
+ limit=limit,
831
837
  )
832
838
  return (
833
839
  Response()
@@ -837,7 +843,7 @@ class KnowledgeBaseRoute(Route):
837
843
  "page": page,
838
844
  "page_size": page_size,
839
845
  "total": await kb_helper.get_chunk_count_by_doc_id(doc_id),
840
- }
846
+ },
841
847
  )
842
848
  .__dict__
843
849
  )
@@ -846,7 +852,7 @@ class KnowledgeBaseRoute(Route):
846
852
  except Exception as e:
847
853
  logger.error(f"获取块列表失败: {e}")
848
854
  logger.error(traceback.format_exc())
849
- return Response().error(f"获取块列表失败: {str(e)}").__dict__
855
+ return Response().error(f"获取块列表失败: {e!s}").__dict__
850
856
 
851
857
  # ===== 检索 API =====
852
858
 
@@ -893,7 +899,9 @@ class KnowledgeBaseRoute(Route):
893
899
  if debug:
894
900
  try:
895
901
  img_base64 = await generate_tsne_visualization(
896
- query, kb_names, kb_manager
902
+ query,
903
+ kb_names,
904
+ kb_manager,
897
905
  )
898
906
  if img_base64:
899
907
  response_data["visualization"] = img_base64
@@ -909,7 +917,7 @@ class KnowledgeBaseRoute(Route):
909
917
  except Exception as e:
910
918
  logger.error(f"检索失败: {e}")
911
919
  logger.error(traceback.format_exc())
912
- return Response().error(f"检索失败: {str(e)}").__dict__
920
+ return Response().error(f"检索失败: {e!s}").__dict__
913
921
 
914
922
  # ===== 会话知识库配置 API =====
915
923
 
@@ -945,7 +953,7 @@ class KnowledgeBaseRoute(Route):
945
953
 
946
954
  except Exception as e:
947
955
  logger.error(f"[KB配置] 获取配置时出错: {e}", exc_info=True)
948
- return Response().error(f"获取会话知识库配置失败: {str(e)}").__dict__
956
+ return Response().error(f"获取会话知识库配置失败: {e!s}").__dict__
949
957
 
950
958
  async def set_session_kb_config(self):
951
959
  """设置会话的知识库配置
@@ -1024,13 +1032,12 @@ class KnowledgeBaseRoute(Route):
1024
1032
  )
1025
1033
  .__dict__
1026
1034
  )
1027
- else:
1028
- logger.error("[KB配置] 配置保存失败,验证不匹配")
1029
- return Response().error("配置保存失败").__dict__
1035
+ logger.error("[KB配置] 配置保存失败,验证不匹配")
1036
+ return Response().error("配置保存失败").__dict__
1030
1037
 
1031
1038
  except Exception as e:
1032
1039
  logger.error(f"[KB配置] 设置配置时出错: {e}", exc_info=True)
1033
- return Response().error(f"设置会话知识库配置失败: {str(e)}").__dict__
1040
+ return Response().error(f"设置会话知识库配置失败: {e!s}").__dict__
1034
1041
 
1035
1042
  async def delete_session_kb_config(self):
1036
1043
  """删除会话的知识库配置
@@ -1062,4 +1069,4 @@ class KnowledgeBaseRoute(Route):
1062
1069
  except Exception as e:
1063
1070
  logger.error(f"删除会话知识库配置失败: {e}")
1064
1071
  logger.error(traceback.format_exc())
1065
- return Response().error(f"删除会话知识库配置失败: {str(e)}").__dict__
1072
+ return Response().error(f"删除会话知识库配置失败: {e!s}").__dict__
@@ -1,8 +1,11 @@
1
1
  import asyncio
2
2
  import json
3
+
3
4
  from quart import make_response
4
- from astrbot.core import logger, LogBroker
5
- from .route import Route, RouteContext, Response
5
+
6
+ from astrbot.core import LogBroker, logger
7
+
8
+ from .route import Response, Route, RouteContext
6
9
 
7
10
 
8
11
  class LogRoute(Route):
@@ -11,7 +14,9 @@ class LogRoute(Route):
11
14
  self.log_broker = log_broker
12
15
  self.app.add_url_rule("/api/live-log", view_func=self.log, methods=["GET"])
13
16
  self.app.add_url_rule(
14
- "/api/log-history", view_func=self.log_history, methods=["GET"]
17
+ "/api/log-history",
18
+ view_func=self.log_history,
19
+ methods=["GET"],
15
20
  )
16
21
 
17
22
  async def log(self):
@@ -55,7 +60,7 @@ class LogRoute(Route):
55
60
  .ok(
56
61
  data={
57
62
  "logs": logs,
58
- }
63
+ },
59
64
  )
60
65
  .__dict__
61
66
  )
@@ -1,9 +1,12 @@
1
1
  import traceback
2
- from .route import Route, Response, RouteContext
3
- from astrbot.core import logger
2
+
4
3
  from quart import request
5
- from astrbot.core.db import BaseDatabase
4
+
5
+ from astrbot.core import logger
6
6
  from astrbot.core.core_lifecycle import AstrBotCoreLifecycle
7
+ from astrbot.core.db import BaseDatabase
8
+
9
+ from .route import Response, Route, RouteContext
7
10
 
8
11
 
9
12
  class PersonaRoute(Route):
@@ -46,13 +49,13 @@ class PersonaRoute(Route):
46
49
  else None,
47
50
  }
48
51
  for persona in personas
49
- ]
52
+ ],
50
53
  )
51
54
  .__dict__
52
55
  )
53
56
  except Exception as e:
54
- logger.error(f"获取人格列表失败: {str(e)}\n{traceback.format_exc()}")
55
- return Response().error(f"获取人格列表失败: {str(e)}").__dict__
57
+ logger.error(f"获取人格列表失败: {e!s}\n{traceback.format_exc()}")
58
+ return Response().error(f"获取人格列表失败: {e!s}").__dict__
56
59
 
57
60
  async def get_persona_detail(self):
58
61
  """获取指定人格的详细信息"""
@@ -81,13 +84,13 @@ class PersonaRoute(Route):
81
84
  "updated_at": persona.updated_at.isoformat()
82
85
  if persona.updated_at
83
86
  else None,
84
- }
87
+ },
85
88
  )
86
89
  .__dict__
87
90
  )
88
91
  except Exception as e:
89
- logger.error(f"获取人格详情失败: {str(e)}\n{traceback.format_exc()}")
90
- return Response().error(f"获取人格详情失败: {str(e)}").__dict__
92
+ logger.error(f"获取人格详情失败: {e!s}\n{traceback.format_exc()}")
93
+ return Response().error(f"获取人格详情失败: {e!s}").__dict__
91
94
 
92
95
  async def create_persona(self):
93
96
  """创建新人格"""
@@ -136,15 +139,15 @@ class PersonaRoute(Route):
136
139
  if persona.updated_at
137
140
  else None,
138
141
  },
139
- }
142
+ },
140
143
  )
141
144
  .__dict__
142
145
  )
143
146
  except ValueError as e:
144
147
  return Response().error(str(e)).__dict__
145
148
  except Exception as e:
146
- logger.error(f"创建人格失败: {str(e)}\n{traceback.format_exc()}")
147
- return Response().error(f"创建人格失败: {str(e)}").__dict__
149
+ logger.error(f"创建人格失败: {e!s}\n{traceback.format_exc()}")
150
+ return Response().error(f"创建人格失败: {e!s}").__dict__
148
151
 
149
152
  async def update_persona(self):
150
153
  """更新人格信息"""
@@ -177,8 +180,8 @@ class PersonaRoute(Route):
177
180
  except ValueError as e:
178
181
  return Response().error(str(e)).__dict__
179
182
  except Exception as e:
180
- logger.error(f"更新人格失败: {str(e)}\n{traceback.format_exc()}")
181
- return Response().error(f"更新人格失败: {str(e)}").__dict__
183
+ logger.error(f"更新人格失败: {e!s}\n{traceback.format_exc()}")
184
+ return Response().error(f"更新人格失败: {e!s}").__dict__
182
185
 
183
186
  async def delete_persona(self):
184
187
  """删除人格"""
@@ -195,5 +198,5 @@ class PersonaRoute(Route):
195
198
  except ValueError as e:
196
199
  return Response().error(str(e)).__dict__
197
200
  except Exception as e:
198
- logger.error(f"删除人格失败: {str(e)}\n{traceback.format_exc()}")
199
- return Response().error(f"删除人格失败: {str(e)}").__dict__
201
+ logger.error(f"删除人格失败: {e!s}\n{traceback.format_exc()}")
202
+ return Response().error(f"删除人格失败: {e!s}").__dict__