AstrBot 4.0.0b4__py3-none-any.whl → 4.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 (43) hide show
  1. astrbot/api/event/filter/__init__.py +2 -0
  2. astrbot/cli/utils/basic.py +12 -3
  3. astrbot/core/astrbot_config_mgr.py +16 -9
  4. astrbot/core/config/default.py +82 -4
  5. astrbot/core/initial_loader.py +4 -1
  6. astrbot/core/message/components.py +59 -50
  7. astrbot/core/pipeline/process_stage/method/llm_request.py +6 -2
  8. astrbot/core/pipeline/result_decorate/stage.py +5 -1
  9. astrbot/core/platform/manager.py +25 -3
  10. astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +26 -14
  11. astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +11 -4
  12. astrbot/core/platform/sources/satori/satori_adapter.py +482 -0
  13. astrbot/core/platform/sources/satori/satori_event.py +221 -0
  14. astrbot/core/platform/sources/telegram/tg_adapter.py +0 -1
  15. astrbot/core/provider/entities.py +17 -15
  16. astrbot/core/provider/sources/gemini_source.py +57 -18
  17. astrbot/core/provider/sources/openai_source.py +12 -5
  18. astrbot/core/provider/sources/vllm_rerank_source.py +6 -0
  19. astrbot/core/star/__init__.py +7 -5
  20. astrbot/core/star/filter/command.py +9 -3
  21. astrbot/core/star/filter/platform_adapter_type.py +3 -0
  22. astrbot/core/star/register/__init__.py +2 -0
  23. astrbot/core/star/register/star_handler.py +18 -4
  24. astrbot/core/star/star_handler.py +9 -1
  25. astrbot/core/star/star_tools.py +116 -21
  26. astrbot/core/updator.py +7 -5
  27. astrbot/core/utils/io.py +1 -1
  28. astrbot/core/utils/t2i/network_strategy.py +11 -18
  29. astrbot/core/utils/t2i/renderer.py +8 -2
  30. astrbot/core/utils/t2i/template/astrbot_powershell.html +184 -0
  31. astrbot/core/utils/t2i/template_manager.py +112 -0
  32. astrbot/core/zip_updator.py +26 -4
  33. astrbot/dashboard/routes/chat.py +6 -1
  34. astrbot/dashboard/routes/config.py +24 -49
  35. astrbot/dashboard/routes/route.py +19 -2
  36. astrbot/dashboard/routes/t2i.py +230 -0
  37. astrbot/dashboard/routes/update.py +3 -5
  38. astrbot/dashboard/server.py +13 -4
  39. {astrbot-4.0.0b4.dist-info → astrbot-4.1.0.dist-info}/METADATA +40 -53
  40. {astrbot-4.0.0b4.dist-info → astrbot-4.1.0.dist-info}/RECORD +43 -38
  41. {astrbot-4.0.0b4.dist-info → astrbot-4.1.0.dist-info}/WHEEL +0 -0
  42. {astrbot-4.0.0b4.dist-info → astrbot-4.1.0.dist-info}/entry_points.txt +0 -0
  43. {astrbot-4.0.0b4.dist-info → astrbot-4.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -7,6 +7,7 @@ from astrbot.core.star.register import (
7
7
  register_permission_type as permission_type,
8
8
  register_custom_filter as custom_filter,
9
9
  register_on_astrbot_loaded as on_astrbot_loaded,
10
+ register_on_platform_loaded as on_platform_loaded,
10
11
  register_on_llm_request as on_llm_request,
11
12
  register_on_llm_response as on_llm_response,
12
13
  register_llm_tool as llm_tool,
@@ -41,6 +42,7 @@ __all__ = [
41
42
  "custom_filter",
42
43
  "PermissionType",
43
44
  "on_astrbot_loaded",
45
+ "on_platform_loaded",
44
46
  "on_llm_request",
45
47
  "llm_tool",
46
48
  "on_decorating_result",
@@ -37,7 +37,10 @@ async def check_dashboard(astrbot_root: Path) -> None:
37
37
  ):
38
38
  click.echo("正在安装管理面板...")
39
39
  await download_dashboard(
40
- path="data/dashboard.zip", extract_path=str(astrbot_root)
40
+ path="data/dashboard.zip",
41
+ extract_path=str(astrbot_root),
42
+ version=f"v{VERSION}",
43
+ latest=False,
41
44
  )
42
45
  click.echo("管理面板安装完成")
43
46
 
@@ -50,7 +53,10 @@ async def check_dashboard(astrbot_root: Path) -> None:
50
53
  version = dashboard_version.split("v")[1]
51
54
  click.echo(f"管理面板版本: {version}")
52
55
  await download_dashboard(
53
- path="data/dashboard.zip", extract_path=str(astrbot_root)
56
+ path="data/dashboard.zip",
57
+ extract_path=str(astrbot_root),
58
+ version=f"v{VERSION}",
59
+ latest=False,
54
60
  )
55
61
  except Exception as e:
56
62
  click.echo(f"下载管理面板失败: {e}")
@@ -59,7 +65,10 @@ async def check_dashboard(astrbot_root: Path) -> None:
59
65
  click.echo("初始化管理面板目录...")
60
66
  try:
61
67
  await download_dashboard(
62
- path=str(astrbot_root / "dashboard.zip"), extract_path=str(astrbot_root)
68
+ path=str(astrbot_root / "dashboard.zip"),
69
+ extract_path=str(astrbot_root),
70
+ version=f"v{VERSION}",
71
+ latest=False,
63
72
  )
64
73
  click.echo("管理面板初始化完成")
65
74
  except Exception as e:
@@ -36,13 +36,21 @@ class AstrBotConfigManager:
36
36
  self.confs: dict[str, AstrBotConfig] = {}
37
37
  """uuid / "default" -> AstrBotConfig"""
38
38
  self.confs["default"] = default_config
39
+ self.abconf_data = None
39
40
  self._load_all_configs()
40
41
 
42
+ def _get_abconf_data(self) -> dict:
43
+ """获取所有的 abconf 数据"""
44
+ if self.abconf_data is None:
45
+ self.abconf_data = self.sp.get(
46
+ "abconf_mapping", {}, scope="global", scope_id="global"
47
+ )
48
+ return self.abconf_data
49
+
41
50
  def _load_all_configs(self):
42
51
  """Load all configurations from the shared preferences."""
43
- abconf_data = self.sp.get(
44
- "abconf_mapping", {}, scope="global", scope_id="global"
45
- )
52
+ abconf_data = self._get_abconf_data()
53
+ self.abconf_data = abconf_data
46
54
  for uuid_, meta in abconf_data.items():
47
55
  filename = meta["path"]
48
56
  conf_path = os.path.join(get_astrbot_config_path(), filename)
@@ -72,9 +80,7 @@ class AstrBotConfigManager:
72
80
  ConfInfo: 包含配置文件的 uuid, 路径和名称等信息, 是一个 dict 类型
73
81
  """
74
82
  # uuid -> { "umop": list, "path": str, "name": str }
75
- abconf_data = self.sp.get(
76
- "abconf_mapping", {}, scope="global", scope_id="global"
77
- )
83
+ abconf_data = self._get_abconf_data()
78
84
  if isinstance(umo, MessageSession):
79
85
  umo = str(umo)
80
86
  else:
@@ -115,6 +121,7 @@ class AstrBotConfigManager:
115
121
  "name": random_word,
116
122
  }
117
123
  self.sp.put("abconf_mapping", abconf_data, scope="global", scope_id="global")
124
+ self.abconf_data = abconf_data
118
125
 
119
126
  def get_conf(self, umo: str | MessageSession | None) -> AstrBotConfig:
120
127
  """获取指定 umo 的配置文件。如果不存在,则 fallback 到默认配置文件。"""
@@ -147,9 +154,7 @@ class AstrBotConfigManager:
147
154
  """获取所有配置文件的元数据列表"""
148
155
  conf_list = []
149
156
  conf_list.append(DEFAULT_CONFIG_CONF_INFO)
150
- abconf_mapping = self.sp.get(
151
- "abconf_mapping", {}, scope="global", scope_id="global"
152
- )
157
+ abconf_mapping = self._get_abconf_data()
153
158
  for uuid_, meta in abconf_mapping.items():
154
159
  conf_list.append(ConfInfo(**meta, id=uuid_))
155
160
  return conf_list
@@ -218,6 +223,7 @@ class AstrBotConfigManager:
218
223
  # 从映射中移除
219
224
  del abconf_data[conf_id]
220
225
  self.sp.put("abconf_mapping", abconf_data, scope="global", scope_id="global")
226
+ self.abconf_data = abconf_data
221
227
 
222
228
  logger.info(f"成功删除配置文件 {conf_id}")
223
229
  return True
@@ -263,6 +269,7 @@ class AstrBotConfigManager:
263
269
 
264
270
  # 保存更新
265
271
  self.sp.put("abconf_mapping", abconf_data, scope="global", scope_id="global")
272
+ self.abconf_data = abconf_data
266
273
  logger.info(f"成功更新配置文件 {conf_id} 的信息")
267
274
  return True
268
275
 
@@ -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.0.0-beta.4"
9
+ VERSION = "4.1.0"
10
10
  DB_PATH = os.path.join(get_astrbot_data_path(), "data_v4.db")
11
11
 
12
12
  # 默认配置
@@ -56,7 +56,7 @@ DEFAULT_CONFIG = {
56
56
  "wake_prefix": "",
57
57
  "web_search": False,
58
58
  "websearch_provider": "default",
59
- "websearch_tavily_key": "",
59
+ "websearch_tavily_key": [],
60
60
  "web_search_link": False,
61
61
  "display_reasoning_text": False,
62
62
  "identifier": False,
@@ -103,6 +103,7 @@ DEFAULT_CONFIG = {
103
103
  "t2i_strategy": "remote",
104
104
  "t2i_endpoint": "",
105
105
  "t2i_use_file_service": False,
106
+ "t2i_active_template": "base",
106
107
  "http_proxy": "",
107
108
  "no_proxy": ["localhost", "127.0.0.1", "::1"],
108
109
  "dashboard": {
@@ -246,8 +247,49 @@ CONFIG_METADATA_2 = {
246
247
  "slack_webhook_port": 6197,
247
248
  "slack_webhook_path": "/astrbot-slack-webhook/callback",
248
249
  },
250
+ "Satori": {
251
+ "id": "satori",
252
+ "type": "satori",
253
+ "enable": False,
254
+ "satori_api_base_url": "http://localhost:5140/satori/v1",
255
+ "satori_endpoint": "ws://127.0.0.1:5140/satori/v1/events",
256
+ "satori_token": "",
257
+ "satori_auto_reconnect": True,
258
+ "satori_heartbeat_interval": 10,
259
+ "satori_reconnect_delay": 5,
260
+ },
249
261
  },
250
262
  "items": {
263
+ "satori_api_base_url": {
264
+ "description": "Satori API Base URL",
265
+ "type": "string",
266
+ "hint": "The base URL for the Satori API.",
267
+ },
268
+ "satori_endpoint": {
269
+ "description": "Satori WebSocket Endpoint",
270
+ "type": "string",
271
+ "hint": "The WebSocket endpoint for Satori events.",
272
+ },
273
+ "satori_token": {
274
+ "description": "Satori Token",
275
+ "type": "string",
276
+ "hint": "The token used for authenticating with the Satori API.",
277
+ },
278
+ "satori_auto_reconnect": {
279
+ "description": "Enable Auto Reconnect",
280
+ "type": "bool",
281
+ "hint": "Whether to automatically reconnect the WebSocket on disconnection.",
282
+ },
283
+ "satori_heartbeat_interval": {
284
+ "description": "Satori Heartbeat Interval",
285
+ "type": "int",
286
+ "hint": "The interval (in seconds) for sending heartbeat messages.",
287
+ },
288
+ "satori_reconnect_delay": {
289
+ "description": "Satori Reconnect Delay",
290
+ "type": "int",
291
+ "hint": "The delay (in seconds) before attempting to reconnect.",
292
+ },
251
293
  "slack_connection_mode": {
252
294
  "description": "Slack Connection Mode",
253
295
  "type": "string",
@@ -557,6 +599,7 @@ CONFIG_METADATA_2 = {
557
599
  "api_base": "https://api.openai.com/v1",
558
600
  "timeout": 120,
559
601
  "model_config": {"model": "gpt-4o-mini", "temperature": 0.4},
602
+ "custom_extra_body": {},
560
603
  "modalities": ["text", "image", "tool_use"],
561
604
  "hint": "也兼容所有与 OpenAI API 兼容的服务。",
562
605
  },
@@ -571,6 +614,7 @@ CONFIG_METADATA_2 = {
571
614
  "api_base": "",
572
615
  "timeout": 120,
573
616
  "model_config": {"model": "gpt-4o-mini", "temperature": 0.4},
617
+ "custom_extra_body": {},
574
618
  "modalities": ["text", "image", "tool_use"],
575
619
  },
576
620
  "xAI": {
@@ -583,6 +627,7 @@ CONFIG_METADATA_2 = {
583
627
  "api_base": "https://api.x.ai/v1",
584
628
  "timeout": 120,
585
629
  "model_config": {"model": "grok-2-latest", "temperature": 0.4},
630
+ "custom_extra_body": {},
586
631
  "modalities": ["text", "image", "tool_use"],
587
632
  },
588
633
  "Anthropic": {
@@ -612,6 +657,7 @@ CONFIG_METADATA_2 = {
612
657
  "key": ["ollama"], # ollama 的 key 默认是 ollama
613
658
  "api_base": "http://localhost:11434/v1",
614
659
  "model_config": {"model": "llama3.1-8b", "temperature": 0.4},
660
+ "custom_extra_body": {},
615
661
  "modalities": ["text", "image", "tool_use"],
616
662
  },
617
663
  "LM Studio": {
@@ -625,6 +671,7 @@ CONFIG_METADATA_2 = {
625
671
  "model_config": {
626
672
  "model": "llama-3.1-8b",
627
673
  },
674
+ "custom_extra_body": {},
628
675
  "modalities": ["text", "image", "tool_use"],
629
676
  },
630
677
  "Gemini(OpenAI兼容)": {
@@ -640,6 +687,7 @@ CONFIG_METADATA_2 = {
640
687
  "model": "gemini-1.5-flash",
641
688
  "temperature": 0.4,
642
689
  },
690
+ "custom_extra_body": {},
643
691
  "modalities": ["text", "image", "tool_use"],
644
692
  },
645
693
  "Gemini": {
@@ -680,6 +728,7 @@ CONFIG_METADATA_2 = {
680
728
  "api_base": "https://api.deepseek.com/v1",
681
729
  "timeout": 120,
682
730
  "model_config": {"model": "deepseek-chat", "temperature": 0.4},
731
+ "custom_extra_body": {},
683
732
  "modalities": ["text", "image", "tool_use"],
684
733
  },
685
734
  "302.AI": {
@@ -692,6 +741,7 @@ CONFIG_METADATA_2 = {
692
741
  "api_base": "https://api.302.ai/v1",
693
742
  "timeout": 120,
694
743
  "model_config": {"model": "gpt-4.1-mini", "temperature": 0.4},
744
+ "custom_extra_body": {},
695
745
  "modalities": ["text", "image", "tool_use"],
696
746
  },
697
747
  "硅基流动": {
@@ -707,6 +757,7 @@ CONFIG_METADATA_2 = {
707
757
  "model": "deepseek-ai/DeepSeek-V3",
708
758
  "temperature": 0.4,
709
759
  },
760
+ "custom_extra_body": {},
710
761
  "modalities": ["text", "image", "tool_use"],
711
762
  },
712
763
  "PPIO派欧云": {
@@ -722,6 +773,7 @@ CONFIG_METADATA_2 = {
722
773
  "model": "deepseek/deepseek-r1",
723
774
  "temperature": 0.4,
724
775
  },
776
+ "custom_extra_body": {},
725
777
  },
726
778
  "优云智算": {
727
779
  "id": "compshare",
@@ -735,6 +787,7 @@ CONFIG_METADATA_2 = {
735
787
  "model_config": {
736
788
  "model": "moonshotai/Kimi-K2-Instruct",
737
789
  },
790
+ "custom_extra_body": {},
738
791
  "modalities": ["text", "image", "tool_use"],
739
792
  },
740
793
  "Kimi": {
@@ -747,6 +800,7 @@ CONFIG_METADATA_2 = {
747
800
  "timeout": 120,
748
801
  "api_base": "https://api.moonshot.cn/v1",
749
802
  "model_config": {"model": "moonshot-v1-8k", "temperature": 0.4},
803
+ "custom_extra_body": {},
750
804
  "modalities": ["text", "image", "tool_use"],
751
805
  },
752
806
  "智谱 AI": {
@@ -805,6 +859,7 @@ CONFIG_METADATA_2 = {
805
859
  "timeout": 120,
806
860
  "api_base": "https://api-inference.modelscope.cn/v1",
807
861
  "model_config": {"model": "Qwen/Qwen3-32B", "temperature": 0.4},
862
+ "custom_extra_body": {},
808
863
  "modalities": ["text", "image", "tool_use"],
809
864
  },
810
865
  "FastGPT": {
@@ -816,6 +871,7 @@ CONFIG_METADATA_2 = {
816
871
  "key": [],
817
872
  "api_base": "https://api.fastgpt.in/api/v1",
818
873
  "timeout": 60,
874
+ "custom_extra_body": {},
819
875
  },
820
876
  "Whisper(API)": {
821
877
  "id": "whisper",
@@ -866,6 +922,9 @@ CONFIG_METADATA_2 = {
866
922
  "provider_type": "text_to_speech",
867
923
  "enable": False,
868
924
  "edge-tts-voice": "zh-CN-XiaoxiaoNeural",
925
+ "rate": "+0%",
926
+ "volume": "+0%",
927
+ "pitch": "+0Hz",
869
928
  "timeout": 20,
870
929
  },
871
930
  "GSV TTS(本地加载)": {
@@ -1057,6 +1116,12 @@ CONFIG_METADATA_2 = {
1057
1116
  "render_type": "checkbox",
1058
1117
  "hint": "模型支持的模态。如所填写的模型不支持图像,请取消勾选图像。",
1059
1118
  },
1119
+ "custom_extra_body": {
1120
+ "description": "自定义请求体参数",
1121
+ "type": "dict",
1122
+ "items": {},
1123
+ "hint": "此处添加的键值对将被合并到发送给 API 的 extra_body 中。值可以是字符串、数字或布尔值。",
1124
+ },
1060
1125
  "provider": {
1061
1126
  "type": "string",
1062
1127
  "invisible": True,
@@ -1893,7 +1958,9 @@ CONFIG_METADATA_3 = {
1893
1958
  },
1894
1959
  "provider_settings.websearch_tavily_key": {
1895
1960
  "description": "Tavily API Key",
1896
- "type": "string",
1961
+ "type": "list",
1962
+ "items": {"type": "string"},
1963
+ "hint": "可添加多个 Key 进行轮询。",
1897
1964
  "condition": {
1898
1965
  "provider_settings.websearch_provider": "tavily",
1899
1966
  },
@@ -1926,7 +1993,7 @@ CONFIG_METADATA_3 = {
1926
1993
  },
1927
1994
  "provider_settings.max_agent_step": {
1928
1995
  "description": "工具调用轮数上限",
1929
- "type": "bool",
1996
+ "type": "int",
1930
1997
  },
1931
1998
  "provider_settings.streaming_response": {
1932
1999
  "description": "流式回复",
@@ -2290,6 +2357,12 @@ CONFIG_METADATA_3_SYSTEM = {
2290
2357
  },
2291
2358
  "_special": "t2i_template",
2292
2359
  },
2360
+ "t2i_active_template": {
2361
+ "description": "当前应用的文转图渲染模板",
2362
+ "type": "string",
2363
+ "hint": "此处的值由文转图模板管理页面进行维护。",
2364
+ "invisible": True,
2365
+ },
2293
2366
  "log_level": {
2294
2367
  "description": "控制台日志级别",
2295
2368
  "type": "string",
@@ -2321,6 +2394,11 @@ CONFIG_METADATA_3_SYSTEM = {
2321
2394
  "type": "string",
2322
2395
  "hint": "启用后,会以添加环境变量的方式设置代理。格式为 `http://ip:port`",
2323
2396
  },
2397
+ "no_proxy": {
2398
+ "description": "直连地址列表",
2399
+ "type": "list",
2400
+ "items": {"type": "string"},
2401
+ },
2324
2402
  },
2325
2403
  }
2326
2404
  },
@@ -22,6 +22,7 @@ class InitialLoader:
22
22
  self.db = db
23
23
  self.logger = logger
24
24
  self.log_broker = log_broker
25
+ self.webui_dir: str | None = None
25
26
 
26
27
  async def start(self):
27
28
  core_lifecycle = AstrBotCoreLifecycle(self.log_broker, self.db)
@@ -35,8 +36,10 @@ class InitialLoader:
35
36
 
36
37
  core_task = core_lifecycle.start()
37
38
 
39
+ webui_dir = self.webui_dir
40
+
38
41
  self.dashboard_server = AstrBotDashboard(
39
- core_lifecycle, self.db, core_lifecycle.dashboard_shutdown_event
42
+ core_lifecycle, self.db, core_lifecycle.dashboard_shutdown_event, webui_dir
40
43
  )
41
44
  task = asyncio.gather(
42
45
  core_task, self.dashboard_server.run()