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,15 +1,16 @@
|
|
|
1
1
|
import enum
|
|
2
|
-
|
|
3
|
-
from typing import List, Optional, Union, AsyncGenerator
|
|
2
|
+
from collections.abc import AsyncGenerator
|
|
4
3
|
from dataclasses import dataclass, field
|
|
4
|
+
|
|
5
|
+
from typing_extensions import deprecated
|
|
6
|
+
|
|
5
7
|
from astrbot.core.message.components import (
|
|
6
|
-
BaseMessageComponent,
|
|
7
|
-
Plain,
|
|
8
|
-
Image,
|
|
9
8
|
At,
|
|
10
9
|
AtAll,
|
|
10
|
+
BaseMessageComponent,
|
|
11
|
+
Image,
|
|
12
|
+
Plain,
|
|
11
13
|
)
|
|
12
|
-
from typing_extensions import deprecated
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
@dataclass
|
|
@@ -20,16 +21,18 @@ class MessageChain:
|
|
|
20
21
|
Attributes:
|
|
21
22
|
`chain` (list): 用于顺序存储各个组件。
|
|
22
23
|
`use_t2i_` (bool): 用于标记是否使用文本转图片服务。默认为 None,即跟随用户的设置。当设置为 True 时,将会使用文本转图片服务。
|
|
24
|
+
|
|
23
25
|
"""
|
|
24
26
|
|
|
25
|
-
chain:
|
|
26
|
-
use_t2i_:
|
|
27
|
+
chain: list[BaseMessageComponent] = field(default_factory=list)
|
|
28
|
+
use_t2i_: bool | None = None # None 为跟随用户设置
|
|
29
|
+
type: str | None = None
|
|
30
|
+
"""消息链承载的消息的类型。可选,用于让消息平台区分不同业务场景的消息链。"""
|
|
27
31
|
|
|
28
32
|
def message(self, message: str):
|
|
29
33
|
"""添加一条文本消息到消息链 `chain` 中。
|
|
30
34
|
|
|
31
35
|
Example:
|
|
32
|
-
|
|
33
36
|
CommandResult().message("Hello ").message("world!")
|
|
34
37
|
# 输出 Hello world!
|
|
35
38
|
|
|
@@ -37,11 +40,10 @@ class MessageChain:
|
|
|
37
40
|
self.chain.append(Plain(message))
|
|
38
41
|
return self
|
|
39
42
|
|
|
40
|
-
def at(self, name: str, qq:
|
|
43
|
+
def at(self, name: str, qq: str | int):
|
|
41
44
|
"""添加一条 At 消息到消息链 `chain` 中。
|
|
42
45
|
|
|
43
46
|
Example:
|
|
44
|
-
|
|
45
47
|
CommandResult().at("张三", "12345678910")
|
|
46
48
|
# 输出 @张三
|
|
47
49
|
|
|
@@ -53,7 +55,6 @@ class MessageChain:
|
|
|
53
55
|
"""添加一条 AtAll 消息到消息链 `chain` 中。
|
|
54
56
|
|
|
55
57
|
Example:
|
|
56
|
-
|
|
57
58
|
CommandResult().at_all()
|
|
58
59
|
# 输出 @所有人
|
|
59
60
|
|
|
@@ -66,7 +67,6 @@ class MessageChain:
|
|
|
66
67
|
"""添加一条错误消息到消息链 `chain` 中
|
|
67
68
|
|
|
68
69
|
Example:
|
|
69
|
-
|
|
70
70
|
CommandResult().error("解析失败")
|
|
71
71
|
|
|
72
72
|
"""
|
|
@@ -80,7 +80,6 @@ class MessageChain:
|
|
|
80
80
|
如果需要发送本地图片,请使用 `file_image` 方法。
|
|
81
81
|
|
|
82
82
|
Example:
|
|
83
|
-
|
|
84
83
|
CommandResult().image("https://example.com/image.jpg")
|
|
85
84
|
|
|
86
85
|
"""
|
|
@@ -94,15 +93,26 @@ class MessageChain:
|
|
|
94
93
|
如果需要发送网络图片,请使用 `url_image` 方法。
|
|
95
94
|
|
|
96
95
|
CommandResult().image("image.jpg")
|
|
96
|
+
|
|
97
97
|
"""
|
|
98
98
|
self.chain.append(Image.fromFileSystem(path))
|
|
99
99
|
return self
|
|
100
100
|
|
|
101
|
+
def base64_image(self, base64_str: str):
|
|
102
|
+
"""添加一条图片消息(base64 编码字符串)到消息链 `chain` 中。
|
|
103
|
+
Example:
|
|
104
|
+
|
|
105
|
+
CommandResult().base64_image("iVBORw0KGgoAAAANSUhEUgAAAAUA...")
|
|
106
|
+
"""
|
|
107
|
+
self.chain.append(Image.fromBase64(base64_str))
|
|
108
|
+
return self
|
|
109
|
+
|
|
101
110
|
def use_t2i(self, use_t2i: bool):
|
|
102
111
|
"""设置是否使用文本转图片服务。
|
|
103
112
|
|
|
104
113
|
Args:
|
|
105
114
|
use_t2i (bool): 是否使用文本转图片服务。默认为 None,即跟随用户的设置。当设置为 True 时,将会使用文本转图片服务。
|
|
115
|
+
|
|
106
116
|
"""
|
|
107
117
|
self.use_t2i_ = use_t2i
|
|
108
118
|
return self
|
|
@@ -114,7 +124,7 @@ class MessageChain:
|
|
|
114
124
|
def squash_plain(self):
|
|
115
125
|
"""将消息链中的所有 Plain 消息段聚合到第一个 Plain 消息段中。"""
|
|
116
126
|
if not self.chain:
|
|
117
|
-
return
|
|
127
|
+
return None
|
|
118
128
|
|
|
119
129
|
new_chain = []
|
|
120
130
|
first_plain = None
|
|
@@ -142,6 +152,7 @@ class EventResultType(enum.Enum):
|
|
|
142
152
|
Attributes:
|
|
143
153
|
CONTINUE: 事件将会继续传播
|
|
144
154
|
STOP: 事件将会终止传播
|
|
155
|
+
|
|
145
156
|
"""
|
|
146
157
|
|
|
147
158
|
CONTINUE = enum.auto()
|
|
@@ -157,7 +168,7 @@ class ResultContentType(enum.Enum):
|
|
|
157
168
|
"""普通的消息结果"""
|
|
158
169
|
STREAMING_RESULT = enum.auto()
|
|
159
170
|
"""调用 LLM 产生的流式结果"""
|
|
160
|
-
STREAMING_FINISH= enum.auto()
|
|
171
|
+
STREAMING_FINISH = enum.auto()
|
|
161
172
|
"""流式输出完成"""
|
|
162
173
|
|
|
163
174
|
|
|
@@ -170,17 +181,18 @@ class MessageEventResult(MessageChain):
|
|
|
170
181
|
`chain` (list): 用于顺序存储各个组件。
|
|
171
182
|
`use_t2i_` (bool): 用于标记是否使用文本转图片服务。默认为 None,即跟随用户的设置。当设置为 True 时,将会使用文本转图片服务。
|
|
172
183
|
`result_type` (EventResultType): 事件处理的结果类型。
|
|
184
|
+
|
|
173
185
|
"""
|
|
174
186
|
|
|
175
|
-
result_type:
|
|
176
|
-
default_factory=lambda: EventResultType.CONTINUE
|
|
187
|
+
result_type: EventResultType | None = field(
|
|
188
|
+
default_factory=lambda: EventResultType.CONTINUE,
|
|
177
189
|
)
|
|
178
190
|
|
|
179
|
-
result_content_type:
|
|
180
|
-
default_factory=lambda: ResultContentType.GENERAL_RESULT
|
|
191
|
+
result_content_type: ResultContentType | None = field(
|
|
192
|
+
default_factory=lambda: ResultContentType.GENERAL_RESULT,
|
|
181
193
|
)
|
|
182
194
|
|
|
183
|
-
async_stream:
|
|
195
|
+
async_stream: AsyncGenerator | None = None
|
|
184
196
|
"""异步流"""
|
|
185
197
|
|
|
186
198
|
def stop_event(self) -> "MessageEventResult":
|
|
@@ -194,9 +206,7 @@ class MessageEventResult(MessageChain):
|
|
|
194
206
|
return self
|
|
195
207
|
|
|
196
208
|
def is_stopped(self) -> bool:
|
|
197
|
-
"""
|
|
198
|
-
是否终止事件传播。
|
|
199
|
-
"""
|
|
209
|
+
"""是否终止事件传播。"""
|
|
200
210
|
return self.result_type == EventResultType.STOP
|
|
201
211
|
|
|
202
212
|
def set_async_stream(self, stream: AsyncGenerator) -> "MessageEventResult":
|
|
@@ -209,6 +219,7 @@ class MessageEventResult(MessageChain):
|
|
|
209
219
|
|
|
210
220
|
Args:
|
|
211
221
|
result_type (EventResultType): 事件处理的结果类型。
|
|
222
|
+
|
|
212
223
|
"""
|
|
213
224
|
self.result_content_type = typ
|
|
214
225
|
return self
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
from astrbot import logger
|
|
2
|
+
from astrbot.core.astrbot_config_mgr import AstrBotConfigManager
|
|
3
|
+
from astrbot.core.db import BaseDatabase
|
|
4
|
+
from astrbot.core.db.po import Persona, Personality
|
|
5
|
+
from astrbot.core.platform.message_session import MessageSession
|
|
6
|
+
|
|
7
|
+
DEFAULT_PERSONALITY = Personality(
|
|
8
|
+
prompt="You are a helpful and friendly assistant.",
|
|
9
|
+
name="default",
|
|
10
|
+
begin_dialogs=[],
|
|
11
|
+
mood_imitation_dialogs=[],
|
|
12
|
+
tools=None,
|
|
13
|
+
_begin_dialogs_processed=[],
|
|
14
|
+
_mood_imitation_dialogs_processed="",
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class PersonaManager:
|
|
19
|
+
def __init__(self, db_helper: BaseDatabase, acm: AstrBotConfigManager):
|
|
20
|
+
self.db = db_helper
|
|
21
|
+
self.acm = acm
|
|
22
|
+
default_ps = acm.default_conf.get("provider_settings", {})
|
|
23
|
+
self.default_persona: str = default_ps.get("default_personality", "default")
|
|
24
|
+
self.personas: list[Persona] = []
|
|
25
|
+
self.selected_default_persona: Persona | None = None
|
|
26
|
+
|
|
27
|
+
self.personas_v3: list[Personality] = []
|
|
28
|
+
self.selected_default_persona_v3: Personality | None = None
|
|
29
|
+
self.persona_v3_config: list[dict] = []
|
|
30
|
+
|
|
31
|
+
async def initialize(self):
|
|
32
|
+
self.personas = await self.get_all_personas()
|
|
33
|
+
self.get_v3_persona_data()
|
|
34
|
+
logger.info(f"已加载 {len(self.personas)} 个人格。")
|
|
35
|
+
|
|
36
|
+
async def get_persona(self, persona_id: str):
|
|
37
|
+
"""获取指定 persona 的信息"""
|
|
38
|
+
persona = await self.db.get_persona_by_id(persona_id)
|
|
39
|
+
if not persona:
|
|
40
|
+
raise ValueError(f"Persona with ID {persona_id} does not exist.")
|
|
41
|
+
return persona
|
|
42
|
+
|
|
43
|
+
async def get_default_persona_v3(
|
|
44
|
+
self,
|
|
45
|
+
umo: str | MessageSession | None = None,
|
|
46
|
+
) -> Personality:
|
|
47
|
+
"""获取默认 persona"""
|
|
48
|
+
cfg = self.acm.get_conf(umo)
|
|
49
|
+
default_persona_id = cfg.get("provider_settings", {}).get(
|
|
50
|
+
"default_personality",
|
|
51
|
+
"default",
|
|
52
|
+
)
|
|
53
|
+
if not default_persona_id or default_persona_id == "default":
|
|
54
|
+
return DEFAULT_PERSONALITY
|
|
55
|
+
try:
|
|
56
|
+
return next(p for p in self.personas_v3 if p["name"] == default_persona_id)
|
|
57
|
+
except Exception:
|
|
58
|
+
return DEFAULT_PERSONALITY
|
|
59
|
+
|
|
60
|
+
async def delete_persona(self, persona_id: str):
|
|
61
|
+
"""删除指定 persona"""
|
|
62
|
+
if not await self.db.get_persona_by_id(persona_id):
|
|
63
|
+
raise ValueError(f"Persona with ID {persona_id} does not exist.")
|
|
64
|
+
await self.db.delete_persona(persona_id)
|
|
65
|
+
self.personas = [p for p in self.personas if p.persona_id != persona_id]
|
|
66
|
+
self.get_v3_persona_data()
|
|
67
|
+
|
|
68
|
+
async def update_persona(
|
|
69
|
+
self,
|
|
70
|
+
persona_id: str,
|
|
71
|
+
system_prompt: str | None = None,
|
|
72
|
+
begin_dialogs: list[str] | None = None,
|
|
73
|
+
tools: list[str] | None = None,
|
|
74
|
+
):
|
|
75
|
+
"""更新指定 persona 的信息。tools 参数为 None 时表示使用所有工具,空列表表示不使用任何工具"""
|
|
76
|
+
existing_persona = await self.db.get_persona_by_id(persona_id)
|
|
77
|
+
if not existing_persona:
|
|
78
|
+
raise ValueError(f"Persona with ID {persona_id} does not exist.")
|
|
79
|
+
persona = await self.db.update_persona(
|
|
80
|
+
persona_id,
|
|
81
|
+
system_prompt,
|
|
82
|
+
begin_dialogs,
|
|
83
|
+
tools=tools,
|
|
84
|
+
)
|
|
85
|
+
if persona:
|
|
86
|
+
for i, p in enumerate(self.personas):
|
|
87
|
+
if p.persona_id == persona_id:
|
|
88
|
+
self.personas[i] = persona
|
|
89
|
+
break
|
|
90
|
+
self.get_v3_persona_data()
|
|
91
|
+
return persona
|
|
92
|
+
|
|
93
|
+
async def get_all_personas(self) -> list[Persona]:
|
|
94
|
+
"""获取所有 personas"""
|
|
95
|
+
return await self.db.get_personas()
|
|
96
|
+
|
|
97
|
+
async def create_persona(
|
|
98
|
+
self,
|
|
99
|
+
persona_id: str,
|
|
100
|
+
system_prompt: str,
|
|
101
|
+
begin_dialogs: list[str] = None,
|
|
102
|
+
tools: list[str] = None,
|
|
103
|
+
) -> Persona:
|
|
104
|
+
"""创建新的 persona。tools 参数为 None 时表示使用所有工具,空列表表示不使用任何工具"""
|
|
105
|
+
if await self.db.get_persona_by_id(persona_id):
|
|
106
|
+
raise ValueError(f"Persona with ID {persona_id} already exists.")
|
|
107
|
+
new_persona = await self.db.insert_persona(
|
|
108
|
+
persona_id,
|
|
109
|
+
system_prompt,
|
|
110
|
+
begin_dialogs,
|
|
111
|
+
tools=tools,
|
|
112
|
+
)
|
|
113
|
+
self.personas.append(new_persona)
|
|
114
|
+
self.get_v3_persona_data()
|
|
115
|
+
return new_persona
|
|
116
|
+
|
|
117
|
+
def get_v3_persona_data(
|
|
118
|
+
self,
|
|
119
|
+
) -> tuple[list[dict], list[Personality], Personality]:
|
|
120
|
+
"""获取 AstrBot <4.0.0 版本的 persona 数据。
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
- list[dict]: 包含 persona 配置的字典列表。
|
|
124
|
+
- list[Personality]: 包含 Personality 对象的列表。
|
|
125
|
+
- Personality: 默认选择的 Personality 对象。
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
v3_persona_config = [
|
|
129
|
+
{
|
|
130
|
+
"prompt": persona.system_prompt,
|
|
131
|
+
"name": persona.persona_id,
|
|
132
|
+
"begin_dialogs": persona.begin_dialogs or [],
|
|
133
|
+
"mood_imitation_dialogs": [], # deprecated
|
|
134
|
+
"tools": persona.tools,
|
|
135
|
+
}
|
|
136
|
+
for persona in self.personas
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
personas_v3: list[Personality] = []
|
|
140
|
+
selected_default_persona: Personality | None = None
|
|
141
|
+
|
|
142
|
+
for persona_cfg in v3_persona_config:
|
|
143
|
+
begin_dialogs = persona_cfg.get("begin_dialogs", [])
|
|
144
|
+
bd_processed = []
|
|
145
|
+
if begin_dialogs:
|
|
146
|
+
if len(begin_dialogs) % 2 != 0:
|
|
147
|
+
logger.error(
|
|
148
|
+
f"{persona_cfg['name']} 人格情景预设对话格式不对,条数应该为偶数。",
|
|
149
|
+
)
|
|
150
|
+
begin_dialogs = []
|
|
151
|
+
user_turn = True
|
|
152
|
+
for dialog in begin_dialogs:
|
|
153
|
+
bd_processed.append(
|
|
154
|
+
{
|
|
155
|
+
"role": "user" if user_turn else "assistant",
|
|
156
|
+
"content": dialog,
|
|
157
|
+
"_no_save": None, # 不持久化到 db
|
|
158
|
+
},
|
|
159
|
+
)
|
|
160
|
+
user_turn = not user_turn
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
persona = Personality(
|
|
164
|
+
**persona_cfg,
|
|
165
|
+
_begin_dialogs_processed=bd_processed,
|
|
166
|
+
_mood_imitation_dialogs_processed="", # deprecated
|
|
167
|
+
)
|
|
168
|
+
if persona["name"] == self.default_persona:
|
|
169
|
+
selected_default_persona = persona
|
|
170
|
+
personas_v3.append(persona)
|
|
171
|
+
except Exception as e:
|
|
172
|
+
logger.error(f"解析 Persona 配置失败:{e}")
|
|
173
|
+
|
|
174
|
+
if not selected_default_persona and len(personas_v3) > 0:
|
|
175
|
+
# 默认选择第一个
|
|
176
|
+
selected_default_persona = personas_v3[0]
|
|
177
|
+
|
|
178
|
+
if not selected_default_persona:
|
|
179
|
+
selected_default_persona = DEFAULT_PERSONALITY
|
|
180
|
+
personas_v3.append(selected_default_persona)
|
|
181
|
+
|
|
182
|
+
self.personas_v3 = personas_v3
|
|
183
|
+
self.selected_default_persona_v3 = selected_default_persona
|
|
184
|
+
self.persona_v3_config = v3_persona_config
|
|
185
|
+
self.selected_default_persona = Persona(
|
|
186
|
+
persona_id=selected_default_persona["name"],
|
|
187
|
+
system_prompt=selected_default_persona["prompt"],
|
|
188
|
+
begin_dialogs=selected_default_persona["begin_dialogs"],
|
|
189
|
+
tools=selected_default_persona["tools"] or None,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
return v3_persona_config, personas_v3, selected_default_persona
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
from astrbot.core.message.message_event_result import (
|
|
2
|
-
MessageEventResult,
|
|
3
2
|
EventResultType,
|
|
3
|
+
MessageEventResult,
|
|
4
4
|
)
|
|
5
5
|
|
|
6
|
-
from .waking_check.stage import WakingCheckStage
|
|
7
|
-
from .whitelist_check.stage import WhitelistCheckStage
|
|
8
|
-
from .rate_limit_check.stage import RateLimitStage
|
|
9
6
|
from .content_safety_check.stage import ContentSafetyCheckStage
|
|
10
|
-
from .platform_compatibility.stage import PlatformCompatibilityStage
|
|
11
7
|
from .preprocess_stage.stage import PreProcessStage
|
|
12
8
|
from .process_stage.stage import ProcessStage
|
|
13
|
-
from .
|
|
9
|
+
from .rate_limit_check.stage import RateLimitStage
|
|
14
10
|
from .respond.stage import RespondStage
|
|
11
|
+
from .result_decorate.stage import ResultDecorateStage
|
|
12
|
+
from .session_status_check.stage import SessionStatusCheckStage
|
|
13
|
+
from .waking_check.stage import WakingCheckStage
|
|
14
|
+
from .whitelist_check.stage import WhitelistCheckStage
|
|
15
15
|
|
|
16
16
|
# 管道阶段顺序
|
|
17
17
|
STAGES_ORDER = [
|
|
18
18
|
"WakingCheckStage", # 检查是否需要唤醒
|
|
19
19
|
"WhitelistCheckStage", # 检查是否在群聊/私聊白名单
|
|
20
|
+
"SessionStatusCheckStage", # 检查会话是否整体启用
|
|
20
21
|
"RateLimitStage", # 检查会话是否超过频率限制
|
|
21
22
|
"ContentSafetyCheckStage", # 检查内容安全
|
|
22
|
-
"PlatformCompatibilityStage", # 检查所有处理器的平台兼容性
|
|
23
23
|
"PreProcessStage", # 预处理
|
|
24
24
|
"ProcessStage", # 交由 Stars 处理(a.k.a 插件),或者 LLM 调用
|
|
25
25
|
"ResultDecorateStage", # 处理结果,比如添加回复前缀、t2i、转换为语音 等
|
|
@@ -27,15 +27,15 @@ STAGES_ORDER = [
|
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
__all__ = [
|
|
30
|
-
"WakingCheckStage",
|
|
31
|
-
"WhitelistCheckStage",
|
|
32
|
-
"RateLimitStage",
|
|
33
30
|
"ContentSafetyCheckStage",
|
|
34
|
-
"
|
|
31
|
+
"EventResultType",
|
|
32
|
+
"MessageEventResult",
|
|
35
33
|
"PreProcessStage",
|
|
36
34
|
"ProcessStage",
|
|
37
|
-
"
|
|
35
|
+
"RateLimitStage",
|
|
38
36
|
"RespondStage",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
37
|
+
"ResultDecorateStage",
|
|
38
|
+
"SessionStatusCheckStage",
|
|
39
|
+
"WakingCheckStage",
|
|
40
|
+
"WhitelistCheckStage",
|
|
41
41
|
]
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from ..context import PipelineContext
|
|
4
|
-
from astrbot.core.platform.astr_message_event import AstrMessageEvent
|
|
5
|
-
from astrbot.core.message.message_event_result import MessageEventResult
|
|
1
|
+
from collections.abc import AsyncGenerator
|
|
2
|
+
|
|
6
3
|
from astrbot.core import logger
|
|
4
|
+
from astrbot.core.message.message_event_result import MessageEventResult
|
|
5
|
+
from astrbot.core.platform.astr_message_event import AstrMessageEvent
|
|
6
|
+
|
|
7
|
+
from ..context import PipelineContext
|
|
8
|
+
from ..stage import Stage, register_stage
|
|
7
9
|
from .strategies.strategy import StrategySelector
|
|
8
10
|
|
|
9
11
|
|
|
@@ -19,8 +21,10 @@ class ContentSafetyCheckStage(Stage):
|
|
|
19
21
|
self.strategy_selector = StrategySelector(config)
|
|
20
22
|
|
|
21
23
|
async def process(
|
|
22
|
-
self,
|
|
23
|
-
|
|
24
|
+
self,
|
|
25
|
+
event: AstrMessageEvent,
|
|
26
|
+
check_text: str | None = None,
|
|
27
|
+
) -> None | AsyncGenerator[None, None]:
|
|
24
28
|
"""检查内容安全"""
|
|
25
29
|
text = check_text if check_text else event.get_message_str()
|
|
26
30
|
ok, info = self.strategy_selector.check(text)
|
|
@@ -28,8 +32,8 @@ class ContentSafetyCheckStage(Stage):
|
|
|
28
32
|
if event.is_at_or_wake_command:
|
|
29
33
|
event.set_result(
|
|
30
34
|
MessageEventResult().message(
|
|
31
|
-
"你的消息或者大模型的响应中包含不适当的内容,已被屏蔽。"
|
|
32
|
-
)
|
|
35
|
+
"你的消息或者大模型的响应中包含不适当的内容,已被屏蔽。",
|
|
36
|
+
),
|
|
33
37
|
)
|
|
34
38
|
yield
|
|
35
39
|
event.stop_event()
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
"""
|
|
2
|
-
使用此功能应该先 pip install baidu-aip
|
|
3
|
-
"""
|
|
1
|
+
"""使用此功能应该先 pip install baidu-aip"""
|
|
4
2
|
|
|
5
|
-
from . import ContentSafetyStrategy
|
|
6
3
|
from aip import AipContentCensor
|
|
7
4
|
|
|
5
|
+
from . import ContentSafetyStrategy
|
|
6
|
+
|
|
8
7
|
|
|
9
8
|
class BaiduAipStrategy(ContentSafetyStrategy):
|
|
10
9
|
def __init__(self, appid: str, ak: str, sk: str) -> None:
|
|
@@ -13,18 +12,18 @@ class BaiduAipStrategy(ContentSafetyStrategy):
|
|
|
13
12
|
self.secret_key = sk
|
|
14
13
|
self.client = AipContentCensor(self.app_id, self.api_key, self.secret_key)
|
|
15
14
|
|
|
16
|
-
def check(self, content: str):
|
|
15
|
+
def check(self, content: str) -> tuple[bool, str]:
|
|
17
16
|
res = self.client.textCensorUserDefined(content)
|
|
18
17
|
if "conclusionType" not in res:
|
|
19
18
|
return False, ""
|
|
20
19
|
if res["conclusionType"] == 1:
|
|
21
20
|
return True, ""
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
if "data" not in res:
|
|
22
|
+
return False, ""
|
|
23
|
+
count = len(res["data"])
|
|
24
|
+
parts = [f"百度审核服务发现 {count} 处违规:\n"]
|
|
25
|
+
for i in res["data"]:
|
|
26
|
+
parts.append(f"{i['msg']};\n")
|
|
27
|
+
parts.append("\n判断结果:" + res["conclusion"])
|
|
28
|
+
info = "".join(parts)
|
|
29
|
+
return False, info
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
|
+
|
|
2
3
|
from . import ContentSafetyStrategy
|
|
3
4
|
|
|
4
5
|
|
|
@@ -16,7 +17,7 @@ class KeywordsStrategy(ContentSafetyStrategy):
|
|
|
16
17
|
# json.loads(base64.b64decode(f.read()).decode("utf-8"))["keywords"]
|
|
17
18
|
# )
|
|
18
19
|
|
|
19
|
-
def check(self, content: str) -> bool:
|
|
20
|
+
def check(self, content: str) -> tuple[bool, str]:
|
|
20
21
|
for keyword in self.keywords:
|
|
21
22
|
if re.search(keyword, content):
|
|
22
23
|
return False, "内容安全检查不通过,匹配到敏感词。"
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
from . import ContentSafetyStrategy
|
|
2
|
-
from typing import List, Tuple
|
|
3
1
|
from astrbot import logger
|
|
4
2
|
|
|
3
|
+
from . import ContentSafetyStrategy
|
|
4
|
+
|
|
5
5
|
|
|
6
6
|
class StrategySelector:
|
|
7
7
|
def __init__(self, config: dict) -> None:
|
|
8
|
-
self.enabled_strategies:
|
|
8
|
+
self.enabled_strategies: list[ContentSafetyStrategy] = []
|
|
9
9
|
if config["internal_keywords"]["enable"]:
|
|
10
10
|
from .keywords import KeywordsStrategy
|
|
11
11
|
|
|
12
12
|
self.enabled_strategies.append(
|
|
13
|
-
KeywordsStrategy(config["internal_keywords"]["extra_keywords"])
|
|
13
|
+
KeywordsStrategy(config["internal_keywords"]["extra_keywords"]),
|
|
14
14
|
)
|
|
15
15
|
if config["baidu_aip"]["enable"]:
|
|
16
16
|
try:
|
|
@@ -23,10 +23,10 @@ class StrategySelector:
|
|
|
23
23
|
config["baidu_aip"]["app_id"],
|
|
24
24
|
config["baidu_aip"]["api_key"],
|
|
25
25
|
config["baidu_aip"]["secret_key"],
|
|
26
|
-
)
|
|
26
|
+
),
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
-
def check(self, content: str) ->
|
|
29
|
+
def check(self, content: str) -> tuple[bool, str]:
|
|
30
30
|
for strategy in self.enabled_strategies:
|
|
31
31
|
ok, info = strategy.check(content)
|
|
32
32
|
if not ok:
|
astrbot/core/pipeline/context.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from astrbot.core.config import AstrBotConfig
|
|
3
4
|
from astrbot.core.star import PluginManager
|
|
4
5
|
|
|
6
|
+
from .context_utils import call_event_hook, call_handler
|
|
7
|
+
|
|
5
8
|
|
|
6
9
|
@dataclass
|
|
7
10
|
class PipelineContext:
|
|
@@ -9,3 +12,6 @@ class PipelineContext:
|
|
|
9
12
|
|
|
10
13
|
astrbot_config: AstrBotConfig # AstrBot 配置对象
|
|
11
14
|
plugin_manager: PluginManager # 插件管理器对象
|
|
15
|
+
astrbot_config_id: str
|
|
16
|
+
call_handler = call_handler
|
|
17
|
+
call_event_hook = call_event_hook
|