AstrBot 4.5.1__py3-none-any.whl → 4.5.3__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 +10 -11
- astrbot/api/event/__init__.py +5 -6
- astrbot/api/event/filter/__init__.py +37 -36
- astrbot/api/platform/__init__.py +7 -8
- astrbot/api/provider/__init__.py +7 -7
- astrbot/api/star/__init__.py +3 -4
- astrbot/api/util/__init__.py +2 -2
- astrbot/cli/__main__.py +5 -5
- astrbot/cli/commands/__init__.py +3 -3
- astrbot/cli/commands/cmd_conf.py +19 -16
- astrbot/cli/commands/cmd_init.py +3 -2
- astrbot/cli/commands/cmd_plug.py +8 -10
- astrbot/cli/commands/cmd_run.py +5 -6
- astrbot/cli/utils/__init__.py +6 -6
- astrbot/cli/utils/basic.py +14 -14
- astrbot/cli/utils/plugin.py +24 -15
- astrbot/cli/utils/version_comparator.py +10 -12
- astrbot/core/__init__.py +8 -6
- astrbot/core/agent/agent.py +3 -2
- astrbot/core/agent/handoff.py +6 -2
- astrbot/core/agent/hooks.py +9 -6
- astrbot/core/agent/mcp_client.py +50 -15
- astrbot/core/agent/message.py +168 -0
- astrbot/core/agent/response.py +2 -1
- astrbot/core/agent/run_context.py +2 -3
- astrbot/core/agent/runners/base.py +10 -13
- astrbot/core/agent/runners/tool_loop_agent_runner.py +52 -51
- astrbot/core/agent/tool.py +60 -41
- astrbot/core/agent/tool_executor.py +9 -3
- astrbot/core/astr_agent_context.py +3 -1
- astrbot/core/astrbot_config_mgr.py +29 -9
- astrbot/core/config/__init__.py +2 -2
- astrbot/core/config/astrbot_config.py +28 -26
- astrbot/core/config/default.py +4 -6
- astrbot/core/conversation_mgr.py +105 -36
- astrbot/core/core_lifecycle.py +68 -54
- astrbot/core/db/__init__.py +33 -18
- astrbot/core/db/migration/helper.py +12 -10
- astrbot/core/db/migration/migra_3_to_4.py +53 -34
- astrbot/core/db/migration/migra_45_to_46.py +1 -1
- astrbot/core/db/migration/shared_preferences_v3.py +2 -1
- astrbot/core/db/migration/sqlite_v3.py +26 -23
- astrbot/core/db/po.py +27 -18
- astrbot/core/db/sqlite.py +74 -45
- astrbot/core/db/vec_db/base.py +10 -14
- astrbot/core/db/vec_db/faiss_impl/document_storage.py +90 -77
- astrbot/core/db/vec_db/faiss_impl/embedding_storage.py +9 -3
- astrbot/core/db/vec_db/faiss_impl/vec_db.py +36 -31
- astrbot/core/event_bus.py +8 -6
- astrbot/core/file_token_service.py +6 -5
- astrbot/core/initial_loader.py +7 -5
- astrbot/core/knowledge_base/chunking/__init__.py +1 -3
- astrbot/core/knowledge_base/chunking/base.py +1 -0
- astrbot/core/knowledge_base/chunking/fixed_size.py +2 -0
- astrbot/core/knowledge_base/chunking/recursive.py +16 -10
- astrbot/core/knowledge_base/kb_db_sqlite.py +50 -48
- astrbot/core/knowledge_base/kb_helper.py +30 -17
- astrbot/core/knowledge_base/kb_mgr.py +6 -7
- astrbot/core/knowledge_base/models.py +10 -4
- astrbot/core/knowledge_base/parsers/__init__.py +3 -5
- astrbot/core/knowledge_base/parsers/base.py +1 -0
- astrbot/core/knowledge_base/parsers/markitdown_parser.py +2 -1
- astrbot/core/knowledge_base/parsers/pdf_parser.py +2 -1
- astrbot/core/knowledge_base/parsers/text_parser.py +1 -0
- astrbot/core/knowledge_base/parsers/util.py +1 -1
- astrbot/core/knowledge_base/retrieval/__init__.py +6 -8
- astrbot/core/knowledge_base/retrieval/manager.py +17 -14
- astrbot/core/knowledge_base/retrieval/rank_fusion.py +7 -3
- astrbot/core/knowledge_base/retrieval/sparse_retriever.py +11 -5
- astrbot/core/log.py +21 -13
- astrbot/core/message/components.py +123 -217
- astrbot/core/message/message_event_result.py +24 -24
- astrbot/core/persona_mgr.py +20 -11
- astrbot/core/pipeline/__init__.py +7 -7
- 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 +12 -13
- astrbot/core/pipeline/content_safety_check/strategies/keywords.py +1 -0
- astrbot/core/pipeline/content_safety_check/strategies/strategy.py +6 -6
- astrbot/core/pipeline/context.py +4 -1
- astrbot/core/pipeline/context_utils.py +77 -7
- astrbot/core/pipeline/preprocess_stage/stage.py +12 -9
- astrbot/core/pipeline/process_stage/method/llm_request.py +125 -72
- astrbot/core/pipeline/process_stage/method/star_request.py +19 -17
- astrbot/core/pipeline/process_stage/stage.py +13 -10
- astrbot/core/pipeline/process_stage/utils.py +6 -5
- astrbot/core/pipeline/rate_limit_check/stage.py +37 -36
- astrbot/core/pipeline/respond/stage.py +23 -20
- astrbot/core/pipeline/result_decorate/stage.py +31 -23
- astrbot/core/pipeline/scheduler.py +12 -8
- astrbot/core/pipeline/session_status_check/stage.py +12 -8
- astrbot/core/pipeline/stage.py +10 -4
- astrbot/core/pipeline/waking_check/stage.py +24 -18
- astrbot/core/pipeline/whitelist_check/stage.py +10 -7
- astrbot/core/platform/__init__.py +6 -6
- astrbot/core/platform/astr_message_event.py +76 -110
- astrbot/core/platform/astrbot_message.py +11 -13
- astrbot/core/platform/manager.py +16 -15
- astrbot/core/platform/message_session.py +5 -3
- astrbot/core/platform/platform.py +16 -24
- astrbot/core/platform/platform_metadata.py +4 -4
- astrbot/core/platform/register.py +8 -8
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +23 -15
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +51 -33
- astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py +42 -27
- astrbot/core/platform/sources/dingtalk/dingtalk_event.py +7 -3
- astrbot/core/platform/sources/discord/client.py +9 -6
- astrbot/core/platform/sources/discord/components.py +18 -14
- astrbot/core/platform/sources/discord/discord_platform_adapter.py +45 -30
- astrbot/core/platform/sources/discord/discord_platform_event.py +38 -30
- astrbot/core/platform/sources/lark/lark_adapter.py +23 -17
- astrbot/core/platform/sources/lark/lark_event.py +21 -14
- astrbot/core/platform/sources/misskey/misskey_adapter.py +107 -67
- astrbot/core/platform/sources/misskey/misskey_api.py +153 -129
- astrbot/core/platform/sources/misskey/misskey_event.py +20 -15
- astrbot/core/platform/sources/misskey/misskey_utils.py +74 -62
- astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py +63 -44
- 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 +12 -7
- astrbot/core/platform/sources/satori/satori_adapter.py +56 -38
- astrbot/core/platform/sources/satori/satori_event.py +34 -25
- astrbot/core/platform/sources/slack/client.py +11 -9
- astrbot/core/platform/sources/slack/slack_adapter.py +52 -36
- astrbot/core/platform/sources/slack/slack_event.py +34 -24
- astrbot/core/platform/sources/telegram/tg_adapter.py +38 -18
- astrbot/core/platform/sources/telegram/tg_event.py +32 -18
- astrbot/core/platform/sources/webchat/webchat_adapter.py +27 -17
- astrbot/core/platform/sources/webchat/webchat_event.py +14 -10
- astrbot/core/platform/sources/wechatpadpro/wechatpadpro_adapter.py +115 -120
- astrbot/core/platform/sources/wechatpadpro/wechatpadpro_message_event.py +9 -8
- astrbot/core/platform/sources/wechatpadpro/xml_data_parser.py +15 -16
- astrbot/core/platform/sources/wecom/wecom_adapter.py +35 -18
- astrbot/core/platform/sources/wecom/wecom_event.py +55 -48
- astrbot/core/platform/sources/wecom/wecom_kf.py +34 -44
- astrbot/core/platform/sources/wecom/wecom_kf_message.py +26 -10
- astrbot/core/platform/sources/wecom_ai_bot/WXBizJsonMsgCrypt.py +18 -10
- astrbot/core/platform/sources/wecom_ai_bot/__init__.py +3 -5
- astrbot/core/platform/sources/wecom_ai_bot/ierror.py +0 -1
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_adapter.py +61 -37
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_api.py +67 -28
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_event.py +8 -9
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_queue_mgr.py +18 -9
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_server.py +14 -12
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_utils.py +22 -12
- astrbot/core/platform/sources/weixin_official_account/weixin_offacc_adapter.py +40 -26
- astrbot/core/platform/sources/weixin_official_account/weixin_offacc_event.py +47 -45
- astrbot/core/platform_message_history_mgr.py +5 -3
- astrbot/core/provider/__init__.py +2 -3
- astrbot/core/provider/entites.py +8 -8
- astrbot/core/provider/entities.py +61 -75
- astrbot/core/provider/func_tool_manager.py +59 -55
- astrbot/core/provider/manager.py +32 -22
- astrbot/core/provider/provider.py +72 -46
- astrbot/core/provider/register.py +7 -7
- astrbot/core/provider/sources/anthropic_source.py +48 -30
- astrbot/core/provider/sources/azure_tts_source.py +17 -13
- astrbot/core/provider/sources/coze_api_client.py +27 -17
- astrbot/core/provider/sources/coze_source.py +104 -87
- astrbot/core/provider/sources/dashscope_source.py +18 -11
- astrbot/core/provider/sources/dashscope_tts.py +36 -23
- astrbot/core/provider/sources/dify_source.py +25 -20
- astrbot/core/provider/sources/edge_tts_source.py +21 -17
- astrbot/core/provider/sources/fishaudio_tts_api_source.py +22 -14
- astrbot/core/provider/sources/gemini_embedding_source.py +12 -13
- astrbot/core/provider/sources/gemini_source.py +72 -58
- astrbot/core/provider/sources/gemini_tts_source.py +8 -6
- astrbot/core/provider/sources/gsv_selfhosted_source.py +17 -14
- astrbot/core/provider/sources/gsvi_tts_source.py +11 -7
- astrbot/core/provider/sources/minimax_tts_api_source.py +50 -40
- astrbot/core/provider/sources/openai_embedding_source.py +6 -8
- astrbot/core/provider/sources/openai_source.py +77 -69
- astrbot/core/provider/sources/openai_tts_api_source.py +14 -6
- astrbot/core/provider/sources/sensevoice_selfhosted_source.py +13 -11
- astrbot/core/provider/sources/vllm_rerank_source.py +10 -4
- astrbot/core/provider/sources/volcengine_tts.py +38 -31
- astrbot/core/provider/sources/whisper_api_source.py +14 -12
- astrbot/core/provider/sources/whisper_selfhosted_source.py +15 -11
- astrbot/core/provider/sources/xinference_rerank_source.py +16 -8
- astrbot/core/provider/sources/xinference_stt_provider.py +35 -25
- astrbot/core/star/__init__.py +16 -11
- astrbot/core/star/config.py +10 -15
- astrbot/core/star/context.py +97 -75
- astrbot/core/star/filter/__init__.py +4 -3
- astrbot/core/star/filter/command.py +30 -28
- astrbot/core/star/filter/command_group.py +27 -24
- 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 +4 -2
- astrbot/core/star/filter/regex.py +4 -2
- astrbot/core/star/register/__init__.py +19 -19
- astrbot/core/star/register/star.py +6 -2
- astrbot/core/star/register/star_handler.py +96 -73
- astrbot/core/star/session_llm_manager.py +48 -14
- astrbot/core/star/session_plugin_manager.py +29 -15
- astrbot/core/star/star.py +1 -2
- astrbot/core/star/star_handler.py +13 -8
- astrbot/core/star/star_manager.py +151 -59
- astrbot/core/star/star_tools.py +44 -37
- astrbot/core/star/updator.py +10 -10
- astrbot/core/umop_config_router.py +10 -4
- astrbot/core/updator.py +13 -5
- astrbot/core/utils/astrbot_path.py +3 -5
- astrbot/core/utils/dify_api_client.py +33 -15
- astrbot/core/utils/io.py +66 -42
- astrbot/core/utils/log_pipe.py +1 -1
- astrbot/core/utils/metrics.py +7 -7
- astrbot/core/utils/path_util.py +15 -16
- astrbot/core/utils/pip_installer.py +5 -5
- astrbot/core/utils/session_waiter.py +19 -20
- astrbot/core/utils/shared_preferences.py +45 -20
- astrbot/core/utils/t2i/__init__.py +4 -1
- astrbot/core/utils/t2i/network_strategy.py +35 -26
- astrbot/core/utils/t2i/renderer.py +11 -5
- astrbot/core/utils/t2i/template_manager.py +14 -15
- astrbot/core/utils/tencent_record_helper.py +19 -13
- astrbot/core/utils/version_comparator.py +10 -13
- astrbot/core/zip_updator.py +43 -40
- astrbot/dashboard/routes/__init__.py +18 -18
- astrbot/dashboard/routes/auth.py +10 -8
- astrbot/dashboard/routes/chat.py +30 -21
- astrbot/dashboard/routes/config.py +92 -75
- astrbot/dashboard/routes/conversation.py +46 -39
- astrbot/dashboard/routes/file.py +4 -2
- astrbot/dashboard/routes/knowledge_base.py +47 -40
- astrbot/dashboard/routes/log.py +9 -4
- astrbot/dashboard/routes/persona.py +19 -16
- astrbot/dashboard/routes/plugin.py +69 -55
- astrbot/dashboard/routes/route.py +3 -1
- astrbot/dashboard/routes/session_management.py +130 -116
- astrbot/dashboard/routes/stat.py +34 -34
- astrbot/dashboard/routes/t2i.py +15 -12
- astrbot/dashboard/routes/tools.py +56 -53
- astrbot/dashboard/routes/update.py +32 -28
- astrbot/dashboard/server.py +30 -26
- astrbot/dashboard/utils.py +8 -4
- {astrbot-4.5.1.dist-info → astrbot-4.5.3.dist-info}/METADATA +2 -1
- astrbot-4.5.3.dist-info/RECORD +261 -0
- astrbot-4.5.1.dist-info/RECORD +0 -260
- {astrbot-4.5.1.dist-info → astrbot-4.5.3.dist-info}/WHEEL +0 -0
- {astrbot-4.5.1.dist-info → astrbot-4.5.3.dist-info}/entry_points.txt +0 -0
- {astrbot-4.5.1.dist-info → astrbot-4.5.3.dist-info}/licenses/LICENSE +0 -0
astrbot/core/star/star_tools.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
插件开发工具集
|
|
1
|
+
"""插件开发工具集
|
|
3
2
|
封装了许多常用的操作,方便插件开发者使用
|
|
4
3
|
|
|
5
4
|
说明:
|
|
@@ -21,47 +20,49 @@
|
|
|
21
20
|
import inspect
|
|
22
21
|
import os
|
|
23
22
|
import uuid
|
|
23
|
+
from collections.abc import Awaitable, Callable
|
|
24
24
|
from pathlib import Path
|
|
25
|
-
from typing import
|
|
25
|
+
from typing import Any, ClassVar
|
|
26
|
+
|
|
27
|
+
from astrbot.api.platform import AstrBotMessage, MessageMember, MessageType
|
|
26
28
|
from astrbot.core.message.components import BaseMessageComponent
|
|
27
29
|
from astrbot.core.message.message_event_result import MessageChain
|
|
28
|
-
from astrbot.api.platform import MessageMember, AstrBotMessage, MessageType
|
|
29
30
|
from astrbot.core.platform.astr_message_event import MessageSesion
|
|
30
|
-
from astrbot.core.star.context import Context
|
|
31
|
-
from astrbot.core.star.star import star_map
|
|
32
|
-
from astrbot.core.utils.astrbot_path import get_astrbot_data_path
|
|
33
31
|
from astrbot.core.platform.sources.aiocqhttp.aiocqhttp_message_event import (
|
|
34
32
|
AiocqhttpMessageEvent,
|
|
35
33
|
)
|
|
36
34
|
from astrbot.core.platform.sources.aiocqhttp.aiocqhttp_platform_adapter import (
|
|
37
35
|
AiocqhttpAdapter,
|
|
38
36
|
)
|
|
37
|
+
from astrbot.core.star.context import Context
|
|
38
|
+
from astrbot.core.star.star import star_map
|
|
39
|
+
from astrbot.core.utils.astrbot_path import get_astrbot_data_path
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
class StarTools:
|
|
42
|
-
"""
|
|
43
|
-
提供给插件使用的便捷工具函数集合
|
|
43
|
+
"""提供给插件使用的便捷工具函数集合
|
|
44
44
|
这些方法封装了一些常用操作,使插件开发更加简单便捷!
|
|
45
45
|
"""
|
|
46
46
|
|
|
47
|
-
_context: ClassVar[
|
|
47
|
+
_context: ClassVar[Context | None] = None
|
|
48
48
|
|
|
49
49
|
@classmethod
|
|
50
50
|
def initialize(cls, context: Context) -> None:
|
|
51
|
-
"""
|
|
52
|
-
初始化StarTools,设置context引用
|
|
51
|
+
"""初始化StarTools,设置context引用
|
|
53
52
|
|
|
54
53
|
Args:
|
|
55
54
|
context: 暴露给插件的上下文
|
|
55
|
+
|
|
56
56
|
"""
|
|
57
57
|
cls._context = context
|
|
58
58
|
|
|
59
59
|
@classmethod
|
|
60
60
|
async def send_message(
|
|
61
|
-
cls,
|
|
61
|
+
cls,
|
|
62
|
+
session: str | MessageSesion,
|
|
63
|
+
message_chain: MessageChain,
|
|
62
64
|
) -> bool:
|
|
63
|
-
"""
|
|
64
|
-
根据session(unified_msg_origin)主动发送消息
|
|
65
|
+
"""根据session(unified_msg_origin)主动发送消息
|
|
65
66
|
|
|
66
67
|
Args:
|
|
67
68
|
session: 消息会话。通过event.session或者event.unified_msg_origin获取
|
|
@@ -75,6 +76,7 @@ class StarTools:
|
|
|
75
76
|
|
|
76
77
|
Note:
|
|
77
78
|
qq_official(QQ官方API平台)不支持此方法
|
|
79
|
+
|
|
78
80
|
"""
|
|
79
81
|
if cls._context is None:
|
|
80
82
|
raise ValueError("StarTools not initialized")
|
|
@@ -88,21 +90,22 @@ class StarTools:
|
|
|
88
90
|
message_chain: MessageChain,
|
|
89
91
|
platform: str = "aiocqhttp",
|
|
90
92
|
):
|
|
91
|
-
"""
|
|
92
|
-
根据 id(例如qq号, 群号等) 直接, 主动地发送消息
|
|
93
|
+
"""根据 id(例如qq号, 群号等) 直接, 主动地发送消息
|
|
93
94
|
|
|
94
95
|
Args:
|
|
95
96
|
type (str): 消息类型, 可选: PrivateMessage, GroupMessage
|
|
96
97
|
id (str): 目标ID, 例如QQ号, 群号等
|
|
97
98
|
message_chain (MessageChain): 消息链
|
|
98
99
|
platform (str): 可选的平台名称,默认平台(aiocqhttp), 目前只支持 aiocqhttp
|
|
100
|
+
|
|
99
101
|
"""
|
|
100
102
|
if cls._context is None:
|
|
101
103
|
raise ValueError("StarTools not initialized")
|
|
102
104
|
platforms = cls._context.platform_manager.get_insts()
|
|
103
105
|
if platform == "aiocqhttp":
|
|
104
106
|
adapter = next(
|
|
105
|
-
(p for p in platforms if isinstance(p, AiocqhttpAdapter)),
|
|
107
|
+
(p for p in platforms if isinstance(p, AiocqhttpAdapter)),
|
|
108
|
+
None,
|
|
106
109
|
)
|
|
107
110
|
if adapter is None:
|
|
108
111
|
raise ValueError("未找到适配器: AiocqhttpAdapter")
|
|
@@ -122,14 +125,13 @@ class StarTools:
|
|
|
122
125
|
self_id: str,
|
|
123
126
|
session_id: str,
|
|
124
127
|
sender: MessageMember,
|
|
125
|
-
message:
|
|
128
|
+
message: list[BaseMessageComponent],
|
|
126
129
|
message_str: str,
|
|
127
130
|
message_id: str = "",
|
|
128
131
|
raw_message: object = None,
|
|
129
132
|
group_id: str = "",
|
|
130
133
|
) -> AstrBotMessage:
|
|
131
|
-
"""
|
|
132
|
-
创建一个AstrBot消息对象
|
|
134
|
+
"""创建一个AstrBot消息对象
|
|
133
135
|
|
|
134
136
|
Args:
|
|
135
137
|
type (str): 消息类型, 例如 "GroupMessage" "FriendMessage" "OtherMessage"
|
|
@@ -145,6 +147,7 @@ class StarTools:
|
|
|
145
147
|
|
|
146
148
|
Returns:
|
|
147
149
|
AstrBotMessage: 创建的消息对象
|
|
150
|
+
|
|
148
151
|
"""
|
|
149
152
|
abm = AstrBotMessage()
|
|
150
153
|
abm.type = MessageType(type)
|
|
@@ -162,23 +165,27 @@ class StarTools:
|
|
|
162
165
|
|
|
163
166
|
@classmethod
|
|
164
167
|
async def create_event(
|
|
165
|
-
cls,
|
|
168
|
+
cls,
|
|
169
|
+
abm: AstrBotMessage,
|
|
170
|
+
platform: str = "aiocqhttp",
|
|
171
|
+
is_wake: bool = True,
|
|
166
172
|
) -> None:
|
|
167
|
-
"""
|
|
168
|
-
创建并提交事件到指定平台
|
|
173
|
+
"""创建并提交事件到指定平台
|
|
169
174
|
当有需要创建一个事件, 触发某些处理流程时, 使用该方法
|
|
170
175
|
|
|
171
176
|
Args:
|
|
172
177
|
abm (AstrBotMessage): 要提交的消息对象, 请先使用 create_message 创建
|
|
173
178
|
platform (str): 可选的平台名称,默认平台(aiocqhttp), 目前只支持 aiocqhttp
|
|
174
179
|
is_wake (bool): 是否标记为唤醒事件, 默认为 True, 只有唤醒事件才会被 llm 响应
|
|
180
|
+
|
|
175
181
|
"""
|
|
176
182
|
if cls._context is None:
|
|
177
183
|
raise ValueError("StarTools not initialized")
|
|
178
184
|
platforms = cls._context.platform_manager.get_insts()
|
|
179
185
|
if platform == "aiocqhttp":
|
|
180
186
|
adapter = next(
|
|
181
|
-
(p for p in platforms if isinstance(p, AiocqhttpAdapter)),
|
|
187
|
+
(p for p in platforms if isinstance(p, AiocqhttpAdapter)),
|
|
188
|
+
None,
|
|
182
189
|
)
|
|
183
190
|
if adapter is None:
|
|
184
191
|
raise ValueError("未找到适配器: AiocqhttpAdapter")
|
|
@@ -196,12 +203,12 @@ class StarTools:
|
|
|
196
203
|
|
|
197
204
|
@classmethod
|
|
198
205
|
def activate_llm_tool(cls, name: str) -> bool:
|
|
199
|
-
"""
|
|
200
|
-
激活一个已经注册的函数调用工具
|
|
206
|
+
"""激活一个已经注册的函数调用工具
|
|
201
207
|
注册的工具默认是激活状态
|
|
202
208
|
|
|
203
209
|
Args:
|
|
204
210
|
name (str): 工具名称
|
|
211
|
+
|
|
205
212
|
"""
|
|
206
213
|
if cls._context is None:
|
|
207
214
|
raise ValueError("StarTools not initialized")
|
|
@@ -209,11 +216,11 @@ class StarTools:
|
|
|
209
216
|
|
|
210
217
|
@classmethod
|
|
211
218
|
def deactivate_llm_tool(cls, name: str) -> bool:
|
|
212
|
-
"""
|
|
213
|
-
停用一个已经注册的函数调用工具
|
|
219
|
+
"""停用一个已经注册的函数调用工具
|
|
214
220
|
|
|
215
221
|
Args:
|
|
216
222
|
name (str): 工具名称
|
|
223
|
+
|
|
217
224
|
"""
|
|
218
225
|
if cls._context is None:
|
|
219
226
|
raise ValueError("StarTools not initialized")
|
|
@@ -227,14 +234,14 @@ class StarTools:
|
|
|
227
234
|
desc: str,
|
|
228
235
|
func_obj: Callable[..., Awaitable[Any]],
|
|
229
236
|
) -> None:
|
|
230
|
-
"""
|
|
231
|
-
为函数调用(function-calling/tools-use)添加工具
|
|
237
|
+
"""为函数调用(function-calling/tools-use)添加工具
|
|
232
238
|
|
|
233
239
|
Args:
|
|
234
240
|
name (str): 工具名称
|
|
235
241
|
func_args (list): 函数参数列表
|
|
236
242
|
desc (str): 工具描述
|
|
237
243
|
func_obj (Awaitable): 函数对象,必须是异步函数
|
|
244
|
+
|
|
238
245
|
"""
|
|
239
246
|
if cls._context is None:
|
|
240
247
|
raise ValueError("StarTools not initialized")
|
|
@@ -242,21 +249,20 @@ class StarTools:
|
|
|
242
249
|
|
|
243
250
|
@classmethod
|
|
244
251
|
def unregister_llm_tool(cls, name: str) -> None:
|
|
245
|
-
"""
|
|
246
|
-
删除一个函数调用工具
|
|
252
|
+
"""删除一个函数调用工具
|
|
247
253
|
如果再要启用,需要重新注册
|
|
248
254
|
|
|
249
255
|
Args:
|
|
250
256
|
name (str): 工具名称
|
|
257
|
+
|
|
251
258
|
"""
|
|
252
259
|
if cls._context is None:
|
|
253
260
|
raise ValueError("StarTools not initialized")
|
|
254
261
|
cls._context.unregister_llm_tool(name)
|
|
255
262
|
|
|
256
263
|
@classmethod
|
|
257
|
-
def get_data_dir(cls, plugin_name:
|
|
258
|
-
"""
|
|
259
|
-
返回插件数据目录的绝对路径。
|
|
264
|
+
def get_data_dir(cls, plugin_name: str | None = None) -> Path:
|
|
265
|
+
"""返回插件数据目录的绝对路径。
|
|
260
266
|
|
|
261
267
|
此方法会在 data/plugin_data 目录下为插件创建一个专属的数据目录。如果未提供插件名称,
|
|
262
268
|
会自动从调用栈中获取插件信息。
|
|
@@ -272,6 +278,7 @@ class StarTools:
|
|
|
272
278
|
- 无法获取调用者模块信息
|
|
273
279
|
- 无法获取模块的元数据信息
|
|
274
280
|
- 创建目录失败(权限不足或其他IO错误)
|
|
281
|
+
|
|
275
282
|
"""
|
|
276
283
|
if not plugin_name:
|
|
277
284
|
frame = inspect.currentframe()
|
|
@@ -294,7 +301,7 @@ class StarTools:
|
|
|
294
301
|
raise ValueError("无法获取插件名称")
|
|
295
302
|
|
|
296
303
|
data_dir = Path(
|
|
297
|
-
os.path.join(get_astrbot_data_path(), "plugin_data", plugin_name)
|
|
304
|
+
os.path.join(get_astrbot_data_path(), "plugin_data", plugin_name),
|
|
298
305
|
)
|
|
299
306
|
|
|
300
307
|
try:
|
astrbot/core/star/updator.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import zipfile
|
|
3
2
|
import shutil
|
|
3
|
+
import zipfile
|
|
4
4
|
|
|
5
|
-
from ..updator import RepoZipUpdator
|
|
6
|
-
from astrbot.core.utils.io import remove_dir, on_error
|
|
7
|
-
from ..star.star import StarMetadata
|
|
8
5
|
from astrbot.core import logger
|
|
9
6
|
from astrbot.core.utils.astrbot_path import get_astrbot_plugin_path
|
|
7
|
+
from astrbot.core.utils.io import on_error, remove_dir
|
|
8
|
+
|
|
9
|
+
from ..star.star import StarMetadata
|
|
10
|
+
from ..updator import RepoZipUpdator
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class PluginUpdator(RepoZipUpdator):
|
|
@@ -44,7 +45,7 @@ class PluginUpdator(RepoZipUpdator):
|
|
|
44
45
|
remove_dir(plugin_path)
|
|
45
46
|
except BaseException as e:
|
|
46
47
|
logger.error(
|
|
47
|
-
f"删除旧版本插件 {plugin_path} 文件夹失败: {
|
|
48
|
+
f"删除旧版本插件 {plugin_path} 文件夹失败: {e!s},使用覆盖安装。",
|
|
48
49
|
)
|
|
49
50
|
|
|
50
51
|
self.unzip_file(plugin_path + ".zip", plugin_path)
|
|
@@ -64,18 +65,17 @@ class PluginUpdator(RepoZipUpdator):
|
|
|
64
65
|
if os.path.isdir(os.path.join(target_dir, update_dir, f)):
|
|
65
66
|
if os.path.exists(os.path.join(target_dir, f)):
|
|
66
67
|
shutil.rmtree(os.path.join(target_dir, f), onerror=on_error)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
os.remove(os.path.join(target_dir, f))
|
|
68
|
+
elif os.path.exists(os.path.join(target_dir, f)):
|
|
69
|
+
os.remove(os.path.join(target_dir, f))
|
|
70
70
|
shutil.move(os.path.join(target_dir, update_dir, f), target_dir)
|
|
71
71
|
|
|
72
72
|
try:
|
|
73
73
|
logger.info(
|
|
74
|
-
f"删除临时文件: {zip_path} 和 {os.path.join(target_dir, update_dir)}"
|
|
74
|
+
f"删除临时文件: {zip_path} 和 {os.path.join(target_dir, update_dir)}",
|
|
75
75
|
)
|
|
76
76
|
shutil.rmtree(os.path.join(target_dir, update_dir), onerror=on_error)
|
|
77
77
|
os.remove(zip_path)
|
|
78
78
|
except BaseException:
|
|
79
79
|
logger.warning(
|
|
80
|
-
f"删除更新文件失败,可以手动删除 {zip_path} 和 {os.path.join(target_dir, update_dir)}"
|
|
80
|
+
f"删除更新文件失败,可以手动删除 {zip_path} 和 {os.path.join(target_dir, update_dir)}",
|
|
81
81
|
)
|
|
@@ -15,7 +15,10 @@ class UmopConfigRouter:
|
|
|
15
15
|
"""加载路由表"""
|
|
16
16
|
# 从 SharedPreferences 中加载 umop_to_conf_id 映射
|
|
17
17
|
sp_data = self.sp.get(
|
|
18
|
-
"umop_config_routing",
|
|
18
|
+
"umop_config_routing",
|
|
19
|
+
{},
|
|
20
|
+
scope="global",
|
|
21
|
+
scope_id="global",
|
|
19
22
|
)
|
|
20
23
|
self.umop_to_conf_id = sp_data
|
|
21
24
|
|
|
@@ -37,6 +40,7 @@ class UmopConfigRouter:
|
|
|
37
40
|
|
|
38
41
|
Returns:
|
|
39
42
|
str | None: 配置文件 ID,如果没有找到则返回 None
|
|
43
|
+
|
|
40
44
|
"""
|
|
41
45
|
for pattern, conf_id in self.umop_to_conf_id.items():
|
|
42
46
|
if self._is_umo_match(pattern, umo):
|
|
@@ -52,11 +56,12 @@ class UmopConfigRouter:
|
|
|
52
56
|
|
|
53
57
|
Raises:
|
|
54
58
|
ValueError: 如果 new_routing 中的 key 格式不正确
|
|
59
|
+
|
|
55
60
|
"""
|
|
56
|
-
for part in new_routing
|
|
61
|
+
for part in new_routing:
|
|
57
62
|
if not isinstance(part, str) or len(part.split(":")) != 3:
|
|
58
63
|
raise ValueError(
|
|
59
|
-
"umop keys must be strings in the format [platform_id]:[message_type]:[session_id], with optional wildcards * or empty for all"
|
|
64
|
+
"umop keys must be strings in the format [platform_id]:[message_type]:[session_id], with optional wildcards * or empty for all",
|
|
60
65
|
)
|
|
61
66
|
|
|
62
67
|
self.umop_to_conf_id = new_routing
|
|
@@ -71,10 +76,11 @@ class UmopConfigRouter:
|
|
|
71
76
|
|
|
72
77
|
Raises:
|
|
73
78
|
ValueError: 如果 umo 格式不正确
|
|
79
|
+
|
|
74
80
|
"""
|
|
75
81
|
if not isinstance(umo, str) or len(umo.split(":")) != 3:
|
|
76
82
|
raise ValueError(
|
|
77
|
-
"umop must be a string in the format [platform_id]:[message_type]:[session_id], with optional wildcards * or empty for all"
|
|
83
|
+
"umop must be a string in the format [platform_id]:[message_type]:[session_id], with optional wildcards * or empty for all",
|
|
78
84
|
)
|
|
79
85
|
|
|
80
86
|
self.umop_to_conf_id[umo] = conf_id
|
astrbot/core/updator.py
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import psutil
|
|
3
2
|
import sys
|
|
4
3
|
import time
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
import psutil
|
|
6
|
+
|
|
6
7
|
from astrbot.core import logger
|
|
7
8
|
from astrbot.core.config.default import VERSION
|
|
8
|
-
from astrbot.core.utils.io import download_file
|
|
9
9
|
from astrbot.core.utils.astrbot_path import get_astrbot_path
|
|
10
|
+
from astrbot.core.utils.io import download_file
|
|
11
|
+
|
|
12
|
+
from .zip_updator import ReleaseInfo, RepoZipUpdator
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class AstrBotUpdator(RepoZipUpdator):
|
|
@@ -67,11 +70,16 @@ class AstrBotUpdator(RepoZipUpdator):
|
|
|
67
70
|
raise e
|
|
68
71
|
|
|
69
72
|
async def check_update(
|
|
70
|
-
self,
|
|
73
|
+
self,
|
|
74
|
+
url: str,
|
|
75
|
+
current_version: str,
|
|
76
|
+
consider_prerelease: bool = True,
|
|
71
77
|
) -> ReleaseInfo:
|
|
72
78
|
"""检查更新"""
|
|
73
79
|
return await super().check_update(
|
|
74
|
-
self.ASTRBOT_RELEASE_API,
|
|
80
|
+
self.ASTRBOT_RELEASE_API,
|
|
81
|
+
VERSION,
|
|
82
|
+
consider_prerelease,
|
|
75
83
|
)
|
|
76
84
|
|
|
77
85
|
async def get_releases(self) -> list:
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Astrbot统一路径获取
|
|
1
|
+
"""Astrbot统一路径获取
|
|
3
2
|
|
|
4
3
|
项目路径:固定为源码所在路径
|
|
5
4
|
根目录路径:默认为当前工作目录,可通过环境变量 ASTRBOT_ROOT 指定
|
|
@@ -14,7 +13,7 @@ import os
|
|
|
14
13
|
def get_astrbot_path() -> str:
|
|
15
14
|
"""获取Astrbot项目路径"""
|
|
16
15
|
return os.path.realpath(
|
|
17
|
-
os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../")
|
|
16
|
+
os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../"),
|
|
18
17
|
)
|
|
19
18
|
|
|
20
19
|
|
|
@@ -22,8 +21,7 @@ def get_astrbot_root() -> str:
|
|
|
22
21
|
"""获取Astrbot根目录路径"""
|
|
23
22
|
if path := os.environ.get("ASTRBOT_ROOT"):
|
|
24
23
|
return os.path.realpath(path)
|
|
25
|
-
|
|
26
|
-
return os.path.realpath(os.getcwd())
|
|
24
|
+
return os.path.realpath(os.getcwd())
|
|
27
25
|
|
|
28
26
|
|
|
29
27
|
def get_astrbot_data_path() -> str:
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import codecs
|
|
2
2
|
import json
|
|
3
|
+
from collections.abc import AsyncGenerator
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from aiohttp import ClientResponse, ClientSession
|
|
7
|
+
|
|
3
8
|
from astrbot.core import logger
|
|
4
|
-
from aiohttp import ClientSession, ClientResponse
|
|
5
|
-
from typing import Dict, List, Any, AsyncGenerator
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
async def _stream_sse(resp: ClientResponse) -> AsyncGenerator[dict, None]:
|
|
@@ -25,7 +28,6 @@ async def _stream_sse(resp: ClientResponse) -> AsyncGenerator[dict, None]:
|
|
|
25
28
|
yield json.loads(buffer[5:])
|
|
26
29
|
except json.JSONDecodeError:
|
|
27
30
|
logger.warning(f"Drop invalid dify json data: {buffer[5:]}")
|
|
28
|
-
pass
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
class DifyAPIClient:
|
|
@@ -39,50 +41,60 @@ class DifyAPIClient:
|
|
|
39
41
|
|
|
40
42
|
async def chat_messages(
|
|
41
43
|
self,
|
|
42
|
-
inputs:
|
|
44
|
+
inputs: dict,
|
|
43
45
|
query: str,
|
|
44
46
|
user: str,
|
|
45
47
|
response_mode: str = "streaming",
|
|
46
48
|
conversation_id: str = "",
|
|
47
|
-
files:
|
|
49
|
+
files: list[dict[str, Any]] | None = None,
|
|
48
50
|
timeout: float = 60,
|
|
49
|
-
) -> AsyncGenerator[
|
|
51
|
+
) -> AsyncGenerator[dict[str, Any], None]:
|
|
52
|
+
if files is None:
|
|
53
|
+
files = []
|
|
50
54
|
url = f"{self.api_base}/chat-messages"
|
|
51
55
|
payload = locals()
|
|
52
56
|
payload.pop("self")
|
|
53
57
|
payload.pop("timeout")
|
|
54
58
|
logger.info(f"chat_messages payload: {payload}")
|
|
55
59
|
async with self.session.post(
|
|
56
|
-
url,
|
|
60
|
+
url,
|
|
61
|
+
json=payload,
|
|
62
|
+
headers=self.headers,
|
|
63
|
+
timeout=timeout,
|
|
57
64
|
) as resp:
|
|
58
65
|
if resp.status != 200:
|
|
59
66
|
text = await resp.text()
|
|
60
67
|
raise Exception(
|
|
61
|
-
f"Dify /chat-messages 接口请求失败:{resp.status}. {text}"
|
|
68
|
+
f"Dify /chat-messages 接口请求失败:{resp.status}. {text}",
|
|
62
69
|
)
|
|
63
70
|
async for event in _stream_sse(resp):
|
|
64
71
|
yield event
|
|
65
72
|
|
|
66
73
|
async def workflow_run(
|
|
67
74
|
self,
|
|
68
|
-
inputs:
|
|
75
|
+
inputs: dict,
|
|
69
76
|
user: str,
|
|
70
77
|
response_mode: str = "streaming",
|
|
71
|
-
files:
|
|
78
|
+
files: list[dict[str, Any]] | None = None,
|
|
72
79
|
timeout: float = 60,
|
|
73
80
|
):
|
|
81
|
+
if files is None:
|
|
82
|
+
files = []
|
|
74
83
|
url = f"{self.api_base}/workflows/run"
|
|
75
84
|
payload = locals()
|
|
76
85
|
payload.pop("self")
|
|
77
86
|
payload.pop("timeout")
|
|
78
87
|
logger.info(f"workflow_run payload: {payload}")
|
|
79
88
|
async with self.session.post(
|
|
80
|
-
url,
|
|
89
|
+
url,
|
|
90
|
+
json=payload,
|
|
91
|
+
headers=self.headers,
|
|
92
|
+
timeout=timeout,
|
|
81
93
|
) as resp:
|
|
82
94
|
if resp.status != 200:
|
|
83
95
|
text = await resp.text()
|
|
84
96
|
raise Exception(
|
|
85
|
-
f"Dify /workflows/run 接口请求失败:{resp.status}. {text}"
|
|
97
|
+
f"Dify /workflows/run 接口请求失败:{resp.status}. {text}",
|
|
86
98
|
)
|
|
87
99
|
async for event in _stream_sse(resp):
|
|
88
100
|
yield event
|
|
@@ -91,7 +103,7 @@ class DifyAPIClient:
|
|
|
91
103
|
self,
|
|
92
104
|
file_path: str,
|
|
93
105
|
user: str,
|
|
94
|
-
) ->
|
|
106
|
+
) -> dict[str, Any]:
|
|
95
107
|
url = f"{self.api_base}/files/upload"
|
|
96
108
|
with open(file_path, "rb") as f:
|
|
97
109
|
payload = {
|
|
@@ -99,7 +111,9 @@ class DifyAPIClient:
|
|
|
99
111
|
"file": f,
|
|
100
112
|
}
|
|
101
113
|
async with self.session.post(
|
|
102
|
-
url,
|
|
114
|
+
url,
|
|
115
|
+
data=payload,
|
|
116
|
+
headers=self.headers,
|
|
103
117
|
) as resp:
|
|
104
118
|
return await resp.json() # {"id": "xxx", ...}
|
|
105
119
|
|
|
@@ -126,7 +140,11 @@ class DifyAPIClient:
|
|
|
126
140
|
return await resp.json()
|
|
127
141
|
|
|
128
142
|
async def rename(
|
|
129
|
-
self,
|
|
143
|
+
self,
|
|
144
|
+
conversation_id: str,
|
|
145
|
+
name: str,
|
|
146
|
+
user: str,
|
|
147
|
+
auto_generate: bool = False,
|
|
130
148
|
):
|
|
131
149
|
# /conversations/:conversation_id/name
|
|
132
150
|
url = f"{self.api_base}/conversations/{conversation_id}/name"
|