AstrBot 4.10.2__py3-none-any.whl → 4.10.4__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 (84) hide show
  1. astrbot/builtin_stars/astrbot/long_term_memory.py +186 -0
  2. astrbot/builtin_stars/astrbot/main.py +120 -0
  3. astrbot/builtin_stars/astrbot/metadata.yaml +4 -0
  4. astrbot/builtin_stars/astrbot/process_llm_request.py +245 -0
  5. astrbot/builtin_stars/builtin_commands/commands/__init__.py +31 -0
  6. astrbot/builtin_stars/builtin_commands/commands/admin.py +77 -0
  7. astrbot/builtin_stars/builtin_commands/commands/alter_cmd.py +173 -0
  8. astrbot/builtin_stars/builtin_commands/commands/conversation.py +366 -0
  9. astrbot/builtin_stars/builtin_commands/commands/help.py +88 -0
  10. astrbot/builtin_stars/builtin_commands/commands/llm.py +20 -0
  11. astrbot/builtin_stars/builtin_commands/commands/persona.py +142 -0
  12. astrbot/builtin_stars/builtin_commands/commands/plugin.py +120 -0
  13. astrbot/builtin_stars/builtin_commands/commands/provider.py +329 -0
  14. astrbot/builtin_stars/builtin_commands/commands/setunset.py +36 -0
  15. astrbot/builtin_stars/builtin_commands/commands/sid.py +36 -0
  16. astrbot/builtin_stars/builtin_commands/commands/t2i.py +23 -0
  17. astrbot/builtin_stars/builtin_commands/commands/tool.py +31 -0
  18. astrbot/builtin_stars/builtin_commands/commands/tts.py +36 -0
  19. astrbot/builtin_stars/builtin_commands/commands/utils/rst_scene.py +26 -0
  20. astrbot/builtin_stars/builtin_commands/main.py +237 -0
  21. astrbot/builtin_stars/builtin_commands/metadata.yaml +4 -0
  22. astrbot/builtin_stars/python_interpreter/main.py +536 -0
  23. astrbot/builtin_stars/python_interpreter/metadata.yaml +4 -0
  24. astrbot/builtin_stars/python_interpreter/requirements.txt +1 -0
  25. astrbot/builtin_stars/python_interpreter/shared/api.py +22 -0
  26. astrbot/builtin_stars/reminder/main.py +266 -0
  27. astrbot/builtin_stars/reminder/metadata.yaml +4 -0
  28. astrbot/builtin_stars/session_controller/main.py +114 -0
  29. astrbot/builtin_stars/session_controller/metadata.yaml +5 -0
  30. astrbot/builtin_stars/web_searcher/engines/__init__.py +111 -0
  31. astrbot/builtin_stars/web_searcher/engines/bing.py +30 -0
  32. astrbot/builtin_stars/web_searcher/engines/sogo.py +52 -0
  33. astrbot/builtin_stars/web_searcher/main.py +436 -0
  34. astrbot/builtin_stars/web_searcher/metadata.yaml +4 -0
  35. astrbot/cli/__init__.py +1 -1
  36. astrbot/core/agent/message.py +32 -1
  37. astrbot/core/agent/runners/tool_loop_agent_runner.py +26 -8
  38. astrbot/core/astr_agent_hooks.py +6 -0
  39. astrbot/core/backup/__init__.py +26 -0
  40. astrbot/core/backup/constants.py +77 -0
  41. astrbot/core/backup/exporter.py +477 -0
  42. astrbot/core/backup/importer.py +761 -0
  43. astrbot/core/config/astrbot_config.py +2 -0
  44. astrbot/core/config/default.py +47 -6
  45. astrbot/core/knowledge_base/chunking/recursive.py +10 -2
  46. astrbot/core/log.py +1 -1
  47. astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py +184 -174
  48. astrbot/core/pipeline/result_decorate/stage.py +65 -57
  49. astrbot/core/pipeline/waking_check/stage.py +31 -3
  50. astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +15 -29
  51. astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py +1 -6
  52. astrbot/core/platform/sources/dingtalk/dingtalk_event.py +15 -1
  53. astrbot/core/platform/sources/lark/lark_adapter.py +2 -10
  54. astrbot/core/platform/sources/misskey/misskey_adapter.py +0 -5
  55. astrbot/core/platform/sources/misskey/misskey_utils.py +0 -3
  56. astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py +4 -9
  57. astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py +4 -9
  58. astrbot/core/platform/sources/satori/satori_adapter.py +6 -1
  59. astrbot/core/platform/sources/slack/slack_adapter.py +3 -6
  60. astrbot/core/platform/sources/webchat/webchat_adapter.py +0 -1
  61. astrbot/core/platform/sources/wechatpadpro/wechatpadpro_adapter.py +3 -5
  62. astrbot/core/provider/entities.py +41 -10
  63. astrbot/core/provider/provider.py +3 -1
  64. astrbot/core/provider/sources/anthropic_source.py +140 -30
  65. astrbot/core/provider/sources/fishaudio_tts_api_source.py +14 -6
  66. astrbot/core/provider/sources/gemini_source.py +112 -29
  67. astrbot/core/provider/sources/minimax_tts_api_source.py +4 -1
  68. astrbot/core/provider/sources/openai_source.py +93 -56
  69. astrbot/core/provider/sources/xai_source.py +29 -0
  70. astrbot/core/provider/sources/xinference_stt_provider.py +24 -12
  71. astrbot/core/star/context.py +1 -1
  72. astrbot/core/star/star_manager.py +52 -13
  73. astrbot/core/utils/astrbot_path.py +34 -0
  74. astrbot/core/utils/pip_installer.py +20 -1
  75. astrbot/dashboard/routes/__init__.py +2 -0
  76. astrbot/dashboard/routes/backup.py +1093 -0
  77. astrbot/dashboard/routes/config.py +45 -0
  78. astrbot/dashboard/routes/log.py +44 -10
  79. astrbot/dashboard/server.py +9 -1
  80. {astrbot-4.10.2.dist-info → astrbot-4.10.4.dist-info}/METADATA +1 -1
  81. {astrbot-4.10.2.dist-info → astrbot-4.10.4.dist-info}/RECORD +84 -44
  82. {astrbot-4.10.2.dist-info → astrbot-4.10.4.dist-info}/WHEEL +0 -0
  83. {astrbot-4.10.2.dist-info → astrbot-4.10.4.dist-info}/entry_points.txt +0 -0
  84. {astrbot-4.10.2.dist-info → astrbot-4.10.4.dist-info}/licenses/LICENSE +0 -0
@@ -98,6 +98,9 @@ class ResultDecorateStage(Stage):
98
98
  self.content_safe_check_stage = stage_cls()
99
99
  await self.content_safe_check_stage.initialize(ctx)
100
100
 
101
+ provider_cfg = ctx.astrbot_config.get("provider_settings", {})
102
+ self.show_reasoning = provider_cfg.get("display_reasoning_text", False)
103
+
101
104
  def _split_text_by_words(self, text: str) -> list[str]:
102
105
  """使用分段词列表分段文本"""
103
106
  if not self.split_words_pattern:
@@ -254,70 +257,75 @@ class ResultDecorateStage(Stage):
254
257
  event.unified_msg_origin,
255
258
  )
256
259
 
257
- if (
258
- self.ctx.astrbot_config["provider_tts_settings"]["enable"]
260
+ should_tts = (
261
+ bool(self.ctx.astrbot_config["provider_tts_settings"]["enable"])
259
262
  and result.is_llm_result()
260
263
  and SessionServiceManager.should_process_tts_request(event)
261
- ):
262
- should_tts = self.tts_trigger_probability >= 1.0 or (
263
- self.tts_trigger_probability > 0.0
264
- and random.random() <= self.tts_trigger_probability
264
+ and random.random() <= self.tts_trigger_probability
265
+ and tts_provider
266
+ )
267
+ if should_tts and not tts_provider:
268
+ logger.warning(
269
+ f"会话 {event.unified_msg_origin} 未配置文本转语音模型。",
265
270
  )
266
271
 
267
- if not should_tts:
268
- logger.debug("跳过 TTS:触发概率未命中。")
269
- elif not tts_provider:
270
- logger.warning(
271
- f"会话 {event.unified_msg_origin} 未配置文本转语音模型。",
272
- )
273
- else:
274
- new_chain = []
275
- for comp in result.chain:
276
- if isinstance(comp, Plain) and len(comp.text) > 1:
277
- try:
278
- logger.info(f"TTS 请求: {comp.text}")
279
- audio_path = await tts_provider.get_audio(comp.text)
280
- logger.info(f"TTS 结果: {audio_path}")
281
- if not audio_path:
282
- logger.error(
283
- f"由于 TTS 音频文件未找到,消息段转语音失败: {comp.text}",
284
- )
285
- new_chain.append(comp)
286
- continue
287
-
288
- use_file_service = self.ctx.astrbot_config[
289
- "provider_tts_settings"
290
- ]["use_file_service"]
291
- callback_api_base = self.ctx.astrbot_config[
292
- "callback_api_base"
293
- ]
294
- dual_output = self.ctx.astrbot_config[
295
- "provider_tts_settings"
296
- ]["dual_output"]
297
-
298
- url = None
299
- if use_file_service and callback_api_base:
300
- token = await file_token_service.register_file(
301
- audio_path,
302
- )
303
- url = f"{callback_api_base}/api/file/{token}"
304
- logger.debug(f"已注册:{url}")
305
-
306
- new_chain.append(
307
- Record(
308
- file=url or audio_path,
309
- url=url or audio_path,
310
- ),
272
+ if (
273
+ not should_tts
274
+ and self.show_reasoning
275
+ and event.get_extra("_llm_reasoning_content")
276
+ ):
277
+ # inject reasoning content to chain
278
+ reasoning_content = event.get_extra("_llm_reasoning_content")
279
+ result.chain.insert(0, Plain(f"🤔 思考: {reasoning_content}\n"))
280
+
281
+ if should_tts and tts_provider:
282
+ new_chain = []
283
+ for comp in result.chain:
284
+ if isinstance(comp, Plain) and len(comp.text) > 1:
285
+ try:
286
+ logger.info(f"TTS 请求: {comp.text}")
287
+ audio_path = await tts_provider.get_audio(comp.text)
288
+ logger.info(f"TTS 结果: {audio_path}")
289
+ if not audio_path:
290
+ logger.error(
291
+ f"由于 TTS 音频文件未找到,消息段转语音失败: {comp.text}",
311
292
  )
312
- if dual_output:
313
- new_chain.append(comp)
314
- except Exception:
315
- logger.error(traceback.format_exc())
316
- logger.error("TTS 失败,使用文本发送。")
317
293
  new_chain.append(comp)
318
- else:
294
+ continue
295
+
296
+ use_file_service = self.ctx.astrbot_config[
297
+ "provider_tts_settings"
298
+ ]["use_file_service"]
299
+ callback_api_base = self.ctx.astrbot_config[
300
+ "callback_api_base"
301
+ ]
302
+ dual_output = self.ctx.astrbot_config[
303
+ "provider_tts_settings"
304
+ ]["dual_output"]
305
+
306
+ url = None
307
+ if use_file_service and callback_api_base:
308
+ token = await file_token_service.register_file(
309
+ audio_path,
310
+ )
311
+ url = f"{callback_api_base}/api/file/{token}"
312
+ logger.debug(f"已注册:{url}")
313
+
314
+ new_chain.append(
315
+ Record(
316
+ file=url or audio_path,
317
+ url=url or audio_path,
318
+ ),
319
+ )
320
+ if dual_output:
321
+ new_chain.append(comp)
322
+ except Exception:
323
+ logger.error(traceback.format_exc())
324
+ logger.error("TTS 失败,使用文本发送。")
319
325
  new_chain.append(comp)
320
- result.chain = new_chain
326
+ else:
327
+ new_chain.append(comp)
328
+ result.chain = new_chain
321
329
 
322
330
  # 文本转图片
323
331
  elif (
@@ -1,9 +1,10 @@
1
- from collections.abc import AsyncGenerator
1
+ from collections.abc import AsyncGenerator, Callable
2
2
 
3
3
  from astrbot import logger
4
4
  from astrbot.core.message.components import At, AtAll, Reply
5
5
  from astrbot.core.message.message_event_result import MessageChain, MessageEventResult
6
6
  from astrbot.core.platform.astr_message_event import AstrMessageEvent
7
+ from astrbot.core.platform.message_type import MessageType
7
8
  from astrbot.core.star.filter.command_group import CommandGroupFilter
8
9
  from astrbot.core.star.filter.permission import PermissionTypeFilter
9
10
  from astrbot.core.star.session_plugin_manager import SessionPluginManager
@@ -13,6 +14,23 @@ from astrbot.core.star.star_handler import EventType, star_handlers_registry
13
14
  from ..context import PipelineContext
14
15
  from ..stage import Stage, register_stage
15
16
 
17
+ UNIQUE_SESSION_ID_BUILDERS: dict[str, Callable[[AstrMessageEvent], str | None]] = {
18
+ "aiocqhttp": lambda e: f"{e.get_sender_id()}_{e.get_group_id()}",
19
+ "slack": lambda e: f"{e.get_sender_id()}_{e.get_group_id()}",
20
+ "dingtalk": lambda e: e.get_sender_id(),
21
+ "qq_official": lambda e: e.get_sender_id(),
22
+ "qq_official_webhook": lambda e: e.get_sender_id(),
23
+ "lark": lambda e: f"{e.get_sender_id()}%{e.get_group_id()}",
24
+ "misskey": lambda e: f"{e.get_session_id()}_{e.get_sender_id()}",
25
+ "wechatpadpro": lambda e: f"{e.get_group_id()}#{e.get_sender_id()}",
26
+ }
27
+
28
+
29
+ def build_unique_session_id(event: AstrMessageEvent) -> str | None:
30
+ platform = event.get_platform_name()
31
+ builder = UNIQUE_SESSION_ID_BUILDERS.get(platform)
32
+ return builder(event) if builder else None
33
+
16
34
 
17
35
  @register_stage
18
36
  class WakingCheckStage(Stage):
@@ -53,18 +71,27 @@ class WakingCheckStage(Stage):
53
71
  self.disable_builtin_commands = self.ctx.astrbot_config.get(
54
72
  "disable_builtin_commands", False
55
73
  )
74
+ platform_settings = self.ctx.astrbot_config.get("platform_settings", {})
75
+ self.unique_session = platform_settings.get("unique_session", False)
56
76
 
57
77
  async def process(
58
78
  self,
59
79
  event: AstrMessageEvent,
60
80
  ) -> None | AsyncGenerator[None, None]:
81
+ # apply unique session
82
+ if self.unique_session and event.message_obj.type == MessageType.GROUP_MESSAGE:
83
+ sid = build_unique_session_id(event)
84
+ if sid:
85
+ event.session_id = sid
86
+
87
+ # ignore bot self message
61
88
  if (
62
89
  self.ignore_bot_self_message
63
90
  and event.get_self_id() == event.get_sender_id()
64
91
  ):
65
- # 忽略机器人自己发送的消息
66
92
  event.stop_event()
67
93
  return
94
+
68
95
  # 设置 sender 身份
69
96
  event.message_str = event.message_str.strip()
70
97
  for admin_id in self.ctx.astrbot_config["admins_id"]:
@@ -136,7 +163,8 @@ class WakingCheckStage(Stage):
136
163
  ):
137
164
  if (
138
165
  self.disable_builtin_commands
139
- and handler.handler_module_path == "packages.builtin_commands.main"
166
+ and handler.handler_module_path
167
+ == "astrbot.builtin_stars.builtin_commands.main"
140
168
  ):
141
169
  logger.debug("skipping builtin command")
142
170
  continue
@@ -41,7 +41,6 @@ class AiocqhttpAdapter(Platform):
41
41
  super().__init__(platform_config, event_queue)
42
42
 
43
43
  self.settings = platform_settings
44
- self.unique_session = platform_settings["unique_session"]
45
44
  self.host = platform_config["ws_reverse_host"]
46
45
  self.port = platform_config["ws_reverse_port"]
47
46
 
@@ -136,14 +135,11 @@ class AiocqhttpAdapter(Platform):
136
135
  abm.group_id = str(event.group_id)
137
136
  else:
138
137
  abm.type = MessageType.FRIEND_MESSAGE
139
- if self.unique_session and abm.type == MessageType.GROUP_MESSAGE:
140
- abm.session_id = str(abm.sender.user_id) + "_" + str(event.group_id)
141
- else:
142
- abm.session_id = (
143
- str(event.group_id)
144
- if abm.type == MessageType.GROUP_MESSAGE
145
- else abm.sender.user_id
146
- )
138
+ abm.session_id = (
139
+ str(event.group_id)
140
+ if abm.type == MessageType.GROUP_MESSAGE
141
+ else abm.sender.user_id
142
+ )
147
143
  abm.message_str = ""
148
144
  abm.message = []
149
145
  abm.timestamp = int(time.time())
@@ -164,16 +160,11 @@ class AiocqhttpAdapter(Platform):
164
160
  abm.type = MessageType.GROUP_MESSAGE
165
161
  else:
166
162
  abm.type = MessageType.FRIEND_MESSAGE
167
- if self.unique_session and abm.type == MessageType.GROUP_MESSAGE:
168
- abm.session_id = (
169
- str(abm.sender.user_id) + "_" + str(event.group_id)
170
- ) # 也保留群组 id
171
- else:
172
- abm.session_id = (
173
- str(event.group_id)
174
- if abm.type == MessageType.GROUP_MESSAGE
175
- else abm.sender.user_id
176
- )
163
+ abm.session_id = (
164
+ str(event.group_id)
165
+ if abm.type == MessageType.GROUP_MESSAGE
166
+ else abm.sender.user_id
167
+ )
177
168
  abm.message_str = ""
178
169
  abm.message = []
179
170
  abm.raw_message = event
@@ -210,16 +201,11 @@ class AiocqhttpAdapter(Platform):
210
201
  abm.group.group_name = event.get("group_name", "N/A")
211
202
  elif event["message_type"] == "private":
212
203
  abm.type = MessageType.FRIEND_MESSAGE
213
- if self.unique_session and abm.type == MessageType.GROUP_MESSAGE:
214
- abm.session_id = (
215
- abm.sender.user_id + "_" + str(event.group_id)
216
- ) # 也保留群组 id
217
- else:
218
- abm.session_id = (
219
- str(event.group_id)
220
- if abm.type == MessageType.GROUP_MESSAGE
221
- else abm.sender.user_id
222
- )
204
+ abm.session_id = (
205
+ str(event.group_id)
206
+ if abm.type == MessageType.GROUP_MESSAGE
207
+ else abm.sender.user_id
208
+ )
223
209
 
224
210
  abm.message_id = str(event.message_id)
225
211
  abm.message = []
@@ -50,8 +50,6 @@ class DingtalkPlatformAdapter(Platform):
50
50
  ) -> None:
51
51
  super().__init__(platform_config, event_queue)
52
52
 
53
- self.unique_session = platform_settings["unique_session"]
54
-
55
53
  self.client_id = platform_config["client_id"]
56
54
  self.client_secret = platform_config["client_secret"]
57
55
 
@@ -129,10 +127,7 @@ class DingtalkPlatformAdapter(Platform):
129
127
  if id := self._id_to_sid(user.dingtalk_id):
130
128
  abm.message.append(At(qq=id))
131
129
  abm.group_id = message.conversation_id
132
- if self.unique_session:
133
- abm.session_id = abm.sender.user_id
134
- else:
135
- abm.session_id = abm.group_id
130
+ abm.session_id = abm.group_id
136
131
  else:
137
132
  abm.session_id = abm.sender.user_id
138
133
 
@@ -25,6 +25,20 @@ class DingtalkMessageEvent(AstrMessageEvent):
25
25
  client: dingtalk_stream.ChatbotHandler,
26
26
  message: MessageChain,
27
27
  ):
28
+ icm = cast(dingtalk_stream.ChatbotMessage, self.message_obj.raw_message)
29
+ ats = []
30
+ # fixes: #4218
31
+ # 钉钉 at 机器人需要使用 sender_staff_id 而不是 sender_id
32
+ for i in message.chain:
33
+ if isinstance(i, Comp.At):
34
+ print(i.qq, icm.sender_id, icm.sender_staff_id)
35
+ if str(i.qq) in str(icm.sender_id or ""):
36
+ # 适配器会将开头的 $:LWCP_v1:$ 去掉,因此我们用 in 判断
37
+ ats.append(f"@{icm.sender_staff_id}")
38
+ else:
39
+ ats.append(f"@{i.qq}")
40
+ at_str = " ".join(ats)
41
+
28
42
  for segment in message.chain:
29
43
  if isinstance(segment, Comp.Plain):
30
44
  segment.text = segment.text.strip()
@@ -32,7 +46,7 @@ class DingtalkMessageEvent(AstrMessageEvent):
32
46
  None,
33
47
  client.reply_markdown,
34
48
  segment.text,
35
- segment.text,
49
+ f"{at_str} {segment.text}".strip(),
36
50
  cast(dingtalk_stream.ChatbotMessage, self.message_obj.raw_message),
37
51
  )
38
52
  elif isinstance(segment, Comp.Image):
@@ -44,8 +44,6 @@ class LarkPlatformAdapter(Platform):
44
44
  ) -> None:
45
45
  super().__init__(platform_config, event_queue)
46
46
 
47
- self.unique_session = platform_settings["unique_session"]
48
-
49
47
  self.appid = platform_config["app_id"]
50
48
  self.appsecret = platform_config["app_secret"]
51
49
  self.domain = platform_config.get("domain", lark.FEISHU_DOMAIN)
@@ -317,14 +315,8 @@ class LarkPlatformAdapter(Platform):
317
315
  user_id=event.event.sender.sender_id.open_id,
318
316
  nickname=event.event.sender.sender_id.open_id[:8],
319
317
  )
320
- # 独立会话
321
- if not self.unique_session:
322
- if abm.type == MessageType.GROUP_MESSAGE:
323
- abm.session_id = abm.group_id
324
- else:
325
- abm.session_id = abm.sender.user_id
326
- elif abm.type == MessageType.GROUP_MESSAGE:
327
- abm.session_id = f"{abm.sender.user_id}%{abm.group_id}" # 也保留群组id
318
+ if abm.type == MessageType.GROUP_MESSAGE:
319
+ abm.session_id = abm.group_id
328
320
  else:
329
321
  abm.session_id = abm.sender.user_id
330
322
 
@@ -91,8 +91,6 @@ class MisskeyPlatformAdapter(Platform):
91
91
  except Exception:
92
92
  self.max_download_bytes = None
93
93
 
94
- self.unique_session = platform_settings["unique_session"]
95
-
96
94
  self.api: MisskeyAPI | None = None
97
95
  self._running = False
98
96
  self.client_self_id = ""
@@ -641,7 +639,6 @@ class MisskeyPlatformAdapter(Platform):
641
639
  sender_info,
642
640
  self.client_self_id,
643
641
  is_chat=False,
644
- unique_session=self.unique_session,
645
642
  )
646
643
  cache_user_info(
647
644
  self._user_cache,
@@ -690,7 +687,6 @@ class MisskeyPlatformAdapter(Platform):
690
687
  sender_info,
691
688
  self.client_self_id,
692
689
  is_chat=True,
693
- unique_session=self.unique_session,
694
690
  )
695
691
  cache_user_info(
696
692
  self._user_cache,
@@ -720,7 +716,6 @@ class MisskeyPlatformAdapter(Platform):
720
716
  self.client_self_id,
721
717
  is_chat=False,
722
718
  room_id=room_id,
723
- unique_session=self.unique_session,
724
719
  )
725
720
 
726
721
  cache_user_info(
@@ -338,7 +338,6 @@ def create_base_message(
338
338
  client_self_id: str,
339
339
  is_chat: bool = False,
340
340
  room_id: str | None = None,
341
- unique_session: bool = False,
342
341
  ) -> AstrBotMessage:
343
342
  """创建基础消息对象"""
344
343
  message = AstrBotMessage()
@@ -353,8 +352,6 @@ def create_base_message(
353
352
  if room_id:
354
353
  session_prefix = "room"
355
354
  session_id = f"{session_prefix}%{room_id}"
356
- if unique_session:
357
- session_id += f"_{sender_info['sender_id']}"
358
355
  message.type = MessageType.GROUP_MESSAGE
359
356
  message.group_id = room_id
360
357
  elif is_chat:
@@ -44,11 +44,8 @@ class botClient(Client):
44
44
  message,
45
45
  MessageType.GROUP_MESSAGE,
46
46
  )
47
- abm.session_id = (
48
- abm.sender.user_id
49
- if self.platform.unique_session
50
- else cast(str, message.group_openid)
51
- )
47
+ abm.group_id = cast(str, message.group_openid)
48
+ abm.session_id = abm.group_id
52
49
  self._commit(abm)
53
50
 
54
51
  # 收到频道消息
@@ -57,9 +54,8 @@ class botClient(Client):
57
54
  message,
58
55
  MessageType.GROUP_MESSAGE,
59
56
  )
60
- abm.session_id = (
61
- abm.sender.user_id if self.platform.unique_session else message.channel_id
62
- )
57
+ abm.group_id = message.channel_id
58
+ abm.session_id = abm.group_id
63
59
  self._commit(abm)
64
60
 
65
61
  # 收到私聊消息
@@ -104,7 +100,6 @@ class QQOfficialPlatformAdapter(Platform):
104
100
 
105
101
  self.appid = platform_config["appid"]
106
102
  self.secret = platform_config["secret"]
107
- self.unique_session: bool = platform_settings["unique_session"]
108
103
  qq_group = platform_config["enable_group_c2c"]
109
104
  guild_dm = platform_config["enable_guild_direct_message"]
110
105
 
@@ -35,11 +35,8 @@ class botClient(Client):
35
35
  message,
36
36
  MessageType.GROUP_MESSAGE,
37
37
  )
38
- abm.session_id = (
39
- abm.sender.user_id
40
- if self.platform.unique_session
41
- else cast(str, message.group_openid)
42
- )
38
+ abm.group_id = cast(str, message.group_openid)
39
+ abm.session_id = abm.group_id
43
40
  self._commit(abm)
44
41
 
45
42
  # 收到频道消息
@@ -48,9 +45,8 @@ class botClient(Client):
48
45
  message,
49
46
  MessageType.GROUP_MESSAGE,
50
47
  )
51
- abm.session_id = (
52
- abm.sender.user_id if self.platform.unique_session else message.channel_id
53
- )
48
+ abm.group_id = message.channel_id
49
+ abm.session_id = abm.group_id
54
50
  self._commit(abm)
55
51
 
56
52
  # 收到私聊消息
@@ -95,7 +91,6 @@ class QQOfficialWebhookPlatformAdapter(Platform):
95
91
 
96
92
  self.appid = platform_config["appid"]
97
93
  self.secret = platform_config["secret"]
98
- self.unique_session = platform_settings["unique_session"]
99
94
  self.unified_webhook_mode = platform_config.get("unified_webhook_mode", False)
100
95
 
101
96
  intents = botpy.Intents(
@@ -142,7 +142,12 @@ class SatoriPlatformAdapter(Platform):
142
142
  raise ValueError(f"WebSocket URL必须以ws://或wss://开头: {self.endpoint}")
143
143
 
144
144
  try:
145
- websocket = await connect(self.endpoint, additional_headers={})
145
+ websocket = await connect(
146
+ self.endpoint,
147
+ additional_headers={},
148
+ max_size=10 * 1024 * 1024, # 10MB
149
+ )
150
+
146
151
  self.ws = websocket
147
152
 
148
153
  await asyncio.sleep(0.1)
@@ -41,7 +41,6 @@ class SlackAdapter(Platform):
41
41
  ) -> None:
42
42
  super().__init__(platform_config, event_queue)
43
43
  self.settings = platform_settings
44
- self.unique_session = platform_settings.get("unique_session", False)
45
44
 
46
45
  self.bot_token = platform_config.get("bot_token")
47
46
  self.app_token = platform_config.get("app_token")
@@ -147,12 +146,10 @@ class SlackAdapter(Platform):
147
146
  abm.group_id = channel_id
148
147
 
149
148
  # 设置会话ID
150
- if self.unique_session and abm.type == MessageType.GROUP_MESSAGE:
151
- abm.session_id = f"{user_id}_{channel_id}"
149
+ if abm.type == MessageType.GROUP_MESSAGE:
150
+ abm.session_id = abm.group_id
152
151
  else:
153
- abm.session_id = (
154
- channel_id if abm.type == MessageType.GROUP_MESSAGE else user_id
155
- )
152
+ abm.session_id = user_id
156
153
 
157
154
  abm.message_id = event.get("client_msg_id", uuid.uuid4().hex)
158
155
  abm.timestamp = int(float(event.get("ts", time.time())))
@@ -79,7 +79,6 @@ class WebChatAdapter(Platform):
79
79
  super().__init__(platform_config, event_queue)
80
80
 
81
81
  self.settings = platform_settings
82
- self.unique_session = platform_settings["unique_session"]
83
82
  self.imgs_dir = os.path.join(get_astrbot_data_path(), "webchat", "imgs")
84
83
  os.makedirs(self.imgs_dir, exist_ok=True)
85
84
 
@@ -47,7 +47,6 @@ class WeChatPadProAdapter(Platform):
47
47
  self._shutdown_event = None
48
48
  self.wxnewpass = None
49
49
  self.settings = platform_settings
50
- self.unique_session = platform_settings.get("unique_session", False)
51
50
 
52
51
  self.metadata = PlatformMetadata(
53
52
  name="wechatpadpro",
@@ -509,11 +508,10 @@ class WeChatPadProAdapter(Platform):
509
508
  if accurate_nickname:
510
509
  abm.sender.nickname = accurate_nickname
511
510
 
512
- # 对于群聊,session_id 可以是群聊 ID 或发送者 ID + 群聊 ID (如果 unique_session 为 True)
513
- if self.unique_session:
514
- abm.session_id = f"{from_user_name}#{abm.sender.user_id}"
511
+ if abm.type == MessageType.GROUP_MESSAGE:
512
+ abm.session_id = abm.group_id
515
513
  else:
516
- abm.session_id = from_user_name
514
+ abm.session_id = abm.sender.user_id
517
515
 
518
516
  msg_source = raw_message.get("msg_source", "")
519
517
  if self.wxid in msg_source: