AstrBot 4.7.4__py3-none-any.whl → 4.9.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.
- astrbot/cli/__init__.py +1 -1
- astrbot/core/agent/runners/tool_loop_agent_runner.py +0 -1
- astrbot/core/agent/tool.py +7 -2
- astrbot/core/astr_agent_run_util.py +15 -1
- astrbot/core/astr_agent_tool_exec.py +5 -1
- astrbot/core/config/astrbot_config.py +4 -0
- astrbot/core/config/default.py +116 -1
- astrbot/core/core_lifecycle.py +1 -1
- astrbot/core/db/__init__.py +32 -4
- astrbot/core/db/migration/migra_3_to_4.py +2 -0
- astrbot/core/db/migration/sqlite_v3.py +6 -4
- astrbot/core/db/po.py +16 -15
- astrbot/core/db/sqlite.py +56 -1
- astrbot/core/db/vec_db/faiss_impl/embedding_storage.py +2 -0
- astrbot/core/event_bus.py +6 -1
- astrbot/core/knowledge_base/retrieval/manager.py +5 -1
- astrbot/core/log.py +2 -1
- astrbot/core/message/components.py +9 -3
- astrbot/core/persona_mgr.py +2 -2
- astrbot/core/pipeline/content_safety_check/stage.py +1 -1
- astrbot/core/pipeline/context_utils.py +2 -1
- astrbot/core/pipeline/process_stage/method/agent_sub_stages/third_party.py +1 -1
- astrbot/core/pipeline/process_stage/method/star_request.py +1 -2
- astrbot/core/pipeline/process_stage/stage.py +1 -1
- astrbot/core/pipeline/respond/stage.py +4 -2
- astrbot/core/pipeline/result_decorate/stage.py +68 -21
- astrbot/core/pipeline/scheduler.py +5 -1
- astrbot/core/pipeline/waking_check/stage.py +10 -0
- astrbot/core/platform/astr_message_event.py +5 -3
- astrbot/core/platform/astrbot_message.py +2 -2
- astrbot/core/platform/manager.py +71 -9
- astrbot/core/platform/platform.py +109 -4
- astrbot/core/platform/platform_metadata.py +1 -1
- astrbot/core/platform/register.py +1 -0
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +8 -6
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +13 -8
- astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py +28 -22
- astrbot/core/platform/sources/dingtalk/dingtalk_event.py +5 -2
- astrbot/core/platform/sources/discord/client.py +16 -4
- astrbot/core/platform/sources/discord/components.py +2 -2
- astrbot/core/platform/sources/discord/discord_platform_adapter.py +53 -26
- astrbot/core/platform/sources/discord/discord_platform_event.py +29 -8
- astrbot/core/platform/sources/lark/lark_adapter.py +178 -22
- astrbot/core/platform/sources/lark/lark_event.py +39 -4
- astrbot/core/platform/sources/lark/server.py +206 -0
- astrbot/core/platform/sources/misskey/misskey_adapter.py +3 -5
- astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py +64 -18
- astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py +14 -10
- astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py +36 -11
- astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_server.py +15 -2
- astrbot/core/platform/sources/satori/satori_adapter.py +1 -2
- astrbot/core/platform/sources/slack/client.py +58 -40
- astrbot/core/platform/sources/slack/slack_adapter.py +36 -16
- astrbot/core/platform/sources/slack/slack_event.py +11 -10
- astrbot/core/platform/sources/telegram/tg_adapter.py +2 -3
- astrbot/core/platform/sources/telegram/tg_event.py +23 -27
- astrbot/core/platform/sources/webchat/webchat_adapter.py +97 -31
- astrbot/core/platform/sources/webchat/webchat_event.py +35 -35
- astrbot/core/platform/sources/wechatpadpro/wechatpadpro_adapter.py +27 -11
- astrbot/core/platform/sources/wecom/wecom_adapter.py +75 -36
- astrbot/core/platform/sources/wecom/wecom_event.py +3 -3
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_adapter.py +26 -9
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_event.py +3 -3
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_server.py +27 -5
- astrbot/core/platform/sources/weixin_official_account/weixin_offacc_adapter.py +81 -35
- astrbot/core/platform/sources/weixin_official_account/weixin_offacc_event.py +11 -8
- astrbot/core/platform_message_history_mgr.py +3 -3
- astrbot/core/provider/func_tool_manager.py +3 -3
- astrbot/core/provider/manager.py +130 -74
- astrbot/core/provider/provider.py +12 -1
- astrbot/core/provider/sources/azure_tts_source.py +31 -9
- astrbot/core/provider/sources/bailian_rerank_source.py +4 -0
- astrbot/core/provider/sources/dashscope_tts.py +3 -2
- astrbot/core/provider/sources/edge_tts_source.py +1 -1
- astrbot/core/provider/sources/fishaudio_tts_api_source.py +5 -4
- astrbot/core/provider/sources/gemini_embedding_source.py +15 -5
- astrbot/core/provider/sources/gemini_source.py +12 -10
- astrbot/core/provider/sources/minimax_tts_api_source.py +4 -2
- astrbot/core/provider/sources/openai_embedding_source.py +2 -2
- astrbot/core/provider/sources/openai_source.py +4 -0
- astrbot/core/provider/sources/sensevoice_selfhosted_source.py +5 -2
- astrbot/core/provider/sources/vllm_rerank_source.py +1 -0
- astrbot/core/provider/sources/whisper_api_source.py +44 -12
- astrbot/core/provider/sources/whisper_selfhosted_source.py +6 -2
- astrbot/core/provider/sources/xinference_rerank_source.py +10 -2
- astrbot/core/star/context.py +2 -2
- astrbot/core/star/register/star_handler.py +22 -5
- astrbot/core/star/star_handler.py +85 -4
- astrbot/core/updator.py +3 -3
- astrbot/core/utils/io.py +1 -1
- astrbot/core/utils/session_waiter.py +17 -10
- astrbot/core/utils/shared_preferences.py +32 -0
- astrbot/core/utils/t2i/__init__.py +2 -2
- astrbot/core/utils/t2i/local_strategy.py +25 -31
- astrbot/core/utils/tencent_record_helper.py +2 -2
- astrbot/core/utils/version_comparator.py +6 -3
- astrbot/core/utils/webhook_utils.py +66 -0
- astrbot/dashboard/routes/__init__.py +2 -0
- astrbot/dashboard/routes/chat.py +311 -76
- astrbot/dashboard/routes/config.py +14 -5
- astrbot/dashboard/routes/knowledge_base.py +254 -79
- astrbot/dashboard/routes/log.py +13 -8
- astrbot/dashboard/routes/platform.py +100 -0
- astrbot/dashboard/routes/plugin.py +108 -51
- astrbot/dashboard/routes/route.py +2 -0
- astrbot/dashboard/server.py +9 -4
- {astrbot-4.7.4.dist-info → astrbot-4.9.0.dist-info}/METADATA +50 -37
- {astrbot-4.7.4.dist-info → astrbot-4.9.0.dist-info}/RECORD +111 -108
- {astrbot-4.7.4.dist-info → astrbot-4.9.0.dist-info}/WHEEL +0 -0
- {astrbot-4.7.4.dist-info → astrbot-4.9.0.dist-info}/entry_points.txt +0 -0
- {astrbot-4.7.4.dist-info → astrbot-4.9.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import hashlib
|
|
2
3
|
import json
|
|
3
4
|
import os
|
|
4
5
|
import ssl
|
|
5
6
|
import traceback
|
|
7
|
+
from dataclasses import dataclass
|
|
6
8
|
from datetime import datetime
|
|
7
9
|
|
|
8
10
|
import aiohttp
|
|
9
11
|
import certifi
|
|
10
12
|
from quart import request
|
|
11
13
|
|
|
14
|
+
from astrbot.api import sp
|
|
12
15
|
from astrbot.core import DEMO_MODE, file_token_service, logger
|
|
13
16
|
from astrbot.core.core_lifecycle import AstrBotCoreLifecycle
|
|
14
17
|
from astrbot.core.star.filter.command import CommandFilter
|
|
@@ -25,6 +28,13 @@ PLUGIN_UPDATE_CONCURRENCY = (
|
|
|
25
28
|
)
|
|
26
29
|
|
|
27
30
|
|
|
31
|
+
@dataclass
|
|
32
|
+
class RegistrySource:
|
|
33
|
+
urls: list[str]
|
|
34
|
+
cache_file: str
|
|
35
|
+
md5_url: str | None # None means "no remote MD5, always treat cache as stale"
|
|
36
|
+
|
|
37
|
+
|
|
28
38
|
class PluginRoute(Route):
|
|
29
39
|
def __init__(
|
|
30
40
|
self,
|
|
@@ -45,6 +55,8 @@ class PluginRoute(Route):
|
|
|
45
55
|
"/plugin/on": ("POST", self.on_plugin),
|
|
46
56
|
"/plugin/reload": ("POST", self.reload_plugins),
|
|
47
57
|
"/plugin/readme": ("GET", self.get_plugin_readme),
|
|
58
|
+
"/plugin/source/get": ("GET", self.get_custom_source),
|
|
59
|
+
"/plugin/source/save": ("POST", self.save_custom_source),
|
|
48
60
|
}
|
|
49
61
|
self.core_lifecycle = core_lifecycle
|
|
50
62
|
self.plugin_manager = plugin_manager
|
|
@@ -84,22 +96,15 @@ class PluginRoute(Route):
|
|
|
84
96
|
custom = request.args.get("custom_registry")
|
|
85
97
|
force_refresh = request.args.get("force_refresh", "false").lower() == "true"
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if custom:
|
|
90
|
-
urls = [custom]
|
|
91
|
-
else:
|
|
92
|
-
urls = [
|
|
93
|
-
"https://api.soulter.top/astrbot/plugins",
|
|
94
|
-
"https://github.com/AstrBotDevs/AstrBot_Plugins_Collection/raw/refs/heads/main/plugin_cache_original.json",
|
|
95
|
-
]
|
|
99
|
+
# 构建注册表源信息
|
|
100
|
+
source = self._build_registry_source(custom)
|
|
96
101
|
|
|
97
102
|
# 如果不是强制刷新,先检查缓存是否有效
|
|
98
103
|
cached_data = None
|
|
99
104
|
if not force_refresh:
|
|
100
105
|
# 先检查MD5是否匹配,如果匹配则使用缓存
|
|
101
|
-
if await self._is_cache_valid(
|
|
102
|
-
cached_data = self._load_plugin_cache(cache_file)
|
|
106
|
+
if await self._is_cache_valid(source):
|
|
107
|
+
cached_data = self._load_plugin_cache(source.cache_file)
|
|
103
108
|
if cached_data:
|
|
104
109
|
logger.debug("缓存MD5匹配,使用缓存的插件市场数据")
|
|
105
110
|
return Response().ok(cached_data).__dict__
|
|
@@ -109,7 +114,7 @@ class PluginRoute(Route):
|
|
|
109
114
|
ssl_context = ssl.create_default_context(cafile=certifi.where())
|
|
110
115
|
connector = aiohttp.TCPConnector(ssl=ssl_context)
|
|
111
116
|
|
|
112
|
-
for url in urls:
|
|
117
|
+
for url in source.urls:
|
|
113
118
|
try:
|
|
114
119
|
async with (
|
|
115
120
|
aiohttp.ClientSession(
|
|
@@ -128,11 +133,13 @@ class PluginRoute(Route):
|
|
|
128
133
|
logger.warning(f"远程插件市场数据为空: {url}")
|
|
129
134
|
continue # 继续尝试其他URL或使用缓存
|
|
130
135
|
|
|
131
|
-
logger.info(
|
|
136
|
+
logger.info(
|
|
137
|
+
f"成功获取远程插件市场数据,包含 {len(remote_data)} 个插件"
|
|
138
|
+
)
|
|
132
139
|
# 获取最新的MD5并保存到缓存
|
|
133
|
-
current_md5 = await self.
|
|
140
|
+
current_md5 = await self._fetch_remote_md5(source.md5_url)
|
|
134
141
|
self._save_plugin_cache(
|
|
135
|
-
cache_file,
|
|
142
|
+
source.cache_file,
|
|
136
143
|
remote_data,
|
|
137
144
|
current_md5,
|
|
138
145
|
)
|
|
@@ -143,7 +150,7 @@ class PluginRoute(Route):
|
|
|
143
150
|
|
|
144
151
|
# 如果远程获取失败,尝试使用缓存数据
|
|
145
152
|
if not cached_data:
|
|
146
|
-
cached_data = self._load_plugin_cache(cache_file)
|
|
153
|
+
cached_data = self._load_plugin_cache(source.cache_file)
|
|
147
154
|
|
|
148
155
|
if cached_data:
|
|
149
156
|
logger.warning("远程插件市场数据获取失败,使用缓存数据")
|
|
@@ -151,39 +158,47 @@ class PluginRoute(Route):
|
|
|
151
158
|
|
|
152
159
|
return Response().error("获取插件列表失败,且没有可用的缓存数据").__dict__
|
|
153
160
|
|
|
154
|
-
|
|
155
|
-
"""
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
# 加载缓存文件
|
|
161
|
-
with open(cache_file, encoding="utf-8") as f:
|
|
162
|
-
cache_data = json.load(f)
|
|
161
|
+
def _build_registry_source(self, custom_url: str | None) -> RegistrySource:
|
|
162
|
+
"""构建注册表源信息"""
|
|
163
|
+
if custom_url:
|
|
164
|
+
# 对自定义URL生成一个安全的文件名
|
|
165
|
+
url_hash = hashlib.md5(custom_url.encode()).hexdigest()[:8]
|
|
166
|
+
cache_file = f"data/plugins_custom_{url_hash}.json"
|
|
163
167
|
|
|
164
|
-
|
|
165
|
-
if
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
# 更安全的后缀处理方式
|
|
169
|
+
if custom_url.endswith(".json"):
|
|
170
|
+
md5_url = custom_url[:-5] + "-md5.json"
|
|
171
|
+
else:
|
|
172
|
+
md5_url = custom_url + "-md5.json"
|
|
168
173
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
urls = [custom_url]
|
|
175
|
+
else:
|
|
176
|
+
cache_file = "data/plugins.json"
|
|
177
|
+
md5_url = "https://api.soulter.top/astrbot/plugins-md5"
|
|
178
|
+
urls = [
|
|
179
|
+
"https://api.soulter.top/astrbot/plugins",
|
|
180
|
+
"https://github.com/AstrBotDevs/AstrBot_Plugins_Collection/raw/refs/heads/main/plugin_cache_original.json",
|
|
181
|
+
]
|
|
182
|
+
return RegistrySource(urls=urls, cache_file=cache_file, md5_url=md5_url)
|
|
174
183
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return is_valid
|
|
184
|
+
def _load_cached_md5(self, cache_file: str) -> str | None:
|
|
185
|
+
"""从缓存文件中加载MD5"""
|
|
186
|
+
if not os.path.exists(cache_file):
|
|
187
|
+
return None
|
|
180
188
|
|
|
189
|
+
try:
|
|
190
|
+
with open(cache_file, encoding="utf-8") as f:
|
|
191
|
+
cache_data = json.load(f)
|
|
192
|
+
return cache_data.get("md5")
|
|
181
193
|
except Exception as e:
|
|
182
|
-
logger.warning(f"
|
|
183
|
-
return
|
|
194
|
+
logger.warning(f"加载缓存MD5失败: {e}")
|
|
195
|
+
return None
|
|
196
|
+
|
|
197
|
+
async def _fetch_remote_md5(self, md5_url: str | None) -> str | None:
|
|
198
|
+
"""获取远程MD5"""
|
|
199
|
+
if not md5_url:
|
|
200
|
+
return None
|
|
184
201
|
|
|
185
|
-
async def _get_remote_md5(self) -> str:
|
|
186
|
-
"""获取远程插件数据的MD5"""
|
|
187
202
|
try:
|
|
188
203
|
ssl_context = ssl.create_default_context(cafile=certifi.where())
|
|
189
204
|
connector = aiohttp.TCPConnector(ssl=ssl_context)
|
|
@@ -193,18 +208,37 @@ class PluginRoute(Route):
|
|
|
193
208
|
trust_env=True,
|
|
194
209
|
connector=connector,
|
|
195
210
|
) as session,
|
|
196
|
-
session.get(
|
|
197
|
-
"https://api.soulter.top/astrbot/plugins-md5",
|
|
198
|
-
) as response,
|
|
211
|
+
session.get(md5_url) as response,
|
|
199
212
|
):
|
|
200
213
|
if response.status == 200:
|
|
201
214
|
data = await response.json()
|
|
202
215
|
return data.get("md5", "")
|
|
203
|
-
logger.error(f"获取MD5失败,状态码:{response.status}")
|
|
204
|
-
return ""
|
|
205
216
|
except Exception as e:
|
|
206
|
-
logger.
|
|
207
|
-
|
|
217
|
+
logger.debug(f"获取远程MD5失败: {e}")
|
|
218
|
+
return None
|
|
219
|
+
|
|
220
|
+
async def _is_cache_valid(self, source: RegistrySource) -> bool:
|
|
221
|
+
"""检查缓存是否有效(基于MD5)"""
|
|
222
|
+
try:
|
|
223
|
+
cached_md5 = self._load_cached_md5(source.cache_file)
|
|
224
|
+
if not cached_md5:
|
|
225
|
+
logger.debug("缓存文件中没有MD5信息")
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
remote_md5 = await self._fetch_remote_md5(source.md5_url)
|
|
229
|
+
if remote_md5 is None:
|
|
230
|
+
logger.warning("无法获取远程MD5,将使用缓存")
|
|
231
|
+
return True # 如果无法获取远程MD5,认为缓存有效
|
|
232
|
+
|
|
233
|
+
is_valid = cached_md5 == remote_md5
|
|
234
|
+
logger.debug(
|
|
235
|
+
f"插件数据MD5: 本地={cached_md5}, 远程={remote_md5}, 有效={is_valid}",
|
|
236
|
+
)
|
|
237
|
+
return is_valid
|
|
238
|
+
|
|
239
|
+
except Exception as e:
|
|
240
|
+
logger.warning(f"检查缓存有效性失败: {e}")
|
|
241
|
+
return False
|
|
208
242
|
|
|
209
243
|
def _load_plugin_cache(self, cache_file: str):
|
|
210
244
|
"""加载本地缓存的插件市场数据"""
|
|
@@ -545,9 +579,13 @@ class PluginRoute(Route):
|
|
|
545
579
|
logger.warning(f"插件 {plugin_name} 不存在")
|
|
546
580
|
return Response().error(f"插件 {plugin_name} 不存在").__dict__
|
|
547
581
|
|
|
582
|
+
if not plugin_obj.root_dir_name:
|
|
583
|
+
logger.warning(f"插件 {plugin_name} 目录不存在")
|
|
584
|
+
return Response().error(f"插件 {plugin_name} 目录不存在").__dict__
|
|
585
|
+
|
|
548
586
|
plugin_dir = os.path.join(
|
|
549
587
|
self.plugin_manager.plugin_store_path,
|
|
550
|
-
plugin_obj.root_dir_name,
|
|
588
|
+
plugin_obj.root_dir_name or "",
|
|
551
589
|
)
|
|
552
590
|
|
|
553
591
|
if not os.path.isdir(plugin_dir):
|
|
@@ -572,3 +610,22 @@ class PluginRoute(Route):
|
|
|
572
610
|
except Exception as e:
|
|
573
611
|
logger.error(f"/api/plugin/readme: {traceback.format_exc()}")
|
|
574
612
|
return Response().error(f"读取README文件失败: {e!s}").__dict__
|
|
613
|
+
|
|
614
|
+
async def get_custom_source(self):
|
|
615
|
+
"""获取自定义插件源"""
|
|
616
|
+
sources = await sp.global_get("custom_plugin_sources", [])
|
|
617
|
+
return Response().ok(sources).__dict__
|
|
618
|
+
|
|
619
|
+
async def save_custom_source(self):
|
|
620
|
+
"""保存自定义插件源"""
|
|
621
|
+
try:
|
|
622
|
+
data = await request.get_json()
|
|
623
|
+
sources = data.get("sources", [])
|
|
624
|
+
if not isinstance(sources, list):
|
|
625
|
+
return Response().error("sources fields must be a list").__dict__
|
|
626
|
+
|
|
627
|
+
await sp.global_put("custom_plugin_sources", sources)
|
|
628
|
+
return Response().ok(None, "保存成功").__dict__
|
|
629
|
+
except Exception as e:
|
|
630
|
+
logger.error(f"/api/plugin/source/save: {traceback.format_exc()}")
|
|
631
|
+
return Response().error(str(e)).__dict__
|
astrbot/dashboard/server.py
CHANGED
|
@@ -2,9 +2,12 @@ import asyncio
|
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
4
|
import socket
|
|
5
|
+
from typing import cast
|
|
5
6
|
|
|
6
7
|
import jwt
|
|
7
8
|
import psutil
|
|
9
|
+
from flask.json.provider import DefaultJSONProvider
|
|
10
|
+
from psutil._common import addr as psutil_addr
|
|
8
11
|
from quart import Quart, g, jsonify, request
|
|
9
12
|
from quart.logging import default_handler
|
|
10
13
|
|
|
@@ -16,11 +19,12 @@ from astrbot.core.utils.astrbot_path import get_astrbot_data_path
|
|
|
16
19
|
from astrbot.core.utils.io import get_local_ip_addresses
|
|
17
20
|
|
|
18
21
|
from .routes import *
|
|
22
|
+
from .routes.platform import PlatformRoute
|
|
19
23
|
from .routes.route import Response, RouteContext
|
|
20
24
|
from .routes.session_management import SessionManagementRoute
|
|
21
25
|
from .routes.t2i import T2iRoute
|
|
22
26
|
|
|
23
|
-
APP: Quart
|
|
27
|
+
APP: Quart
|
|
24
28
|
|
|
25
29
|
|
|
26
30
|
class AstrBotDashboard:
|
|
@@ -47,7 +51,7 @@ class AstrBotDashboard:
|
|
|
47
51
|
self.app.config["MAX_CONTENT_LENGTH"] = (
|
|
48
52
|
128 * 1024 * 1024
|
|
49
53
|
) # 将 Flask 允许的最大上传文件体大小设置为 128 MB
|
|
50
|
-
self.app.json.sort_keys = False
|
|
54
|
+
cast(DefaultJSONProvider, self.app.json).sort_keys = False
|
|
51
55
|
self.app.before_request(self.auth_middleware)
|
|
52
56
|
# token 用于验证请求
|
|
53
57
|
logging.getLogger(self.app.name).removeHandler(default_handler)
|
|
@@ -79,6 +83,7 @@ class AstrBotDashboard:
|
|
|
79
83
|
self.persona_route = PersonaRoute(self.context, db, core_lifecycle)
|
|
80
84
|
self.t2i_route = T2iRoute(self.context, core_lifecycle)
|
|
81
85
|
self.kb_route = KnowledgeBaseRoute(self.context, core_lifecycle)
|
|
86
|
+
self.platform_route = PlatformRoute(self.context, core_lifecycle)
|
|
82
87
|
|
|
83
88
|
self.app.add_url_rule(
|
|
84
89
|
"/api/plug/<path:subpath>",
|
|
@@ -102,7 +107,7 @@ class AstrBotDashboard:
|
|
|
102
107
|
async def auth_middleware(self):
|
|
103
108
|
if not request.path.startswith("/api"):
|
|
104
109
|
return None
|
|
105
|
-
allowed_endpoints = ["/api/auth/login", "/api/file"]
|
|
110
|
+
allowed_endpoints = ["/api/auth/login", "/api/file", "/api/platform/webhook"]
|
|
106
111
|
if any(request.path.startswith(prefix) for prefix in allowed_endpoints):
|
|
107
112
|
return None
|
|
108
113
|
# 声明 JWT
|
|
@@ -145,7 +150,7 @@ class AstrBotDashboard:
|
|
|
145
150
|
"""获取占用端口的进程详细信息"""
|
|
146
151
|
try:
|
|
147
152
|
for conn in psutil.net_connections(kind="inet"):
|
|
148
|
-
if conn.laddr.port == port:
|
|
153
|
+
if cast(psutil_addr, conn.laddr).port == port:
|
|
149
154
|
try:
|
|
150
155
|
process = psutil.Process(conn.pid)
|
|
151
156
|
# 获取详细信息
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: AstrBot
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.9.0
|
|
4
4
|
Summary: Easy-to-use multi-platform LLM chatbot and development framework
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Keywords: Astrbot,Astrbot Module,Astrbot Plugin
|
|
@@ -61,11 +61,14 @@ Description-Content-Type: text/markdown
|
|
|
61
61
|
|
|
62
62
|

|
|
63
63
|
|
|
64
|
-
</p>
|
|
65
|
-
|
|
66
64
|
<div align="center">
|
|
67
65
|
|
|
68
|
-
|
|
66
|
+
|
|
67
|
+
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_en.md">English</a> |
|
|
68
|
+
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ja.md">日本語</a> |
|
|
69
|
+
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh-TW.md">繁體中文</a> |
|
|
70
|
+
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_fr.md">Français</a> |
|
|
71
|
+
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ru.md">Русский</a>
|
|
69
72
|
|
|
70
73
|
<div>
|
|
71
74
|
<a href="https://trendshift.io/repositories/12875" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12875" alt="Soulter%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
@@ -75,35 +78,38 @@ Description-Content-Type: text/markdown
|
|
|
75
78
|
<br>
|
|
76
79
|
|
|
77
80
|
<div>
|
|
78
|
-
<img src="https://img.shields.io/github/v/release/AstrBotDevs/AstrBot?
|
|
79
|
-
<img src="https://img.shields.io/badge/python-3.10+-blue.svg
|
|
80
|
-
<
|
|
81
|
-
<a href="https://
|
|
82
|
-
<a href="https://
|
|
83
|
-
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%E4%B8%AA&
|
|
81
|
+
<img src="https://img.shields.io/github/v/release/AstrBotDevs/AstrBot?color=76bad9" href="https://github.com/AstrBotDevs/AstrBot/releases/latest">
|
|
82
|
+
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
|
|
83
|
+
<img src="https://deepwiki.com/badge.svg" href="https://deepwiki.com/AstrBotDevs/AstrBot">
|
|
84
|
+
<a href="https://zread.ai/AstrBotDevs/AstrBot" target="_blank"><img src="https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff" alt="zread"/></a>
|
|
85
|
+
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg?color=76bad9"/></a>
|
|
86
|
+
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%E4%B8%AA&label=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&cacheSeconds=3600">
|
|
87
|
+
<img src="https://gitcode.com/Soulter/AstrBot/star/badge.svg" href="https://gitcode.com/Soulter/AstrBot">
|
|
84
88
|
</div>
|
|
85
89
|
|
|
86
90
|
<br>
|
|
87
91
|
|
|
88
|
-
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_en.md">English</a> |
|
|
89
|
-
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ja.md">日本語</a> |
|
|
90
92
|
<a href="https://astrbot.app/">文档</a> |
|
|
91
93
|
<a href="https://blog.astrbot.app/">Blog</a> |
|
|
92
94
|
<a href="https://astrbot.featurebase.app/roadmap">路线图</a> |
|
|
93
95
|
<a href="https://github.com/AstrBotDevs/AstrBot/issues">问题提交</a>
|
|
94
96
|
</div>
|
|
95
97
|
|
|
96
|
-
AstrBot 是一个开源的一站式 Agent
|
|
98
|
+
AstrBot 是一个开源的一站式 Agent 聊天机器人平台,可接入主流即时通讯软件,为个人、开发者和团队打造可靠、可扩展的对话式智能基础设施。无论是个人 AI 伙伴、智能客服、自动化助手,还是企业知识库,AstrBot 都能在你的即时通讯软件平台的工作流中快速构建生产可用的 AI 应用。
|
|
99
|
+
|
|
100
|
+
<img width="1776" height="1080" alt="image" src="https://github.com/user-attachments/assets/00782c4c-4437-4d97-aabc-605e3738da5c" />
|
|
97
101
|
|
|
98
102
|
## 主要功能
|
|
99
103
|
|
|
100
|
-
1.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
1. 💯 免费 & 开源。
|
|
105
|
+
1. ✨ AI 大模型对话,多模态,Agent,MCP,知识库,人格设定。
|
|
106
|
+
2. 🤖 支持接入 Dify、阿里云百炼、Coze 等智能体平台。
|
|
107
|
+
2. 🌐 多平台,支持 QQ、企业微信、飞书、钉钉、微信公众号、Telegram、Slack 以及[更多](#支持的消息平台)。
|
|
108
|
+
3. 📦 插件扩展,已有近 800 个插件可一键安装。
|
|
109
|
+
5. 💻 WebUI 支持。
|
|
110
|
+
6. 🌐 国际化(i18n)支持。
|
|
105
111
|
|
|
106
|
-
##
|
|
112
|
+
## 快速开始
|
|
107
113
|
|
|
108
114
|
#### Docker 部署(推荐 🥳)
|
|
109
115
|
|
|
@@ -111,6 +117,12 @@ AstrBot 是一个开源的一站式 Agent 聊天机器人平台,可无缝接
|
|
|
111
117
|
|
|
112
118
|
请参阅官方文档 [使用 Docker 部署 AstrBot](https://astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot) 。
|
|
113
119
|
|
|
120
|
+
#### uv 部署
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
uvx astrbot
|
|
124
|
+
```
|
|
125
|
+
|
|
114
126
|
#### 宝塔面板部署
|
|
115
127
|
|
|
116
128
|
AstrBot 与宝塔面板合作,已上架至宝塔面板。
|
|
@@ -162,24 +174,6 @@ uv run main.py
|
|
|
162
174
|
|
|
163
175
|
或者请参阅官方文档 [通过源码部署 AstrBot](https://astrbot.app/deploy/astrbot/cli.html) 。
|
|
164
176
|
|
|
165
|
-
## 🌍 社区
|
|
166
|
-
|
|
167
|
-
### QQ 群组
|
|
168
|
-
|
|
169
|
-
- 1 群:322154837
|
|
170
|
-
- 3 群:630166526
|
|
171
|
-
- 5 群:822130018
|
|
172
|
-
- 6 群:753075035
|
|
173
|
-
- 开发者群:975206796
|
|
174
|
-
|
|
175
|
-
### Telegram 群组
|
|
176
|
-
|
|
177
|
-
<a href="https://t.me/+hAsD2Ebl5as3NmY1"><img alt="Telegram_community" src="https://img.shields.io/badge/Telegram-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
|
|
178
|
-
|
|
179
|
-
### Discord 群组
|
|
180
|
-
|
|
181
|
-
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
|
|
182
|
-
|
|
183
177
|
## 支持的消息平台
|
|
184
178
|
|
|
185
179
|
**官方维护**
|
|
@@ -266,6 +260,25 @@ pip install pre-commit
|
|
|
266
260
|
pre-commit install
|
|
267
261
|
```
|
|
268
262
|
|
|
263
|
+
## 🌍 社区
|
|
264
|
+
|
|
265
|
+
### QQ 群组
|
|
266
|
+
|
|
267
|
+
- 1 群:322154837
|
|
268
|
+
- 3 群:630166526
|
|
269
|
+
- 5 群:822130018
|
|
270
|
+
- 6 群:753075035
|
|
271
|
+
- 7 群:743746109
|
|
272
|
+
- 开发者群:975206796
|
|
273
|
+
|
|
274
|
+
### Telegram 群组
|
|
275
|
+
|
|
276
|
+
<a href="https://t.me/+hAsD2Ebl5as3NmY1"><img alt="Telegram_community" src="https://img.shields.io/badge/Telegram-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
|
|
277
|
+
|
|
278
|
+
### Discord 群组
|
|
279
|
+
|
|
280
|
+
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
|
|
281
|
+
|
|
269
282
|
## ❤️ Special Thanks
|
|
270
283
|
|
|
271
284
|
特别感谢所有 Contributors 和插件开发者对 AstrBot 的贡献 ❤️
|