AstrBot 4.3.2__py3-none-any.whl → 4.3.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.
@@ -6,7 +6,7 @@ import os
6
6
 
7
7
  from astrbot.core.utils.astrbot_path import get_astrbot_data_path
8
8
 
9
- VERSION = "4.3.2"
9
+ VERSION = "4.3.3"
10
10
  DB_PATH = os.path.join(get_astrbot_data_path(), "data_v4.db")
11
11
 
12
12
  # 默认配置
@@ -775,7 +775,7 @@ CONFIG_METADATA_2 = {
775
775
  "timeout": 120,
776
776
  "model_config": {"model": "deepseek-chat", "temperature": 0.4},
777
777
  "custom_extra_body": {},
778
- "modalities": ["text", "image", "tool_use"],
778
+ "modalities": ["text", "tool_use"],
779
779
  },
780
780
  "302.AI": {
781
781
  "id": "302ai",
@@ -821,6 +821,21 @@ CONFIG_METADATA_2 = {
821
821
  },
822
822
  "custom_extra_body": {},
823
823
  },
824
+ "小马算力": {
825
+ "id": "tokenpony",
826
+ "provider": "tokenpony",
827
+ "type": "openai_chat_completion",
828
+ "provider_type": "chat_completion",
829
+ "enable": True,
830
+ "key": [],
831
+ "api_base": "https://api.tokenpony.cn/v1",
832
+ "timeout": 120,
833
+ "model_config": {
834
+ "model": "kimi-k2-instruct-0905",
835
+ "temperature": 0.7,
836
+ },
837
+ "custom_extra_body": {},
838
+ },
824
839
  "优云智算": {
825
840
  "id": "compshare",
826
841
  "provider": "compshare",
@@ -1041,6 +1056,7 @@ CONFIG_METADATA_2 = {
1041
1056
  "timeout": "20",
1042
1057
  },
1043
1058
  "阿里云百炼 TTS(API)": {
1059
+ "hint": "API Key 从 https://bailian.console.aliyun.com/?tab=model#/api-key 获取。模型和音色的选择文档请参考: 阿里云百炼语音合成音色名称。具体可参考 https://help.aliyun.com/zh/model-studio/speech-synthesis-and-speech-recognition",
1044
1060
  "id": "dashscope_tts",
1045
1061
  "provider": "dashscope",
1046
1062
  "type": "dashscope_tts",
@@ -1420,11 +1436,7 @@ CONFIG_METADATA_2 = {
1420
1436
  "description": "服务订阅密钥",
1421
1437
  "hint": "Azure_TTS 服务的订阅密钥(注意不是令牌)",
1422
1438
  },
1423
- "dashscope_tts_voice": {
1424
- "description": "语音合成模型",
1425
- "type": "string",
1426
- "hint": "阿里云百炼语音合成模型名称。具体可参考 https://help.aliyun.com/zh/model-studio/developer-reference/cosyvoice-python-api 等内容",
1427
- },
1439
+ "dashscope_tts_voice": {"description": "音色", "type": "string"},
1428
1440
  "gm_resp_image_modal": {
1429
1441
  "description": "启用图片模态",
1430
1442
  "type": "bool",
astrbot/core/db/sqlite.py CHANGED
@@ -32,6 +32,12 @@ class SQLiteDatabase(BaseDatabase):
32
32
  """Initialize the database by creating tables if they do not exist."""
33
33
  async with self.engine.begin() as conn:
34
34
  await conn.run_sync(SQLModel.metadata.create_all)
35
+ await conn.execute(text("PRAGMA journal_mode=WAL"))
36
+ await conn.execute(text("PRAGMA synchronous=NORMAL"))
37
+ await conn.execute(text("PRAGMA cache_size=20000"))
38
+ await conn.execute(text("PRAGMA temp_store=MEMORY"))
39
+ await conn.execute(text("PRAGMA mmap_size=134217728"))
40
+ await conn.execute(text("PRAGMA optimize"))
35
41
  await conn.commit()
36
42
 
37
43
  # ====
@@ -160,6 +166,7 @@ class SQLiteDatabase(BaseDatabase):
160
166
  col(ConversationV2.title).ilike(f"%{search_query}%"),
161
167
  col(ConversationV2.content).ilike(f"%{search_query}%"),
162
168
  col(ConversationV2.user_id).ilike(f"%{search_query}%"),
169
+ col(ConversationV2.conversation_id).ilike(f"%{search_query}%"),
163
170
  )
164
171
  )
165
172
  if "message_types" in kwargs and len(kwargs["message_types"]) > 0:
@@ -97,5 +97,6 @@ async def call_event_hook(
97
97
  logger.info(
98
98
  f"{star_map[handler.handler_module_path].name} - {handler.handler_name} 终止了事件传播。"
99
99
  )
100
+ return True
100
101
 
101
102
  return event.is_stopped()
@@ -189,54 +189,54 @@ class ResultDecorateStage(Stage):
189
189
  logger.warning(
190
190
  f"会话 {event.unified_msg_origin} 未配置文本转语音模型。"
191
191
  )
192
- return
193
- new_chain = []
194
- for comp in result.chain:
195
- if isinstance(comp, Plain) and len(comp.text) > 1:
196
- try:
197
- logger.info(f"TTS 请求: {comp.text}")
198
- audio_path = await tts_provider.get_audio(comp.text)
199
- logger.info(f"TTS 结果: {audio_path}")
200
- if not audio_path:
201
- logger.error(
202
- f"由于 TTS 音频文件未找到,消息段转语音失败: {comp.text}"
203
- )
204
- new_chain.append(comp)
205
- continue
192
+ else:
193
+ new_chain = []
194
+ for comp in result.chain:
195
+ if isinstance(comp, Plain) and len(comp.text) > 1:
196
+ try:
197
+ logger.info(f"TTS 请求: {comp.text}")
198
+ audio_path = await tts_provider.get_audio(comp.text)
199
+ logger.info(f"TTS 结果: {audio_path}")
200
+ if not audio_path:
201
+ logger.error(
202
+ f"由于 TTS 音频文件未找到,消息段转语音失败: {comp.text}"
203
+ )
204
+ new_chain.append(comp)
205
+ continue
206
206
 
207
- use_file_service = self.ctx.astrbot_config[
208
- "provider_tts_settings"
209
- ]["use_file_service"]
210
- callback_api_base = self.ctx.astrbot_config[
211
- "callback_api_base"
212
- ]
213
- dual_output = self.ctx.astrbot_config[
214
- "provider_tts_settings"
215
- ]["dual_output"]
207
+ use_file_service = self.ctx.astrbot_config[
208
+ "provider_tts_settings"
209
+ ]["use_file_service"]
210
+ callback_api_base = self.ctx.astrbot_config[
211
+ "callback_api_base"
212
+ ]
213
+ dual_output = self.ctx.astrbot_config[
214
+ "provider_tts_settings"
215
+ ]["dual_output"]
216
216
 
217
- url = None
218
- if use_file_service and callback_api_base:
219
- token = await file_token_service.register_file(
220
- audio_path
221
- )
222
- url = f"{callback_api_base}/api/file/{token}"
223
- logger.debug(f"已注册:{url}")
217
+ url = None
218
+ if use_file_service and callback_api_base:
219
+ token = await file_token_service.register_file(
220
+ audio_path
221
+ )
222
+ url = f"{callback_api_base}/api/file/{token}"
223
+ logger.debug(f"已注册:{url}")
224
224
 
225
- new_chain.append(
226
- Record(
227
- file=url or audio_path,
228
- url=url or audio_path,
225
+ new_chain.append(
226
+ Record(
227
+ file=url or audio_path,
228
+ url=url or audio_path,
229
+ )
229
230
  )
230
- )
231
- if dual_output:
231
+ if dual_output:
232
+ new_chain.append(comp)
233
+ except Exception:
234
+ logger.error(traceback.format_exc())
235
+ logger.error("TTS 失败,使用文本发送。")
232
236
  new_chain.append(comp)
233
- except Exception:
234
- logger.error(traceback.format_exc())
235
- logger.error("TTS 失败,使用文本发送。")
237
+ else:
236
238
  new_chain.append(comp)
237
- else:
238
- new_chain.append(comp)
239
- result.chain = new_chain
239
+ result.chain = new_chain
240
240
 
241
241
  # 文本转图片
242
242
  elif (
@@ -279,7 +279,6 @@ class ResultDecorateStage(Stage):
279
279
  result.chain = [Image.fromFileSystem(url)]
280
280
 
281
281
  # 触发转发消息
282
- has_forwarded = False
283
282
  if event.get_platform_name() == "aiocqhttp":
284
283
  word_cnt = 0
285
284
  for comp in result.chain:
@@ -290,9 +289,9 @@ class ResultDecorateStage(Stage):
290
289
  uin=event.get_self_id(), name="AstrBot", content=[*result.chain]
291
290
  )
292
291
  result.chain = [node]
293
- has_forwarded = True
294
292
 
295
- if not has_forwarded:
293
+ has_plain = any(isinstance(item, Plain) for item in result.chain)
294
+ if has_plain:
296
295
  # at 回复
297
296
  if (
298
297
  self.reply_with_mention
@@ -68,7 +68,8 @@ class Provider(AbstractProvider):
68
68
 
69
69
  def get_keys(self) -> List[str]:
70
70
  """获得提供商 Key"""
71
- return self.provider_config.get("key", [])
71
+ keys = self.provider_config.get("key", [""])
72
+ return keys or [""]
72
73
 
73
74
  @abc.abstractmethod
74
75
  def set_key(self, key: str):
@@ -33,7 +33,7 @@ class ProviderAnthropic(Provider):
33
33
  )
34
34
 
35
35
  self.chosen_api_key: str = ""
36
- self.api_keys: List = provider_config.get("key", [])
36
+ self.api_keys: List = super().get_keys()
37
37
  self.chosen_api_key = self.api_keys[0] if len(self.api_keys) > 0 else ""
38
38
  self.base_url = provider_config.get("api_base", "https://api.anthropic.com")
39
39
  self.timeout = provider_config.get("timeout", 120)
@@ -70,9 +70,13 @@ class ProviderAnthropic(Provider):
70
70
  {
71
71
  "type": "tool_use",
72
72
  "name": tool_call["function"]["name"],
73
- "input": json.loads(tool_call["function"]["arguments"])
74
- if isinstance(tool_call["function"]["arguments"], str)
75
- else tool_call["function"]["arguments"],
73
+ "input": (
74
+ json.loads(tool_call["function"]["arguments"])
75
+ if isinstance(
76
+ tool_call["function"]["arguments"], str
77
+ )
78
+ else tool_call["function"]["arguments"]
79
+ ),
76
80
  "id": tool_call["id"],
77
81
  }
78
82
  )
@@ -355,9 +359,11 @@ class ProviderAnthropic(Provider):
355
359
  "source": {
356
360
  "type": "base64",
357
361
  "media_type": mime_type,
358
- "data": image_data.split("base64,")[1]
359
- if "base64," in image_data
360
- else image_data,
362
+ "data": (
363
+ image_data.split("base64,")[1]
364
+ if "base64," in image_data
365
+ else image_data
366
+ ),
361
367
  },
362
368
  }
363
369
  )
@@ -1,10 +1,22 @@
1
+ import asyncio
2
+ import base64
3
+ import logging
1
4
  import os
2
- import dashscope
3
5
  import uuid
4
- import asyncio
5
- from dashscope.audio.tts_v2 import *
6
- from ..provider import TTSProvider
6
+ from typing import Optional, Tuple
7
+ import aiohttp
8
+ import dashscope
9
+ from dashscope.audio.tts_v2 import AudioFormat, SpeechSynthesizer
10
+
11
+ try:
12
+ from dashscope.aigc.multimodal_conversation import MultiModalConversation
13
+ except (
14
+ ImportError
15
+ ): # pragma: no cover - older dashscope versions without Qwen TTS support
16
+ MultiModalConversation = None
17
+
7
18
  from ..entities import ProviderType
19
+ from ..provider import TTSProvider
8
20
  from ..register import register_provider_adapter
9
21
  from astrbot.core.utils.astrbot_path import get_astrbot_data_path
10
22
 
@@ -26,16 +38,112 @@ class ProviderDashscopeTTSAPI(TTSProvider):
26
38
  dashscope.api_key = self.chosen_api_key
27
39
 
28
40
  async def get_audio(self, text: str) -> str:
41
+ model = self.get_model()
42
+ if not model:
43
+ raise RuntimeError("Dashscope TTS model is not configured.")
44
+
29
45
  temp_dir = os.path.join(get_astrbot_data_path(), "temp")
30
- path = os.path.join(temp_dir, f"dashscope_tts_{uuid.uuid4()}.wav")
31
- self.synthesizer = SpeechSynthesizer(
32
- model=self.get_model(),
46
+ os.makedirs(temp_dir, exist_ok=True)
47
+
48
+ if self._is_qwen_tts_model(model):
49
+ audio_bytes, ext = await self._synthesize_with_qwen_tts(model, text)
50
+ else:
51
+ audio_bytes, ext = await self._synthesize_with_cosyvoice(model, text)
52
+
53
+ if not audio_bytes:
54
+ raise RuntimeError(
55
+ "Audio synthesis failed, returned empty content. The model may not be supported or the service is unavailable."
56
+ )
57
+
58
+ path = os.path.join(temp_dir, f"dashscope_tts_{uuid.uuid4()}{ext}")
59
+ with open(path, "wb") as f:
60
+ f.write(audio_bytes)
61
+ return path
62
+
63
+ def _call_qwen_tts(self, model: str, text: str):
64
+ if MultiModalConversation is None:
65
+ raise RuntimeError(
66
+ "dashscope SDK missing MultiModalConversation. Please upgrade the dashscope package to use Qwen TTS models."
67
+ )
68
+
69
+ kwargs = {
70
+ "model": model,
71
+ "text": text,
72
+ "api_key": self.chosen_api_key,
73
+ "voice": self.voice or "Cherry",
74
+ }
75
+ if not self.voice:
76
+ logging.warning(
77
+ "No voice specified for Qwen TTS model, using default 'Cherry'."
78
+ )
79
+ return MultiModalConversation.call(**kwargs)
80
+
81
+ async def _synthesize_with_qwen_tts(
82
+ self, model: str, text: str
83
+ ) -> Tuple[Optional[bytes], str]:
84
+ loop = asyncio.get_event_loop()
85
+ response = await loop.run_in_executor(None, self._call_qwen_tts, model, text)
86
+ audio_bytes = await self._extract_audio_from_response(response)
87
+ if not audio_bytes:
88
+ raise RuntimeError(
89
+ f"Audio synthesis failed for model '{model}'. {response}"
90
+ )
91
+ ext = ".wav"
92
+ return audio_bytes, ext
93
+
94
+ async def _extract_audio_from_response(self, response) -> Optional[bytes]:
95
+ output = getattr(response, "output", None)
96
+ audio_obj = getattr(output, "audio", None) if output is not None else None
97
+ if not audio_obj:
98
+ return None
99
+
100
+ data_b64 = getattr(audio_obj, "data", None)
101
+ if data_b64:
102
+ try:
103
+ return base64.b64decode(data_b64)
104
+ except (ValueError, TypeError):
105
+ logging.error("Failed to decode base64 audio data.")
106
+ return None
107
+
108
+ url = getattr(audio_obj, "url", None)
109
+ if url:
110
+ return await self._download_audio_from_url(url)
111
+ return None
112
+
113
+ async def _download_audio_from_url(self, url: str) -> Optional[bytes]:
114
+ if not url:
115
+ return None
116
+ timeout = max(self.timeout_ms / 1000, 1) if self.timeout_ms else 20
117
+ try:
118
+ async with aiohttp.ClientSession() as session:
119
+ async with session.get(
120
+ url, timeout=aiohttp.ClientTimeout(total=timeout)
121
+ ) as response:
122
+ return await response.read()
123
+ except (aiohttp.ClientError, asyncio.TimeoutError, OSError) as e:
124
+ logging.error(f"Failed to download audio from URL {url}: {e}")
125
+ return None
126
+
127
+ async def _synthesize_with_cosyvoice(
128
+ self, model: str, text: str
129
+ ) -> Tuple[Optional[bytes], str]:
130
+ synthesizer = SpeechSynthesizer(
131
+ model=model,
33
132
  voice=self.voice,
34
133
  format=AudioFormat.WAV_24000HZ_MONO_16BIT,
35
134
  )
36
- audio = await asyncio.get_event_loop().run_in_executor(
37
- None, self.synthesizer.call, text, self.timeout_ms
135
+ loop = asyncio.get_event_loop()
136
+ audio_bytes = await loop.run_in_executor(
137
+ None, synthesizer.call, text, self.timeout_ms
38
138
  )
39
- with open(path, "wb") as f:
40
- f.write(audio)
41
- return path
139
+ if not audio_bytes:
140
+ resp = synthesizer.get_response()
141
+ if resp and isinstance(resp, dict):
142
+ raise RuntimeError(
143
+ f"Audio synthesis failed for model '{model}'. {resp}".strip()
144
+ )
145
+ return audio_bytes, ".wav"
146
+
147
+ def _is_qwen_tts_model(self, model: str) -> bool:
148
+ model_lower = model.lower()
149
+ return "tts" in model_lower and model_lower.startswith("qwen")
@@ -3,7 +3,7 @@ import base64
3
3
  import json
4
4
  import logging
5
5
  import random
6
- from typing import Optional
6
+ from typing import Optional, List
7
7
  from collections.abc import AsyncGenerator
8
8
 
9
9
  from google import genai
@@ -60,7 +60,7 @@ class ProviderGoogleGenAI(Provider):
60
60
  provider_settings,
61
61
  default_persona,
62
62
  )
63
- self.api_keys: list = provider_config.get("key", [])
63
+ self.api_keys: List = super().get_keys()
64
64
  self.chosen_api_key: str = self.api_keys[0] if len(self.api_keys) > 0 else ""
65
65
  self.timeout: int = int(provider_config.get("timeout", 180))
66
66
 
@@ -218,19 +218,21 @@ class ProviderGoogleGenAI(Provider):
218
218
  response_modalities=modalities,
219
219
  tools=tool_list,
220
220
  safety_settings=self.safety_settings if self.safety_settings else None,
221
- thinking_config=types.ThinkingConfig(
222
- thinking_budget=min(
223
- int(
224
- self.provider_config.get("gm_thinking_config", {}).get(
225
- "budget", 0
226
- )
221
+ thinking_config=(
222
+ types.ThinkingConfig(
223
+ thinking_budget=min(
224
+ int(
225
+ self.provider_config.get("gm_thinking_config", {}).get(
226
+ "budget", 0
227
+ )
228
+ ),
229
+ 24576,
227
230
  ),
228
- 24576,
229
- ),
230
- )
231
- if "gemini-2.5-flash" in self.get_model()
232
- and hasattr(types.ThinkingConfig, "thinking_budget")
233
- else None,
231
+ )
232
+ if "gemini-2.5-flash" in self.get_model()
233
+ and hasattr(types.ThinkingConfig, "thinking_budget")
234
+ else None
235
+ ),
234
236
  automatic_function_calling=types.AutomaticFunctionCallingConfig(
235
237
  disable=True
236
238
  ),
@@ -274,9 +276,11 @@ class ProviderGoogleGenAI(Provider):
274
276
  if role == "user":
275
277
  if isinstance(content, list):
276
278
  parts = [
277
- types.Part.from_text(text=item["text"] or " ")
278
- if item["type"] == "text"
279
- else process_image_url(item["image_url"])
279
+ (
280
+ types.Part.from_text(text=item["text"] or " ")
281
+ if item["type"] == "text"
282
+ else process_image_url(item["image_url"])
283
+ )
280
284
  for item in content
281
285
  ]
282
286
  else:
@@ -38,7 +38,7 @@ class ProviderOpenAIOfficial(Provider):
38
38
  default_persona,
39
39
  )
40
40
  self.chosen_api_key = None
41
- self.api_keys: List = provider_config.get("key", [])
41
+ self.api_keys: List = super().get_keys()
42
42
  self.chosen_api_key = self.api_keys[0] if len(self.api_keys) > 0 else None
43
43
  self.timeout = provider_config.get("timeout", 120)
44
44
  if isinstance(self.timeout, str):
@@ -65,12 +65,12 @@ class SessionManagementRoute(Route):
65
65
  persona_name = data["persona_name"]
66
66
 
67
67
  # 处理 persona 显示
68
- if conv_persona_id == "[%None]":
69
- persona_name = "无人格"
70
- else:
71
- default_persona = persona_mgr.selected_default_persona_v3
72
- if default_persona:
73
- persona_name = default_persona["name"]
68
+ if persona_name is None:
69
+ if conv_persona_id is None:
70
+ if default_persona := persona_mgr.selected_default_persona_v3:
71
+ persona_name = default_persona["name"]
72
+ else:
73
+ persona_name = "[%None]"
74
74
 
75
75
  session_info = {
76
76
  "session_id": session_id,
@@ -9,6 +9,8 @@ from astrbot.core.config.default import VERSION
9
9
  from astrbot.core import DEMO_MODE
10
10
  from astrbot.core.db.migration.helper import do_migration_v4, check_migration_needed_v4
11
11
 
12
+ CLEAR_SITE_DATA_HEADERS = {"Clear-Site-Data": '"cache"'}
13
+
12
14
 
13
15
  class UpdateRoute(Route):
14
16
  def __init__(
@@ -113,17 +115,19 @@ class UpdateRoute(Route):
113
115
 
114
116
  if reboot:
115
117
  await self.core_lifecycle.restart()
116
- return (
118
+ ret = (
117
119
  Response()
118
120
  .ok(None, "更新成功,AstrBot 将在 2 秒内全量重启以应用新的代码。")
119
121
  .__dict__
120
122
  )
123
+ return ret, 200, CLEAR_SITE_DATA_HEADERS
121
124
  else:
122
- return (
125
+ ret = (
123
126
  Response()
124
127
  .ok(None, "更新成功,AstrBot 将在下次启动时应用新的代码。")
125
128
  .__dict__
126
129
  )
130
+ return ret, 200, CLEAR_SITE_DATA_HEADERS
127
131
  except Exception as e:
128
132
  logger.error(f"/api/update_project: {traceback.format_exc()}")
129
133
  return Response().error(e.__str__()).__dict__
@@ -135,9 +139,8 @@ class UpdateRoute(Route):
135
139
  except Exception as e:
136
140
  logger.error(f"下载管理面板文件失败: {e}。")
137
141
  return Response().error(f"下载管理面板文件失败: {e}").__dict__
138
- return (
139
- Response().ok(None, "更新成功。刷新页面即可应用新版本面板。").__dict__
140
- )
142
+ ret = Response().ok(None, "更新成功。刷新页面即可应用新版本面板。").__dict__
143
+ return ret, 200, CLEAR_SITE_DATA_HEADERS
141
144
  except Exception as e:
142
145
  logger.error(f"/api/update_dashboard: {traceback.format_exc()}")
143
146
  return Response().error(e.__str__()).__dict__
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AstrBot
3
- Version: 4.3.2
3
+ Version: 4.3.3
4
4
  Summary: 易上手的多平台 LLM 聊天机器人及开发框架
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.10
@@ -45,10 +45,10 @@ astrbot/core/agent/runners/base.py,sha256=exZS_d2BsrLz-xgeY9ZUPuXikBDUnKxO-dU3ZF
45
45
  astrbot/core/agent/runners/tool_loop_agent_runner.py,sha256=O4sYg1V3dbUcZFLek5Izi-aEJb983tk9DJOCBQvQjro,13558
46
46
  astrbot/core/config/__init__.py,sha256=0CO_3sKtI3WOwWT0k4i6TleWq1SAWJFfB8KjnYB8Zig,172
47
47
  astrbot/core/config/astrbot_config.py,sha256=X-b3c5m4msgJrdYFH2LXic5XKY0ViuUMdNZ335zqSBw,6335
48
- astrbot/core/config/default.py,sha256=DyrHaNp82t7kaXwyE14xZrBpk0MVl50dZJK28z5iB8M,123320
48
+ astrbot/core/config/default.py,sha256=PVNeFncOfO1yksdRDUl2_LJWpAQRaxYYuikZnR9lSco,124015
49
49
  astrbot/core/db/__init__.py,sha256=JOAMt7_j0y96CuArXJ-YY_qXisSartOZwyDTKf9ZDn8,8844
50
50
  astrbot/core/db/po.py,sha256=NDOJpUXI1i4BF1uymCj07opwXM0gdHBtwCoL16Xj4jc,7798
51
- astrbot/core/db/sqlite.py,sha256=5o4nsGnq5NsFkhZEv-eM_rXq_w859TcHk-m602B3mCM,25612
51
+ astrbot/core/db/sqlite.py,sha256=_5-B2Jlare4twLG0TlO95bVTaLu0HAXsfpX5LOcoVWA,26082
52
52
  astrbot/core/db/migration/helper.py,sha256=FcwpvBANNeyBSrRhXyd3hudHYEyhTyrcRg9mU9lZtqY,1935
53
53
  astrbot/core/db/migration/migra_3_to_4.py,sha256=I1CesaBbf5wj9agtNWxDl1V-qixmwdURbBQf5Vzagrk,15025
54
54
  astrbot/core/db/migration/shared_preferences_v3.py,sha256=tE11WIpwT-Q8yVBkw4eveRr1PmFdNRJQSprH4xdO3G4,1245
@@ -63,7 +63,7 @@ astrbot/core/message/components.py,sha256=AzJACQYgw0Yo1iwSIyQWtfE8Xyo-6Q8KcQPE9y
63
63
  astrbot/core/message/message_event_result.py,sha256=dooPyzDVV4danPNQBvZsSXemGsihnBjW3qYByYUEa1s,7248
64
64
  astrbot/core/pipeline/__init__.py,sha256=-jo6a9lKmwY8oPoifJi0IMLPOVdknQKG30ppIyCs5Bg,1461
65
65
  astrbot/core/pipeline/context.py,sha256=3ySHVzhjdT54kTDMMKPse1EFdvb7XfmscNEp3YCJLVM,503
66
- astrbot/core/pipeline/context_utils.py,sha256=lJ2iJorUGOp641qHPEljNhcZn5353C8jUGOz2bp19dA,3524
66
+ astrbot/core/pipeline/context_utils.py,sha256=CmR45Er5yFpI-IPwDfbJA1rOhzgNybkZg149dpgtl6w,3548
67
67
  astrbot/core/pipeline/scheduler.py,sha256=8N6QuLV55gR1jQZDEOUDrvcf42ify8EDmw1aDU3Y4nE,3270
68
68
  astrbot/core/pipeline/stage.py,sha256=dqEhUuQIhAZpPV4dULmVN39R0pIPjyw8Ftvs4Y1C4lY,1352
69
69
  astrbot/core/pipeline/content_safety_check/stage.py,sha256=yUF2h_E41VZQt70pCtIqr1-pgobbJ49omSnKUgg_G-M,1379
@@ -77,7 +77,7 @@ astrbot/core/pipeline/process_stage/method/llm_request.py,sha256=NaWr0eRhuxqb4ZI
77
77
  astrbot/core/pipeline/process_stage/method/star_request.py,sha256=IuPP7qnxvBgKV6a9D3wLU4_KU3Ec3Ml7IOADQCXDgqk,2501
78
78
  astrbot/core/pipeline/rate_limit_check/stage.py,sha256=I_GkpSgioN0-T_catMwpRKtxx-TiMmvu8vV_FE5ORIA,4072
79
79
  astrbot/core/pipeline/respond/stage.py,sha256=XE5yGsHGxESP0zAGmx3qHovP1wGaJDXUgfLb5Z4wasE,10837
80
- astrbot/core/pipeline/result_decorate/stage.py,sha256=An9797dUMWoYlEPXwtzvSkpe2bIPhEKccePb3pOwiY8,13681
80
+ astrbot/core/pipeline/result_decorate/stage.py,sha256=mxTBH5jDWDrfQV2H6XCWMYJLCuPiTAZut4-Gqrpufk4,13847
81
81
  astrbot/core/pipeline/session_status_check/stage.py,sha256=woucuVbzzQoi62MDoP3lTha4es_fUu4p-IPCzSiYDBw,1262
82
82
  astrbot/core/pipeline/waking_check/stage.py,sha256=URBFmfid1CKhtCGjH7OzFmxBE-Gt9vv1eYlp6msIv_Q,8240
83
83
  astrbot/core/pipeline/whitelist_check/stage.py,sha256=VcmLs0VfmspNTsitL_WrZXfv2lR2Nktrb5JEWc1VJuw,2403
@@ -133,25 +133,25 @@ astrbot/core/provider/entites.py,sha256=-353AdRDA6ST4AS48cQ1RRAXHSy3F7pVS_28hW4c
133
133
  astrbot/core/provider/entities.py,sha256=CkC-U9nafBKo2n2kLZqzukosDX7RuZWAK4DMBHQkasA,11238
134
134
  astrbot/core/provider/func_tool_manager.py,sha256=NuWMmAJaEwoJ3XCSvhwtmzDPdzX4K4BIRKuKgF0FlQk,20881
135
135
  astrbot/core/provider/manager.py,sha256=GoRR4hTRyYaaWH6_ICx0tflqG1Lng72dVOuq6pagb5k,21729
136
- astrbot/core/provider/provider.py,sha256=lMBZF6EjCRqLaOEv9-tsIcUdyNsVgFi16e4HdwioIZE,7209
136
+ astrbot/core/provider/provider.py,sha256=3R0xWAYuUQ0VXWja1TZtVVfqN8d3f9VhhYdpdqj5uaA,7239
137
137
  astrbot/core/provider/register.py,sha256=bWAF9zWNnSYQWjmZIXiWgxFaeWIiWjEoEIN_xhmq3mM,1830
138
- astrbot/core/provider/sources/anthropic_source.py,sha256=9I6VEZ5ANv-SIx7TaNGr2o_9S1xK0eTMOxt1ZF4XrBM,14974
138
+ astrbot/core/provider/sources/anthropic_source.py,sha256=GQY8TUw56V6pIGfqwT7KeJ-8dBSDZi7jjCwbhSsVekQ,15184
139
139
  astrbot/core/provider/sources/azure_tts_source.py,sha256=V8WGpMFeYn-DhmE2FtYYYir-51T1S81XKvP08tslm8E,9350
140
140
  astrbot/core/provider/sources/coze_api_client.py,sha256=dr2QpON0I83eIyadh5XDEVnGl26Jm5rbXGzQKkLBBcc,10820
141
141
  astrbot/core/provider/sources/coze_source.py,sha256=KddH9Ryl-cuaobjVBY5ar_cPEb5MUDvc7Pqx9BTp9Oo,25215
142
142
  astrbot/core/provider/sources/dashscope_source.py,sha256=HPzMCI-x5Ht76KxxvWHSwffW5tq6gWJQl48O_YKCTcc,7321
143
- astrbot/core/provider/sources/dashscope_tts.py,sha256=qGVGSKoW-yVHlnWl_eONwLtkAGMQX6t81FPkC-dV25U,1532
143
+ astrbot/core/provider/sources/dashscope_tts.py,sha256=gMm876jMiL15bmMbkAaQSP-XKjSdL1rBLrXCFVQXJhQ,5522
144
144
  astrbot/core/provider/sources/dify_source.py,sha256=Q0VmnacKwD-fOnvwYqbrRMspDYOlJZAHnjBawRzshw4,11472
145
145
  astrbot/core/provider/sources/edge_tts_source.py,sha256=foO2E0Wdc2wJy8yMbLUyX0cjkP6MD4vPCbc8q3Ckkug,4716
146
146
  astrbot/core/provider/sources/fishaudio_tts_api_source.py,sha256=Tu4wHh5txKDWn3_Z57hWgzTU8QUw1oVFBndAqmp4aLY,5439
147
147
  astrbot/core/provider/sources/gemini_embedding_source.py,sha256=FlVlacBLlxo4ZZgrBhurDQRuDYRGtR8Du35XuXEY9nI,2307
148
- astrbot/core/provider/sources/gemini_source.py,sha256=Gwn8nzMcsPsIVgDJ9G20tevUlYDyu_3g1_yaXsmvFPU,28649
148
+ astrbot/core/provider/sources/gemini_source.py,sha256=U7imSkoR1kQyTZN_ueCnbMlJ3bi6cjSNdKivLeOUGeU,28787
149
149
  astrbot/core/provider/sources/gemini_tts_source.py,sha256=mNcb9G6Lb58L2zoSYzroQGyASGrv3k4ZjmOIVvhii_o,2886
150
150
  astrbot/core/provider/sources/gsv_selfhosted_source.py,sha256=7wSQ32AJv4cisjnedENfpThd1kHDqYvnMSCpwbpNNM4,5936
151
151
  astrbot/core/provider/sources/gsvi_tts_source.py,sha256=EoYuAf85NVcPPbyRWkE_doWF-7R8IM5o9ozxbbvaFRk,2025
152
152
  astrbot/core/provider/sources/minimax_tts_api_source.py,sha256=jNLP_4-UHq_Iekvjn3h7G6YZjTCGuII-hq-1RhzjSlE,5877
153
153
  astrbot/core/provider/sources/openai_embedding_source.py,sha256=IIz25EksuIWINKpLqfKG-9Qc4bJ398w24oMjoArXFUA,1669
154
- astrbot/core/provider/sources/openai_source.py,sha256=ZdSI52h9tj78kObkvjIUODjyqWL2VO1N3JvElKo9M8E,20956
154
+ astrbot/core/provider/sources/openai_source.py,sha256=_koDL9xmsFb4Gf2r-1VWzKMGTwQcgs00RKtWOZqcfck,20944
155
155
  astrbot/core/provider/sources/openai_tts_api_source.py,sha256=ClRxEuBJ2-vM5rpMwwhOZXXJanq6asEAVPRvD9wYFrI,1626
156
156
  astrbot/core/provider/sources/sensevoice_selfhosted_source.py,sha256=2-NUDRiJJs3onxnrovdoVqUMI8bxGu2J2n3ZgwjxEm0,3828
157
157
  astrbot/core/provider/sources/vllm_rerank_source.py,sha256=Gv_veniilJ5v9lPGlQG_zmQYmHfhNggYIwj5p02CoLE,2275
@@ -212,14 +212,14 @@ astrbot/dashboard/routes/log.py,sha256=hDl6Niz_Vs4xb64USjCBzdOcm68GDpEsQrNrLr8yK
212
212
  astrbot/dashboard/routes/persona.py,sha256=6icnNNE8A0Yy1WI0INWD9ZPKC7VcZG-xHDfYElhaP8M,7857
213
213
  astrbot/dashboard/routes/plugin.py,sha256=cGGJVEM55uRiPo-EeD5apZQISzPw9vux7a-U2dE4fZQ,19429
214
214
  astrbot/dashboard/routes/route.py,sha256=V-Wm88D0BmxSYAUbedunykbWy5p7Tggae9nDhxm7LZU,1545
215
- astrbot/dashboard/routes/session_management.py,sha256=Gf7cnE3d1IWACHDqGoVsJ5mZTotQfguwZiDP0A6QlpU,26792
215
+ astrbot/dashboard/routes/session_management.py,sha256=yYcaXDwOiNYoLrseCxazLoFpxj_rsOUQ9-_8zifAAXE,26811
216
216
  astrbot/dashboard/routes/stat.py,sha256=KCtP0-f9g664gM2SOBgnU8uKx6zt93-5Kut-d7wd7zk,6910
217
217
  astrbot/dashboard/routes/static_file.py,sha256=7KnNcOb1BVqSTft114LhGsDkfg69X2jHEm0tOK0kW0Y,1169
218
218
  astrbot/dashboard/routes/t2i.py,sha256=scp05AxoJM9cubrkSMBu1BbIWP1BMS50eFEPZ9S6WKM,8893
219
219
  astrbot/dashboard/routes/tools.py,sha256=FvWgjzImgeIGFWJM_r2tku3UTj0J5LwZXfmZJxfJWHM,13975
220
- astrbot/dashboard/routes/update.py,sha256=vhG6ET0GJNLTpfkKABYf3Aq5ChUCID1BvoZissWRBZg,6517
221
- astrbot-4.3.2.dist-info/METADATA,sha256=bJs_S9odxMkmrmby7JCgNxdg28UuHBRIkggXr9BNea0,11095
222
- astrbot-4.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
223
- astrbot-4.3.2.dist-info/entry_points.txt,sha256=OEF09YmhBWYuViXrvTLLpstF4ccmNwDL8r7nnFD0pfI,53
224
- astrbot-4.3.2.dist-info/licenses/LICENSE,sha256=zPfQj5Mq8-gThIiBcxETr7t8gND9bZWOjTGQAr80TQI,34500
225
- astrbot-4.3.2.dist-info/RECORD,,
220
+ astrbot/dashboard/routes/update.py,sha256=cFeb0EGA69afhSB4o1HJYsvlBQGQotQXQJsp_juJ6ck,6707
221
+ astrbot-4.3.3.dist-info/METADATA,sha256=7SX8mVXZ5Mok98mqaH7vN0LYZlO4di7RSHnsyiLfgZE,11095
222
+ astrbot-4.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
223
+ astrbot-4.3.3.dist-info/entry_points.txt,sha256=OEF09YmhBWYuViXrvTLLpstF4ccmNwDL8r7nnFD0pfI,53
224
+ astrbot-4.3.3.dist-info/licenses/LICENSE,sha256=zPfQj5Mq8-gThIiBcxETr7t8gND9bZWOjTGQAr80TQI,34500
225
+ astrbot-4.3.3.dist-info/RECORD,,