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
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
"""
|
|
2
|
-
会话控制
|
|
3
|
-
"""
|
|
1
|
+
"""会话控制"""
|
|
4
2
|
|
|
5
3
|
import abc
|
|
6
4
|
import asyncio
|
|
7
|
-
import time
|
|
8
|
-
import functools
|
|
9
5
|
import copy
|
|
6
|
+
import functools
|
|
7
|
+
import time
|
|
8
|
+
from collections.abc import Awaitable, Callable
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
10
11
|
import astrbot.core.message.components as Comp
|
|
11
|
-
from typing import Dict, Any, Callable, Awaitable, List
|
|
12
12
|
from astrbot.core.platform import AstrMessageEvent
|
|
13
13
|
|
|
14
|
-
USER_SESSIONS:
|
|
15
|
-
FILTERS:
|
|
14
|
+
USER_SESSIONS: dict[str, "SessionWaiter"] = {} # 存储 SessionWaiter 实例
|
|
15
|
+
FILTERS: list["SessionFilter"] = [] # 存储 SessionFilter 实例
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class SessionController:
|
|
19
|
-
"""
|
|
20
|
-
控制一个 Session 是否已经结束
|
|
21
|
-
"""
|
|
19
|
+
"""控制一个 Session 是否已经结束"""
|
|
22
20
|
|
|
23
21
|
def __init__(self):
|
|
24
22
|
self.future = asyncio.Future()
|
|
@@ -29,7 +27,7 @@ class SessionController:
|
|
|
29
27
|
self.timeout: float | int = None
|
|
30
28
|
"""上次保持(keep)开始时的超时时间"""
|
|
31
29
|
|
|
32
|
-
self.history_chains:
|
|
30
|
+
self.history_chains: list[list[Comp.BaseMessageComponent]] = []
|
|
33
31
|
|
|
34
32
|
def stop(self, error: Exception = None):
|
|
35
33
|
"""立即结束这个会话"""
|
|
@@ -39,13 +37,14 @@ class SessionController:
|
|
|
39
37
|
else:
|
|
40
38
|
self.future.set_result(None)
|
|
41
39
|
|
|
42
|
-
def keep(self, timeout: float
|
|
40
|
+
def keep(self, timeout: float = 0, reset_timeout=False):
|
|
43
41
|
"""保持这个会话
|
|
44
42
|
|
|
45
43
|
Args:
|
|
46
44
|
timeout (float): 必填。会话超时时间。
|
|
47
45
|
当 reset_timeout 设置为 True 时, 代表重置超时时间, timeout 必须 > 0, 如果 <= 0 则立即结束会话。
|
|
48
46
|
当 reset_timeout 设置为 False 时, 代表继续维持原来的超时时间, 新 timeout = 原来剩余的timeout + timeout (可以 < 0)
|
|
47
|
+
|
|
49
48
|
"""
|
|
50
49
|
new_ts = time.time()
|
|
51
50
|
|
|
@@ -81,7 +80,7 @@ class SessionController:
|
|
|
81
80
|
pass # 避免报错
|
|
82
81
|
# finally:
|
|
83
82
|
|
|
84
|
-
def get_history_chains(self) ->
|
|
83
|
+
def get_history_chains(self) -> list[list[Comp.BaseMessageComponent]]:
|
|
85
84
|
"""获取历史消息链"""
|
|
86
85
|
return self.history_chains
|
|
87
86
|
|
|
@@ -92,7 +91,6 @@ class SessionFilter:
|
|
|
92
91
|
@abc.abstractmethod
|
|
93
92
|
def filter(self, event: AstrMessageEvent) -> str:
|
|
94
93
|
"""根据事件返回一个会话标识符"""
|
|
95
|
-
pass
|
|
96
94
|
|
|
97
95
|
|
|
98
96
|
class DefaultSessionFilter(SessionFilter):
|
|
@@ -120,7 +118,9 @@ class SessionWaiter:
|
|
|
120
118
|
"""需要保证一个 session 同时只有一个 trigger"""
|
|
121
119
|
|
|
122
120
|
async def register_wait(
|
|
123
|
-
self,
|
|
121
|
+
self,
|
|
122
|
+
handler: Callable[[str], Awaitable[Any]],
|
|
123
|
+
timeout: int = 30,
|
|
124
124
|
) -> Any:
|
|
125
125
|
"""等待外部输入并处理"""
|
|
126
126
|
self.handler = handler
|
|
@@ -149,7 +149,7 @@ class SessionWaiter:
|
|
|
149
149
|
@classmethod
|
|
150
150
|
async def trigger(cls, session_id: str, event: AstrMessageEvent):
|
|
151
151
|
"""外部输入触发会话处理"""
|
|
152
|
-
session = USER_SESSIONS.get(session_id
|
|
152
|
+
session = USER_SESSIONS.get(session_id)
|
|
153
153
|
if not session or session.session_controller.future.done():
|
|
154
154
|
return
|
|
155
155
|
|
|
@@ -157,7 +157,7 @@ class SessionWaiter:
|
|
|
157
157
|
if not session.session_controller.future.done():
|
|
158
158
|
if session.record_history_chains:
|
|
159
159
|
session.session_controller.history_chains.append(
|
|
160
|
-
[copy.deepcopy(comp) for comp in event.get_messages()]
|
|
160
|
+
[copy.deepcopy(comp) for comp in event.get_messages()],
|
|
161
161
|
)
|
|
162
162
|
try:
|
|
163
163
|
# TODO: 这里使用 create_task,跟踪 task,防止超时后这里 handler 仍然在执行
|
|
@@ -167,8 +167,7 @@ class SessionWaiter:
|
|
|
167
167
|
|
|
168
168
|
|
|
169
169
|
def session_waiter(timeout: int = 30, record_history_chains: bool = False):
|
|
170
|
-
"""
|
|
171
|
-
装饰器:自动将函数注册为 SessionWaiter 处理函数,并等待外部输入触发执行。
|
|
170
|
+
"""装饰器:自动将函数注册为 SessionWaiter 处理函数,并等待外部输入触发执行。
|
|
172
171
|
|
|
173
172
|
:param timeout: 超时时间(秒)
|
|
174
173
|
:param record_history_chain: 是否自动记录历史消息链。可以通过 controller.get_history_chains() 获取。深拷贝。
|
|
@@ -1,38 +1,178 @@
|
|
|
1
|
-
import
|
|
1
|
+
import asyncio
|
|
2
2
|
import os
|
|
3
|
+
import threading
|
|
4
|
+
from typing import Any, TypeVar, overload
|
|
5
|
+
|
|
6
|
+
from astrbot.core.db import BaseDatabase
|
|
7
|
+
from astrbot.core.db.po import Preference
|
|
8
|
+
|
|
9
|
+
from .astrbot_path import get_astrbot_data_path
|
|
10
|
+
|
|
11
|
+
_VT = TypeVar("_VT")
|
|
3
12
|
|
|
4
13
|
|
|
5
14
|
class SharedPreferences:
|
|
6
|
-
def __init__(self,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
15
|
+
def __init__(self, db_helper: BaseDatabase, json_storage_path=None):
|
|
16
|
+
if json_storage_path is None:
|
|
17
|
+
json_storage_path = os.path.join(
|
|
18
|
+
get_astrbot_data_path(),
|
|
19
|
+
"shared_preferences.json",
|
|
20
|
+
)
|
|
21
|
+
self.path = json_storage_path
|
|
22
|
+
self.db_helper = db_helper
|
|
23
|
+
|
|
24
|
+
self._sync_loop = asyncio.new_event_loop()
|
|
25
|
+
t = threading.Thread(target=self._sync_loop.run_forever, daemon=True)
|
|
26
|
+
t.start()
|
|
27
|
+
|
|
28
|
+
async def get_async(
|
|
29
|
+
self,
|
|
30
|
+
scope: str,
|
|
31
|
+
scope_id: str,
|
|
32
|
+
key: str,
|
|
33
|
+
default: _VT = None,
|
|
34
|
+
) -> _VT:
|
|
35
|
+
"""获取指定范围和键的偏好设置"""
|
|
36
|
+
if scope_id is not None and key is not None:
|
|
37
|
+
result = await self.db_helper.get_preference(scope, scope_id, key)
|
|
38
|
+
if result:
|
|
39
|
+
ret = result.value["val"]
|
|
40
|
+
else:
|
|
41
|
+
ret = default
|
|
42
|
+
return ret
|
|
43
|
+
|
|
44
|
+
async def range_get_async(
|
|
45
|
+
self,
|
|
46
|
+
scope: str,
|
|
47
|
+
scope_id: str | None = None,
|
|
48
|
+
key: str | None = None,
|
|
49
|
+
) -> list[Preference]:
|
|
50
|
+
"""获取指定范围的偏好设置
|
|
51
|
+
Note: 返回 Preference 列表,其中的 value 属性是一个 dict,value["val"] 为值。scope_id 和 key 可以为 None,这时返回该范围下所有的偏好设置。
|
|
52
|
+
"""
|
|
53
|
+
ret = await self.db_helper.get_preferences(scope, scope_id, key)
|
|
54
|
+
return ret
|
|
55
|
+
|
|
56
|
+
async def session_get(
|
|
57
|
+
self,
|
|
58
|
+
umo: str | None,
|
|
59
|
+
key: str | None = None,
|
|
60
|
+
default: _VT = None,
|
|
61
|
+
) -> _VT | list[Preference]:
|
|
62
|
+
"""获取会话范围的偏好设置
|
|
63
|
+
|
|
64
|
+
Note: 当 umo 或者 key 为 None,时,返回 Preference 列表,其中的 value 属性是一个 dict,value["val"] 为值。
|
|
65
|
+
"""
|
|
66
|
+
if umo is None or key is None:
|
|
67
|
+
return await self.range_get_async("umo", umo, key)
|
|
68
|
+
return await self.get_async("umo", umo, key, default)
|
|
69
|
+
|
|
70
|
+
@overload
|
|
71
|
+
async def global_get(self, key: None, default: Any = None) -> list[Preference]: ...
|
|
72
|
+
|
|
73
|
+
@overload
|
|
74
|
+
async def global_get(self, key: str, default: _VT = None) -> _VT: ...
|
|
75
|
+
|
|
76
|
+
async def global_get(
|
|
77
|
+
self,
|
|
78
|
+
key: str | None,
|
|
79
|
+
default: _VT = None,
|
|
80
|
+
) -> _VT | list[Preference]:
|
|
81
|
+
"""获取全局范围的偏好设置
|
|
82
|
+
|
|
83
|
+
Note: 当 scope_id 或者 key 为 None,时,返回 Preference 列表,其中的 value 属性是一个 dict,value["val"] 为值。
|
|
84
|
+
"""
|
|
85
|
+
if key is None:
|
|
86
|
+
return await self.range_get_async("global", "global", key)
|
|
87
|
+
return await self.get_async("global", "global", key, default)
|
|
88
|
+
|
|
89
|
+
async def put_async(self, scope: str, scope_id: str, key: str, value: Any):
|
|
90
|
+
"""设置指定范围和键的偏好设置"""
|
|
91
|
+
await self.db_helper.insert_preference_or_update(
|
|
92
|
+
scope,
|
|
93
|
+
scope_id,
|
|
94
|
+
key,
|
|
95
|
+
{"val": value},
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
async def session_put(self, umo: str, key: str, value: Any):
|
|
99
|
+
await self.put_async("umo", umo, key, value)
|
|
100
|
+
|
|
101
|
+
async def global_put(self, key: str, value: Any):
|
|
102
|
+
await self.put_async("global", "global", key, value)
|
|
103
|
+
|
|
104
|
+
async def remove_async(self, scope: str, scope_id: str, key: str):
|
|
105
|
+
"""删除指定范围和键的偏好设置"""
|
|
106
|
+
await self.db_helper.remove_preference(scope, scope_id, key)
|
|
107
|
+
|
|
108
|
+
async def session_remove(self, umo: str, key: str):
|
|
109
|
+
await self.remove_async("umo", umo, key)
|
|
110
|
+
|
|
111
|
+
async def global_remove(self, key: str):
|
|
112
|
+
"""删除全局偏好设置"""
|
|
113
|
+
await self.remove_async("global", "global", key)
|
|
114
|
+
|
|
115
|
+
async def clear_async(self, scope: str, scope_id: str):
|
|
116
|
+
"""清空指定范围的所有偏好设置"""
|
|
117
|
+
await self.db_helper.clear_preferences(scope, scope_id)
|
|
118
|
+
|
|
119
|
+
# ====
|
|
120
|
+
# DEPRECATED METHODS
|
|
121
|
+
# ====
|
|
122
|
+
|
|
123
|
+
def get(
|
|
124
|
+
self,
|
|
125
|
+
key: str,
|
|
126
|
+
default: _VT = None,
|
|
127
|
+
scope: str | None = None,
|
|
128
|
+
scope_id: str | None = "",
|
|
129
|
+
) -> _VT:
|
|
130
|
+
"""获取偏好设置(已弃用)"""
|
|
131
|
+
if scope_id == "":
|
|
132
|
+
scope_id = "unknown"
|
|
133
|
+
if scope_id is None or key is None:
|
|
134
|
+
# result = asyncio.run(self.range_get_async(scope, scope_id, key))
|
|
135
|
+
raise ValueError(
|
|
136
|
+
"scope_id and key cannot be None when getting a specific preference.",
|
|
137
|
+
)
|
|
138
|
+
result = asyncio.run_coroutine_threadsafe(
|
|
139
|
+
self.get_async(scope or "unknown", scope_id or "unknown", key, default),
|
|
140
|
+
self._sync_loop,
|
|
141
|
+
).result()
|
|
142
|
+
|
|
143
|
+
return result if result is not None else default
|
|
144
|
+
|
|
145
|
+
def range_get(
|
|
146
|
+
self,
|
|
147
|
+
scope: str,
|
|
148
|
+
scope_id: str | None = None,
|
|
149
|
+
key: str | None = None,
|
|
150
|
+
) -> list[Preference]:
|
|
151
|
+
"""获取指定范围的偏好设置(已弃用)"""
|
|
152
|
+
result = asyncio.run_coroutine_threadsafe(
|
|
153
|
+
self.range_get_async(scope, scope_id, key),
|
|
154
|
+
self._sync_loop,
|
|
155
|
+
).result()
|
|
156
|
+
|
|
157
|
+
return result
|
|
158
|
+
|
|
159
|
+
def put(self, key, value, scope: str | None = None, scope_id: str | None = None):
|
|
160
|
+
"""设置偏好设置(已弃用)"""
|
|
161
|
+
asyncio.run_coroutine_threadsafe(
|
|
162
|
+
self.put_async(scope or "unknown", scope_id or "unknown", key, value),
|
|
163
|
+
self._sync_loop,
|
|
164
|
+
).result()
|
|
165
|
+
|
|
166
|
+
def remove(self, key, scope: str | None = None, scope_id: str | None = None):
|
|
167
|
+
"""删除偏好设置(已弃用)"""
|
|
168
|
+
asyncio.run_coroutine_threadsafe(
|
|
169
|
+
self.remove_async(scope or "unknown", scope_id or "unknown", key),
|
|
170
|
+
self._sync_loop,
|
|
171
|
+
).result()
|
|
172
|
+
|
|
173
|
+
def clear(self, scope: str | None = None, scope_id: str | None = None):
|
|
174
|
+
"""清空偏好设置(已弃用)"""
|
|
175
|
+
asyncio.run_coroutine_threadsafe(
|
|
176
|
+
self.clear_async(scope or "unknown", scope_id or "unknown"),
|
|
177
|
+
self._sync_loop,
|
|
178
|
+
).result()
|