AstrBot 3.5.6__py3-none-any.whl → 4.7.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/api/__init__.py +16 -4
- astrbot/api/all.py +2 -1
- astrbot/api/event/__init__.py +5 -6
- astrbot/api/event/filter/__init__.py +37 -34
- astrbot/api/platform/__init__.py +7 -8
- astrbot/api/provider/__init__.py +8 -7
- astrbot/api/star/__init__.py +3 -4
- astrbot/api/util/__init__.py +2 -2
- astrbot/cli/__init__.py +1 -0
- astrbot/cli/__main__.py +18 -197
- astrbot/cli/commands/__init__.py +6 -0
- astrbot/cli/commands/cmd_conf.py +209 -0
- astrbot/cli/commands/cmd_init.py +56 -0
- astrbot/cli/commands/cmd_plug.py +245 -0
- astrbot/cli/commands/cmd_run.py +62 -0
- astrbot/cli/utils/__init__.py +18 -0
- astrbot/cli/utils/basic.py +76 -0
- astrbot/cli/utils/plugin.py +246 -0
- astrbot/cli/utils/version_comparator.py +90 -0
- astrbot/core/__init__.py +17 -19
- astrbot/core/agent/agent.py +14 -0
- astrbot/core/agent/handoff.py +38 -0
- astrbot/core/agent/hooks.py +30 -0
- astrbot/core/agent/mcp_client.py +385 -0
- astrbot/core/agent/message.py +175 -0
- astrbot/core/agent/response.py +14 -0
- astrbot/core/agent/run_context.py +22 -0
- astrbot/core/agent/runners/__init__.py +3 -0
- astrbot/core/agent/runners/base.py +65 -0
- astrbot/core/agent/runners/coze/coze_agent_runner.py +367 -0
- astrbot/core/agent/runners/coze/coze_api_client.py +324 -0
- astrbot/core/agent/runners/dashscope/dashscope_agent_runner.py +403 -0
- astrbot/core/agent/runners/dify/dify_agent_runner.py +336 -0
- astrbot/core/agent/runners/dify/dify_api_client.py +195 -0
- astrbot/core/agent/runners/tool_loop_agent_runner.py +400 -0
- astrbot/core/agent/tool.py +285 -0
- astrbot/core/agent/tool_executor.py +17 -0
- astrbot/core/astr_agent_context.py +19 -0
- astrbot/core/astr_agent_hooks.py +36 -0
- astrbot/core/astr_agent_run_util.py +80 -0
- astrbot/core/astr_agent_tool_exec.py +246 -0
- astrbot/core/astrbot_config_mgr.py +275 -0
- astrbot/core/config/__init__.py +2 -2
- astrbot/core/config/astrbot_config.py +60 -20
- astrbot/core/config/default.py +1972 -453
- astrbot/core/config/i18n_utils.py +110 -0
- astrbot/core/conversation_mgr.py +285 -75
- astrbot/core/core_lifecycle.py +167 -62
- astrbot/core/db/__init__.py +305 -102
- astrbot/core/db/migration/helper.py +69 -0
- astrbot/core/db/migration/migra_3_to_4.py +357 -0
- astrbot/core/db/migration/migra_45_to_46.py +44 -0
- astrbot/core/db/migration/migra_webchat_session.py +131 -0
- astrbot/core/db/migration/shared_preferences_v3.py +48 -0
- astrbot/core/db/migration/sqlite_v3.py +497 -0
- astrbot/core/db/po.py +259 -55
- astrbot/core/db/sqlite.py +773 -528
- astrbot/core/db/vec_db/base.py +73 -0
- astrbot/core/db/vec_db/faiss_impl/__init__.py +3 -0
- astrbot/core/db/vec_db/faiss_impl/document_storage.py +392 -0
- astrbot/core/db/vec_db/faiss_impl/embedding_storage.py +93 -0
- astrbot/core/db/vec_db/faiss_impl/sqlite_init.sql +17 -0
- astrbot/core/db/vec_db/faiss_impl/vec_db.py +204 -0
- astrbot/core/event_bus.py +26 -22
- astrbot/core/exceptions.py +9 -0
- astrbot/core/file_token_service.py +98 -0
- astrbot/core/initial_loader.py +19 -10
- astrbot/core/knowledge_base/chunking/__init__.py +9 -0
- astrbot/core/knowledge_base/chunking/base.py +25 -0
- astrbot/core/knowledge_base/chunking/fixed_size.py +59 -0
- astrbot/core/knowledge_base/chunking/recursive.py +161 -0
- astrbot/core/knowledge_base/kb_db_sqlite.py +301 -0
- astrbot/core/knowledge_base/kb_helper.py +642 -0
- astrbot/core/knowledge_base/kb_mgr.py +330 -0
- astrbot/core/knowledge_base/models.py +120 -0
- astrbot/core/knowledge_base/parsers/__init__.py +13 -0
- astrbot/core/knowledge_base/parsers/base.py +51 -0
- astrbot/core/knowledge_base/parsers/markitdown_parser.py +26 -0
- astrbot/core/knowledge_base/parsers/pdf_parser.py +101 -0
- astrbot/core/knowledge_base/parsers/text_parser.py +42 -0
- astrbot/core/knowledge_base/parsers/url_parser.py +103 -0
- astrbot/core/knowledge_base/parsers/util.py +13 -0
- astrbot/core/knowledge_base/prompts.py +65 -0
- astrbot/core/knowledge_base/retrieval/__init__.py +14 -0
- astrbot/core/knowledge_base/retrieval/hit_stopwords.txt +767 -0
- astrbot/core/knowledge_base/retrieval/manager.py +276 -0
- astrbot/core/knowledge_base/retrieval/rank_fusion.py +142 -0
- astrbot/core/knowledge_base/retrieval/sparse_retriever.py +136 -0
- astrbot/core/log.py +21 -15
- astrbot/core/message/components.py +413 -287
- astrbot/core/message/message_event_result.py +35 -24
- astrbot/core/persona_mgr.py +192 -0
- astrbot/core/pipeline/__init__.py +14 -14
- astrbot/core/pipeline/content_safety_check/stage.py +13 -9
- astrbot/core/pipeline/content_safety_check/strategies/__init__.py +1 -2
- astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py +13 -14
- astrbot/core/pipeline/content_safety_check/strategies/keywords.py +2 -1
- astrbot/core/pipeline/content_safety_check/strategies/strategy.py +6 -6
- astrbot/core/pipeline/context.py +7 -1
- astrbot/core/pipeline/context_utils.py +107 -0
- astrbot/core/pipeline/preprocess_stage/stage.py +63 -36
- astrbot/core/pipeline/process_stage/method/agent_request.py +48 -0
- astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py +464 -0
- astrbot/core/pipeline/process_stage/method/agent_sub_stages/third_party.py +202 -0
- astrbot/core/pipeline/process_stage/method/star_request.py +26 -32
- astrbot/core/pipeline/process_stage/stage.py +21 -15
- astrbot/core/pipeline/process_stage/utils.py +125 -0
- astrbot/core/pipeline/rate_limit_check/stage.py +34 -36
- astrbot/core/pipeline/respond/stage.py +142 -101
- astrbot/core/pipeline/result_decorate/stage.py +124 -57
- astrbot/core/pipeline/scheduler.py +21 -16
- astrbot/core/pipeline/session_status_check/stage.py +37 -0
- astrbot/core/pipeline/stage.py +11 -76
- astrbot/core/pipeline/waking_check/stage.py +69 -33
- astrbot/core/pipeline/whitelist_check/stage.py +10 -7
- astrbot/core/platform/__init__.py +6 -6
- astrbot/core/platform/astr_message_event.py +107 -129
- astrbot/core/platform/astrbot_message.py +32 -12
- astrbot/core/platform/manager.py +62 -18
- astrbot/core/platform/message_session.py +30 -0
- astrbot/core/platform/platform.py +16 -24
- astrbot/core/platform/platform_metadata.py +9 -4
- astrbot/core/platform/register.py +12 -7
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +136 -60
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +126 -46
- astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py +63 -31
- astrbot/core/platform/sources/dingtalk/dingtalk_event.py +30 -26
- astrbot/core/platform/sources/discord/client.py +129 -0
- astrbot/core/platform/sources/discord/components.py +139 -0
- astrbot/core/platform/sources/discord/discord_platform_adapter.py +473 -0
- astrbot/core/platform/sources/discord/discord_platform_event.py +313 -0
- astrbot/core/platform/sources/lark/lark_adapter.py +27 -18
- astrbot/core/platform/sources/lark/lark_event.py +39 -13
- astrbot/core/platform/sources/misskey/misskey_adapter.py +770 -0
- astrbot/core/platform/sources/misskey/misskey_api.py +964 -0
- astrbot/core/platform/sources/misskey/misskey_event.py +163 -0
- astrbot/core/platform/sources/misskey/misskey_utils.py +550 -0
- astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py +149 -33
- astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py +41 -26
- astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py +36 -17
- astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_event.py +3 -1
- astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_server.py +14 -8
- astrbot/core/platform/sources/satori/satori_adapter.py +792 -0
- astrbot/core/platform/sources/satori/satori_event.py +432 -0
- astrbot/core/platform/sources/slack/client.py +164 -0
- astrbot/core/platform/sources/slack/slack_adapter.py +416 -0
- astrbot/core/platform/sources/slack/slack_event.py +253 -0
- astrbot/core/platform/sources/telegram/tg_adapter.py +100 -43
- astrbot/core/platform/sources/telegram/tg_event.py +136 -36
- astrbot/core/platform/sources/webchat/webchat_adapter.py +72 -22
- astrbot/core/platform/sources/webchat/webchat_event.py +46 -22
- astrbot/core/platform/sources/webchat/webchat_queue_mgr.py +35 -0
- astrbot/core/platform/sources/wechatpadpro/wechatpadpro_adapter.py +926 -0
- astrbot/core/platform/sources/wechatpadpro/wechatpadpro_message_event.py +178 -0
- astrbot/core/platform/sources/wechatpadpro/xml_data_parser.py +159 -0
- astrbot/core/platform/sources/wecom/wecom_adapter.py +169 -27
- astrbot/core/platform/sources/wecom/wecom_event.py +162 -77
- astrbot/core/platform/sources/wecom/wecom_kf.py +279 -0
- astrbot/core/platform/sources/wecom/wecom_kf_message.py +196 -0
- astrbot/core/platform/sources/wecom_ai_bot/WXBizJsonMsgCrypt.py +297 -0
- astrbot/core/platform/sources/wecom_ai_bot/__init__.py +15 -0
- astrbot/core/platform/sources/wecom_ai_bot/ierror.py +19 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_adapter.py +472 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_api.py +417 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_event.py +152 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_queue_mgr.py +153 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_server.py +168 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_utils.py +209 -0
- astrbot/core/platform/sources/weixin_official_account/weixin_offacc_adapter.py +306 -0
- astrbot/core/platform/sources/weixin_official_account/weixin_offacc_event.py +186 -0
- astrbot/core/platform_message_history_mgr.py +49 -0
- astrbot/core/provider/__init__.py +2 -3
- astrbot/core/provider/entites.py +8 -8
- astrbot/core/provider/entities.py +154 -98
- astrbot/core/provider/func_tool_manager.py +446 -458
- astrbot/core/provider/manager.py +345 -207
- astrbot/core/provider/provider.py +188 -73
- astrbot/core/provider/register.py +9 -7
- astrbot/core/provider/sources/anthropic_source.py +295 -115
- astrbot/core/provider/sources/azure_tts_source.py +224 -0
- astrbot/core/provider/sources/bailian_rerank_source.py +236 -0
- astrbot/core/provider/sources/dashscope_tts.py +138 -14
- astrbot/core/provider/sources/edge_tts_source.py +24 -19
- astrbot/core/provider/sources/fishaudio_tts_api_source.py +58 -13
- astrbot/core/provider/sources/gemini_embedding_source.py +61 -0
- astrbot/core/provider/sources/gemini_source.py +310 -132
- astrbot/core/provider/sources/gemini_tts_source.py +81 -0
- astrbot/core/provider/sources/groq_source.py +15 -0
- astrbot/core/provider/sources/gsv_selfhosted_source.py +151 -0
- astrbot/core/provider/sources/gsvi_tts_source.py +14 -7
- astrbot/core/provider/sources/minimax_tts_api_source.py +159 -0
- astrbot/core/provider/sources/openai_embedding_source.py +40 -0
- astrbot/core/provider/sources/openai_source.py +241 -145
- astrbot/core/provider/sources/openai_tts_api_source.py +18 -7
- astrbot/core/provider/sources/sensevoice_selfhosted_source.py +13 -11
- astrbot/core/provider/sources/vllm_rerank_source.py +71 -0
- astrbot/core/provider/sources/volcengine_tts.py +115 -0
- astrbot/core/provider/sources/whisper_api_source.py +18 -13
- astrbot/core/provider/sources/whisper_selfhosted_source.py +19 -12
- astrbot/core/provider/sources/xinference_rerank_source.py +116 -0
- astrbot/core/provider/sources/xinference_stt_provider.py +197 -0
- astrbot/core/provider/sources/zhipu_source.py +6 -73
- astrbot/core/star/__init__.py +43 -11
- astrbot/core/star/config.py +17 -18
- astrbot/core/star/context.py +362 -138
- astrbot/core/star/filter/__init__.py +4 -3
- astrbot/core/star/filter/command.py +111 -35
- astrbot/core/star/filter/command_group.py +46 -34
- astrbot/core/star/filter/custom_filter.py +6 -5
- astrbot/core/star/filter/event_message_type.py +4 -2
- astrbot/core/star/filter/permission.py +4 -2
- astrbot/core/star/filter/platform_adapter_type.py +45 -12
- astrbot/core/star/filter/regex.py +4 -2
- astrbot/core/star/register/__init__.py +19 -15
- astrbot/core/star/register/star.py +41 -13
- astrbot/core/star/register/star_handler.py +236 -86
- astrbot/core/star/session_llm_manager.py +280 -0
- astrbot/core/star/session_plugin_manager.py +170 -0
- astrbot/core/star/star.py +36 -43
- astrbot/core/star/star_handler.py +47 -85
- astrbot/core/star/star_manager.py +442 -260
- astrbot/core/star/star_tools.py +167 -45
- astrbot/core/star/updator.py +17 -20
- astrbot/core/umop_config_router.py +106 -0
- astrbot/core/updator.py +38 -13
- astrbot/core/utils/astrbot_path.py +39 -0
- astrbot/core/utils/command_parser.py +1 -1
- astrbot/core/utils/io.py +119 -60
- astrbot/core/utils/log_pipe.py +1 -1
- astrbot/core/utils/metrics.py +11 -10
- astrbot/core/utils/migra_helper.py +73 -0
- astrbot/core/utils/path_util.py +63 -62
- astrbot/core/utils/pip_installer.py +37 -15
- astrbot/core/utils/session_lock.py +29 -0
- astrbot/core/utils/session_waiter.py +19 -20
- astrbot/core/utils/shared_preferences.py +174 -34
- astrbot/core/utils/t2i/__init__.py +4 -1
- astrbot/core/utils/t2i/local_strategy.py +386 -238
- astrbot/core/utils/t2i/network_strategy.py +109 -49
- astrbot/core/utils/t2i/renderer.py +29 -14
- astrbot/core/utils/t2i/template/astrbot_powershell.html +184 -0
- astrbot/core/utils/t2i/template_manager.py +111 -0
- astrbot/core/utils/tencent_record_helper.py +115 -1
- astrbot/core/utils/version_comparator.py +10 -13
- astrbot/core/zip_updator.py +112 -65
- astrbot/dashboard/routes/__init__.py +20 -13
- astrbot/dashboard/routes/auth.py +20 -9
- astrbot/dashboard/routes/chat.py +297 -141
- astrbot/dashboard/routes/config.py +652 -55
- astrbot/dashboard/routes/conversation.py +107 -37
- astrbot/dashboard/routes/file.py +26 -0
- astrbot/dashboard/routes/knowledge_base.py +1244 -0
- astrbot/dashboard/routes/log.py +27 -2
- astrbot/dashboard/routes/persona.py +202 -0
- astrbot/dashboard/routes/plugin.py +197 -139
- astrbot/dashboard/routes/route.py +27 -7
- astrbot/dashboard/routes/session_management.py +354 -0
- astrbot/dashboard/routes/stat.py +85 -18
- astrbot/dashboard/routes/static_file.py +5 -2
- astrbot/dashboard/routes/t2i.py +233 -0
- astrbot/dashboard/routes/tools.py +184 -120
- astrbot/dashboard/routes/update.py +59 -36
- astrbot/dashboard/server.py +96 -36
- astrbot/dashboard/utils.py +165 -0
- astrbot-4.7.0.dist-info/METADATA +294 -0
- astrbot-4.7.0.dist-info/RECORD +274 -0
- {astrbot-3.5.6.dist-info → astrbot-4.7.0.dist-info}/WHEEL +1 -1
- astrbot/core/db/plugin/sqlite_impl.py +0 -112
- astrbot/core/db/sqlite_init.sql +0 -50
- astrbot/core/pipeline/platform_compatibility/stage.py +0 -56
- astrbot/core/pipeline/process_stage/method/llm_request.py +0 -606
- astrbot/core/platform/sources/gewechat/client.py +0 -806
- astrbot/core/platform/sources/gewechat/downloader.py +0 -55
- astrbot/core/platform/sources/gewechat/gewechat_event.py +0 -255
- astrbot/core/platform/sources/gewechat/gewechat_platform_adapter.py +0 -103
- astrbot/core/platform/sources/gewechat/xml_data_parser.py +0 -110
- astrbot/core/provider/sources/dashscope_source.py +0 -203
- astrbot/core/provider/sources/dify_source.py +0 -281
- astrbot/core/provider/sources/llmtuner_source.py +0 -132
- astrbot/core/rag/embedding/openai_source.py +0 -20
- astrbot/core/rag/knowledge_db_mgr.py +0 -94
- astrbot/core/rag/store/__init__.py +0 -9
- astrbot/core/rag/store/chroma_db.py +0 -42
- astrbot/core/utils/dify_api_client.py +0 -152
- astrbot-3.5.6.dist-info/METADATA +0 -249
- astrbot-3.5.6.dist-info/RECORD +0 -158
- {astrbot-3.5.6.dist-info → astrbot-4.7.0.dist-info}/entry_points.txt +0 -0
- {astrbot-3.5.6.dist-info → astrbot-4.7.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -38,15 +38,15 @@ class VersionComparator:
|
|
|
38
38
|
for i in range(length):
|
|
39
39
|
if v1_parts[i] > v2_parts[i]:
|
|
40
40
|
return 1
|
|
41
|
-
|
|
41
|
+
if v1_parts[i] < v2_parts[i]:
|
|
42
42
|
return -1
|
|
43
43
|
|
|
44
44
|
# 比较预发布标签
|
|
45
45
|
if v1_prerelease is None and v2_prerelease is not None:
|
|
46
46
|
return 1 # 没有预发布标签的版本高于有预发布标签的版本
|
|
47
|
-
|
|
47
|
+
if v1_prerelease is not None and v2_prerelease is None:
|
|
48
48
|
return -1 # 有预发布标签的版本低于没有预发布标签的版本
|
|
49
|
-
|
|
49
|
+
if v1_prerelease is not None and v2_prerelease is not None:
|
|
50
50
|
len_pre = max(len(v1_prerelease), len(v2_prerelease))
|
|
51
51
|
for i in range(len_pre):
|
|
52
52
|
p1 = v1_prerelease[i] if i < len(v1_prerelease) else None
|
|
@@ -54,21 +54,18 @@ class VersionComparator:
|
|
|
54
54
|
|
|
55
55
|
if p1 is None and p2 is not None:
|
|
56
56
|
return -1
|
|
57
|
-
|
|
57
|
+
if p1 is not None and p2 is None:
|
|
58
58
|
return 1
|
|
59
|
-
|
|
59
|
+
if isinstance(p1, int) and isinstance(p2, str):
|
|
60
60
|
return -1
|
|
61
|
-
|
|
61
|
+
if isinstance(p1, str) and isinstance(p2, int):
|
|
62
62
|
return 1
|
|
63
|
-
|
|
63
|
+
if (isinstance(p1, int) and isinstance(p2, int)) or (
|
|
64
|
+
isinstance(p1, str) and isinstance(p2, str)
|
|
65
|
+
):
|
|
64
66
|
if p1 > p2:
|
|
65
67
|
return 1
|
|
66
|
-
|
|
67
|
-
return -1
|
|
68
|
-
elif isinstance(p1, str) and isinstance(p2, str):
|
|
69
|
-
if p1 > p2:
|
|
70
|
-
return 1
|
|
71
|
-
elif p1 < p2:
|
|
68
|
+
if p1 < p2:
|
|
72
69
|
return -1
|
|
73
70
|
return 0 # 预发布标签完全相同
|
|
74
71
|
|
astrbot/core/zip_updator.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import aiohttp
|
|
2
1
|
import os
|
|
3
|
-
import
|
|
2
|
+
import re
|
|
4
3
|
import shutil
|
|
5
|
-
|
|
6
4
|
import ssl
|
|
5
|
+
import zipfile
|
|
6
|
+
|
|
7
|
+
import aiohttp
|
|
7
8
|
import certifi
|
|
8
9
|
|
|
9
|
-
from astrbot.core.utils.io import on_error, download_file
|
|
10
10
|
from astrbot.core import logger
|
|
11
|
+
from astrbot.core.utils.io import download_file, on_error
|
|
11
12
|
from astrbot.core.utils.version_comparator import VersionComparator
|
|
12
13
|
|
|
13
14
|
|
|
@@ -17,7 +18,10 @@ class ReleaseInfo:
|
|
|
17
18
|
body: str
|
|
18
19
|
|
|
19
20
|
def __init__(
|
|
20
|
-
self,
|
|
21
|
+
self,
|
|
22
|
+
version: str = "",
|
|
23
|
+
published_at: str = "",
|
|
24
|
+
body: str = "",
|
|
21
25
|
) -> None:
|
|
22
26
|
self.version = version
|
|
23
27
|
self.published_at = published_at
|
|
@@ -33,29 +37,31 @@ class RepoZipUpdator:
|
|
|
33
37
|
self.rm_on_error = on_error
|
|
34
38
|
|
|
35
39
|
async def fetch_release_info(self, url: str, latest: bool = True) -> list:
|
|
36
|
-
"""
|
|
37
|
-
请求版本信息。
|
|
40
|
+
"""请求版本信息。
|
|
38
41
|
返回一个列表,每个元素是一个字典,包含版本号、发布时间、更新内容、commit hash等信息。
|
|
39
42
|
"""
|
|
40
43
|
try:
|
|
41
44
|
ssl_context = ssl.create_default_context(
|
|
42
|
-
cafile=certifi.where()
|
|
45
|
+
cafile=certifi.where(),
|
|
43
46
|
) # 新增:创建基于 certifi 的 SSL 上下文
|
|
44
47
|
connector = aiohttp.TCPConnector(
|
|
45
|
-
ssl=ssl_context
|
|
48
|
+
ssl=ssl_context,
|
|
46
49
|
) # 新增:使用 TCPConnector 指定 SSL 上下文
|
|
47
|
-
async with
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
async with (
|
|
51
|
+
aiohttp.ClientSession(
|
|
52
|
+
trust_env=True,
|
|
53
|
+
connector=connector,
|
|
54
|
+
) as session,
|
|
55
|
+
session.get(url) as response,
|
|
56
|
+
):
|
|
57
|
+
# 检查 HTTP 状态码
|
|
58
|
+
if response.status != 200:
|
|
59
|
+
text = await response.text()
|
|
60
|
+
logger.error(
|
|
61
|
+
f"请求 {url} 失败,状态码: {response.status}, 内容: {text}",
|
|
62
|
+
)
|
|
63
|
+
raise Exception(f"请求失败,状态码: {response.status}")
|
|
64
|
+
result = await response.json()
|
|
59
65
|
if not result:
|
|
60
66
|
return []
|
|
61
67
|
# if latest:
|
|
@@ -71,7 +77,7 @@ class RepoZipUpdator:
|
|
|
71
77
|
"body": release["body"],
|
|
72
78
|
"tag_name": release["tag_name"],
|
|
73
79
|
"zipball_url": release["zipball_url"],
|
|
74
|
-
}
|
|
80
|
+
},
|
|
75
81
|
)
|
|
76
82
|
except Exception as e:
|
|
77
83
|
logger.error(f"解析版本信息时发生异常: {e}")
|
|
@@ -79,8 +85,7 @@ class RepoZipUpdator:
|
|
|
79
85
|
return ret
|
|
80
86
|
|
|
81
87
|
def github_api_release_parser(self, releases: list) -> list:
|
|
82
|
-
"""
|
|
83
|
-
解析 GitHub API 返回的 releases 信息。
|
|
88
|
+
"""解析 GitHub API 返回的 releases 信息。
|
|
84
89
|
返回一个列表,每个元素是一个字典,包含版本号、发布时间、更新内容、commit hash等信息。
|
|
85
90
|
"""
|
|
86
91
|
ret = []
|
|
@@ -92,98 +97,140 @@ class RepoZipUpdator:
|
|
|
92
97
|
"body": release["body"],
|
|
93
98
|
"tag_name": release["tag_name"],
|
|
94
99
|
"zipball_url": release["zipball_url"],
|
|
95
|
-
}
|
|
100
|
+
},
|
|
96
101
|
)
|
|
97
102
|
return ret
|
|
98
103
|
|
|
99
104
|
def unzip(self):
|
|
100
|
-
raise NotImplementedError
|
|
105
|
+
raise NotImplementedError
|
|
101
106
|
|
|
102
107
|
async def update(self):
|
|
103
|
-
raise NotImplementedError
|
|
108
|
+
raise NotImplementedError
|
|
104
109
|
|
|
105
110
|
def compare_version(self, v1: str, v2: str) -> int:
|
|
106
111
|
"""Semver 版本比较"""
|
|
107
112
|
return VersionComparator.compare_version(v1, v2)
|
|
108
113
|
|
|
109
|
-
async def check_update(
|
|
114
|
+
async def check_update(
|
|
115
|
+
self,
|
|
116
|
+
url: str,
|
|
117
|
+
current_version: str,
|
|
118
|
+
consider_prerelease: bool = True,
|
|
119
|
+
) -> ReleaseInfo | None:
|
|
110
120
|
update_data = await self.fetch_release_info(url)
|
|
111
|
-
|
|
121
|
+
|
|
122
|
+
sel_release_data = None
|
|
123
|
+
if consider_prerelease:
|
|
124
|
+
tag_name = update_data[0]["tag_name"]
|
|
125
|
+
sel_release_data = update_data[0]
|
|
126
|
+
else:
|
|
127
|
+
for data in update_data:
|
|
128
|
+
# 跳过带有 alpha、beta 等预发布标签的版本
|
|
129
|
+
if re.search(
|
|
130
|
+
r"[\-_.]?(alpha|beta|rc|dev)[\-_.]?\d*$",
|
|
131
|
+
data["tag_name"],
|
|
132
|
+
re.IGNORECASE,
|
|
133
|
+
):
|
|
134
|
+
continue
|
|
135
|
+
tag_name = data["tag_name"]
|
|
136
|
+
sel_release_data = data
|
|
137
|
+
break
|
|
138
|
+
|
|
139
|
+
if not sel_release_data or not tag_name:
|
|
140
|
+
logger.error("未找到合适的发布版本")
|
|
141
|
+
return None
|
|
112
142
|
|
|
113
143
|
if self.compare_version(current_version, tag_name) >= 0:
|
|
114
144
|
return None
|
|
115
145
|
return ReleaseInfo(
|
|
116
146
|
version=tag_name,
|
|
117
|
-
published_at=
|
|
118
|
-
body=
|
|
147
|
+
published_at=sel_release_data["published_at"],
|
|
148
|
+
body=f"{tag_name}\n\n{sel_release_data['body']}",
|
|
119
149
|
)
|
|
120
150
|
|
|
121
151
|
async def download_from_repo_url(self, target_path: str, repo_url: str, proxy=""):
|
|
122
|
-
|
|
123
|
-
author = repo_namespace[0]
|
|
124
|
-
repo = repo_namespace[1]
|
|
152
|
+
author, repo, branch = self.parse_github_url(repo_url)
|
|
125
153
|
|
|
126
154
|
logger.info(f"正在下载更新 {repo} ...")
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
# download from the default branch directly.
|
|
131
|
-
logger.info(f"正在从默认分支下载 {author}/{repo} ")
|
|
155
|
+
|
|
156
|
+
if branch:
|
|
157
|
+
logger.info(f"正在从指定分支 {branch} 下载 {author}/{repo}")
|
|
132
158
|
release_url = (
|
|
133
|
-
f"https://github.com/{author}/{repo}/archive/refs/heads/
|
|
159
|
+
f"https://github.com/{author}/{repo}/archive/refs/heads/{branch}.zip"
|
|
134
160
|
)
|
|
135
161
|
else:
|
|
136
|
-
|
|
162
|
+
try:
|
|
163
|
+
release_url = f"https://api.github.com/repos/{author}/{repo}/releases"
|
|
164
|
+
releases = await self.fetch_release_info(url=release_url)
|
|
165
|
+
except Exception as e:
|
|
166
|
+
logger.warning(
|
|
167
|
+
f"获取 {author}/{repo} 的 GitHub Releases 失败: {e},将尝试下载默认分支",
|
|
168
|
+
)
|
|
169
|
+
releases = []
|
|
170
|
+
if not releases:
|
|
171
|
+
# 如果没有最新版本,下载默认分支
|
|
172
|
+
logger.info(f"正在从默认分支下载 {author}/{repo}")
|
|
173
|
+
release_url = (
|
|
174
|
+
f"https://github.com/{author}/{repo}/archive/refs/heads/master.zip"
|
|
175
|
+
)
|
|
176
|
+
else:
|
|
177
|
+
release_url = releases[0]["zipball_url"]
|
|
137
178
|
|
|
138
179
|
if proxy:
|
|
180
|
+
proxy = proxy.rstrip("/")
|
|
139
181
|
release_url = f"{proxy}/{release_url}"
|
|
140
|
-
logger.info(
|
|
182
|
+
logger.info(
|
|
183
|
+
f"检查到设置了镜像站,将使用镜像站下载 {author}/{repo} 仓库源码: {release_url}",
|
|
184
|
+
)
|
|
141
185
|
|
|
142
186
|
await download_file(release_url, target_path + ".zip")
|
|
143
187
|
|
|
144
|
-
def
|
|
145
|
-
"""
|
|
146
|
-
|
|
188
|
+
def parse_github_url(self, url: str):
|
|
189
|
+
"""使用正则表达式解析 GitHub 仓库 URL,支持 `.git` 后缀和 `tree/branch` 结构
|
|
190
|
+
Returns:
|
|
191
|
+
tuple[str, str, str]: 返回作者名、仓库名和分支名
|
|
192
|
+
Raises:
|
|
193
|
+
ValueError: 如果 URL 格式不正确
|
|
147
194
|
"""
|
|
195
|
+
cleaned_url = url.rstrip("/")
|
|
196
|
+
pattern = r"^https://github\.com/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)(\.git)?(?:/tree/([a-zA-Z0-9_-]+))?$"
|
|
197
|
+
match = re.match(pattern, cleaned_url)
|
|
198
|
+
|
|
199
|
+
if match:
|
|
200
|
+
author = match.group(1)
|
|
201
|
+
repo = match.group(2)
|
|
202
|
+
branch = match.group(4)
|
|
203
|
+
return author, repo, branch
|
|
204
|
+
raise ValueError("无效的 GitHub URL")
|
|
205
|
+
|
|
206
|
+
def unzip_file(self, zip_path: str, target_dir: str):
|
|
207
|
+
"""解压缩文件, 并将压缩包内**第一个**文件夹内的文件移动到 target_dir"""
|
|
148
208
|
os.makedirs(target_dir, exist_ok=True)
|
|
149
209
|
update_dir = ""
|
|
150
|
-
logger.info(f"解压文件: {zip_path}")
|
|
151
210
|
with zipfile.ZipFile(zip_path, "r") as z:
|
|
152
211
|
update_dir = z.namelist()[0]
|
|
153
212
|
z.extractall(target_dir)
|
|
213
|
+
logger.debug(f"解压文件完成: {zip_path}")
|
|
154
214
|
|
|
155
215
|
files = os.listdir(os.path.join(target_dir, update_dir))
|
|
156
216
|
for f in files:
|
|
157
|
-
logger.info(f"移动更新文件/目录: {f}")
|
|
158
217
|
if os.path.isdir(os.path.join(target_dir, update_dir, f)):
|
|
159
218
|
if os.path.exists(os.path.join(target_dir, f)):
|
|
160
219
|
shutil.rmtree(os.path.join(target_dir, f), onerror=on_error)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
os.remove(os.path.join(target_dir, f))
|
|
220
|
+
elif os.path.exists(os.path.join(target_dir, f)):
|
|
221
|
+
os.remove(os.path.join(target_dir, f))
|
|
164
222
|
shutil.move(os.path.join(target_dir, update_dir, f), target_dir)
|
|
165
223
|
|
|
166
224
|
try:
|
|
167
|
-
logger.
|
|
168
|
-
f"删除临时更新文件: {zip_path} 和 {os.path.join(target_dir, update_dir)}"
|
|
225
|
+
logger.debug(
|
|
226
|
+
f"删除临时更新文件: {zip_path} 和 {os.path.join(target_dir, update_dir)}",
|
|
169
227
|
)
|
|
170
228
|
shutil.rmtree(os.path.join(target_dir, update_dir), onerror=on_error)
|
|
171
229
|
os.remove(zip_path)
|
|
172
230
|
except BaseException:
|
|
173
|
-
logger.
|
|
174
|
-
f"删除更新文件失败,可以手动删除 {zip_path} 和 {os.path.join(target_dir, update_dir)}"
|
|
231
|
+
logger.warning(
|
|
232
|
+
f"删除更新文件失败,可以手动删除 {zip_path} 和 {os.path.join(target_dir, update_dir)}",
|
|
175
233
|
)
|
|
176
234
|
|
|
177
|
-
def format_repo_name(self, repo_url: str) -> str:
|
|
178
|
-
if repo_url.endswith("/"):
|
|
179
|
-
repo_url = repo_url[:-1]
|
|
180
|
-
|
|
181
|
-
repo_namespace = repo_url.split("/")[-2:]
|
|
182
|
-
repo = repo_namespace[1]
|
|
183
|
-
|
|
184
|
-
repo = self.format_name(repo)
|
|
185
|
-
|
|
186
|
-
return repo
|
|
187
|
-
|
|
188
235
|
def format_name(self, name: str) -> str:
|
|
189
236
|
return name.replace("-", "_").lower()
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
from .auth import AuthRoute
|
|
2
|
-
from .
|
|
2
|
+
from .chat import ChatRoute
|
|
3
3
|
from .config import ConfigRoute
|
|
4
|
-
from .
|
|
5
|
-
from .
|
|
4
|
+
from .conversation import ConversationRoute
|
|
5
|
+
from .file import FileRoute
|
|
6
|
+
from .knowledge_base import KnowledgeBaseRoute
|
|
6
7
|
from .log import LogRoute
|
|
8
|
+
from .persona import PersonaRoute
|
|
9
|
+
from .plugin import PluginRoute
|
|
10
|
+
from .session_management import SessionManagementRoute
|
|
11
|
+
from .stat import StatRoute
|
|
7
12
|
from .static_file import StaticFileRoute
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
10
|
-
from .conversation import ConversationRoute
|
|
11
|
-
|
|
13
|
+
from .tools import ToolsRoute
|
|
14
|
+
from .update import UpdateRoute
|
|
12
15
|
|
|
13
16
|
__all__ = [
|
|
14
17
|
"AuthRoute",
|
|
15
|
-
"
|
|
18
|
+
"ChatRoute",
|
|
16
19
|
"ConfigRoute",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
20
|
+
"ConversationRoute",
|
|
21
|
+
"FileRoute",
|
|
22
|
+
"KnowledgeBaseRoute",
|
|
19
23
|
"LogRoute",
|
|
24
|
+
"PersonaRoute",
|
|
25
|
+
"PluginRoute",
|
|
26
|
+
"SessionManagementRoute",
|
|
27
|
+
"StatRoute",
|
|
20
28
|
"StaticFileRoute",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"ConversationRoute",
|
|
29
|
+
"ToolsRoute",
|
|
30
|
+
"UpdateRoute",
|
|
24
31
|
]
|
astrbot/dashboard/routes/auth.py
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import asyncio
|
|
2
2
|
import datetime
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
import jwt
|
|
4
5
|
from quart import request
|
|
5
|
-
|
|
6
|
+
|
|
6
7
|
from astrbot import logger
|
|
8
|
+
from astrbot.core import DEMO_MODE
|
|
9
|
+
|
|
10
|
+
from .route import Response, Route, RouteContext
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
class AuthRoute(Route):
|
|
@@ -21,7 +25,11 @@ class AuthRoute(Route):
|
|
|
21
25
|
post_data = await request.json
|
|
22
26
|
if post_data["username"] == username and post_data["password"] == password:
|
|
23
27
|
change_pwd_hint = False
|
|
24
|
-
if
|
|
28
|
+
if (
|
|
29
|
+
username == "astrbot"
|
|
30
|
+
and password == "77b90590a8945a7d36c963981a307dc9"
|
|
31
|
+
and not DEMO_MODE
|
|
32
|
+
):
|
|
25
33
|
change_pwd_hint = True
|
|
26
34
|
logger.warning("为了保证安全,请尽快修改默认密码。")
|
|
27
35
|
|
|
@@ -32,12 +40,12 @@ class AuthRoute(Route):
|
|
|
32
40
|
"token": self.generate_jwt(username),
|
|
33
41
|
"username": username,
|
|
34
42
|
"change_pwd_hint": change_pwd_hint,
|
|
35
|
-
}
|
|
43
|
+
},
|
|
36
44
|
)
|
|
37
45
|
.__dict__
|
|
38
46
|
)
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
await asyncio.sleep(3)
|
|
48
|
+
return Response().error("用户名或密码错误").__dict__
|
|
41
49
|
|
|
42
50
|
async def edit_account(self):
|
|
43
51
|
if DEMO_MODE:
|
|
@@ -72,7 +80,10 @@ class AuthRoute(Route):
|
|
|
72
80
|
def generate_jwt(self, username):
|
|
73
81
|
payload = {
|
|
74
82
|
"username": username,
|
|
75
|
-
"exp": datetime.datetime.utcnow() + datetime.timedelta(days=
|
|
83
|
+
"exp": datetime.datetime.utcnow() + datetime.timedelta(days=7),
|
|
76
84
|
}
|
|
77
|
-
|
|
85
|
+
jwt_token = self.config["dashboard"].get("jwt_secret", None)
|
|
86
|
+
if not jwt_token:
|
|
87
|
+
raise ValueError("JWT secret is not set in the cmd_config.")
|
|
88
|
+
token = jwt.encode(payload, jwt_token, algorithm="HS256")
|
|
78
89
|
return token
|