AstrBot 4.1.4__py3-none-any.whl → 4.1.5__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/core/agent/agent.py +1 -1
- astrbot/core/agent/mcp_client.py +3 -1
- astrbot/core/agent/runners/tool_loop_agent_runner.py +6 -27
- astrbot/core/agent/tool.py +28 -17
- astrbot/core/config/default.py +50 -14
- astrbot/core/db/sqlite.py +15 -1
- astrbot/core/pipeline/content_safety_check/stage.py +1 -1
- astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py +1 -1
- astrbot/core/pipeline/content_safety_check/strategies/keywords.py +1 -1
- astrbot/core/pipeline/context_utils.py +4 -1
- astrbot/core/pipeline/process_stage/method/llm_request.py +23 -4
- astrbot/core/pipeline/process_stage/method/star_request.py +8 -6
- astrbot/core/platform/manager.py +4 -0
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +2 -1
- astrbot/core/platform/sources/misskey/misskey_adapter.py +391 -0
- astrbot/core/platform/sources/misskey/misskey_api.py +404 -0
- astrbot/core/platform/sources/misskey/misskey_event.py +123 -0
- astrbot/core/platform/sources/misskey/misskey_utils.py +327 -0
- astrbot/core/platform/sources/satori/satori_adapter.py +290 -24
- astrbot/core/platform/sources/satori/satori_event.py +9 -0
- astrbot/core/platform/sources/telegram/tg_event.py +0 -1
- astrbot/core/provider/entities.py +13 -3
- astrbot/core/provider/func_tool_manager.py +4 -4
- astrbot/core/provider/manager.py +35 -19
- astrbot/core/star/context.py +26 -12
- astrbot/core/star/filter/command_group.py +4 -4
- astrbot/core/star/filter/platform_adapter_type.py +10 -5
- astrbot/core/star/register/star.py +3 -1
- astrbot/core/star/register/star_handler.py +65 -36
- astrbot/core/star/session_plugin_manager.py +3 -0
- astrbot/core/star/star_handler.py +4 -4
- astrbot/core/star/star_manager.py +10 -4
- astrbot/core/star/star_tools.py +6 -2
- astrbot/core/star/updator.py +3 -0
- {astrbot-4.1.4.dist-info → astrbot-4.1.5.dist-info}/METADATA +6 -7
- {astrbot-4.1.4.dist-info → astrbot-4.1.5.dist-info}/RECORD +39 -35
- {astrbot-4.1.4.dist-info → astrbot-4.1.5.dist-info}/WHEEL +0 -0
- {astrbot-4.1.4.dist-info → astrbot-4.1.5.dist-info}/entry_points.txt +0 -0
- {astrbot-4.1.4.dist-info → astrbot-4.1.5.dist-info}/licenses/LICENSE +0 -0
astrbot/core/star/context.py
CHANGED
|
@@ -23,7 +23,7 @@ from .star import star_registry, StarMetadata, star_map
|
|
|
23
23
|
from .star_handler import star_handlers_registry, StarHandlerMetadata, EventType
|
|
24
24
|
from .filter.command import CommandFilter
|
|
25
25
|
from .filter.regex import RegexFilter
|
|
26
|
-
from typing import Awaitable
|
|
26
|
+
from typing import Awaitable, Any, Callable
|
|
27
27
|
from astrbot.core.conversation_mgr import ConversationManager
|
|
28
28
|
from astrbot.core.star.filter.platform_adapter_type import (
|
|
29
29
|
PlatformAdapterType,
|
|
@@ -105,7 +105,10 @@ class Context:
|
|
|
105
105
|
|
|
106
106
|
def get_provider_by_id(self, provider_id: str) -> Provider | None:
|
|
107
107
|
"""通过 ID 获取对应的 LLM Provider(Chat_Completion 类型)。"""
|
|
108
|
-
|
|
108
|
+
prov = self.provider_manager.inst_map.get(provider_id)
|
|
109
|
+
if prov and not isinstance(prov, Provider):
|
|
110
|
+
raise ValueError("返回的 Provider 不是 Provider 类型")
|
|
111
|
+
return prov
|
|
109
112
|
|
|
110
113
|
def get_all_providers(self) -> List[Provider]:
|
|
111
114
|
"""获取所有用于文本生成任务的 LLM Provider(Chat_Completion 类型)。"""
|
|
@@ -130,34 +133,43 @@ class Context:
|
|
|
130
133
|
Args:
|
|
131
134
|
umo(str): unified_message_origin 值,如果传入并且用户启用了提供商会话隔离,则使用该会话偏好的提供商。
|
|
132
135
|
"""
|
|
133
|
-
|
|
136
|
+
prov = self.provider_manager.get_using_provider(
|
|
134
137
|
provider_type=ProviderType.CHAT_COMPLETION,
|
|
135
138
|
umo=umo,
|
|
136
139
|
)
|
|
140
|
+
if prov and not isinstance(prov, Provider):
|
|
141
|
+
raise ValueError("返回的 Provider 不是 Provider 类型")
|
|
142
|
+
return prov
|
|
137
143
|
|
|
138
|
-
def get_using_tts_provider(self, umo: str | None = None) -> TTSProvider:
|
|
144
|
+
def get_using_tts_provider(self, umo: str | None = None) -> TTSProvider | None:
|
|
139
145
|
"""
|
|
140
146
|
获取当前使用的用于 TTS 任务的 Provider。
|
|
141
147
|
|
|
142
148
|
Args:
|
|
143
149
|
umo(str): unified_message_origin 值,如果传入,则使用该会话偏好的提供商。
|
|
144
150
|
"""
|
|
145
|
-
|
|
151
|
+
prov = self.provider_manager.get_using_provider(
|
|
146
152
|
provider_type=ProviderType.TEXT_TO_SPEECH,
|
|
147
153
|
umo=umo,
|
|
148
154
|
)
|
|
155
|
+
if prov and not isinstance(prov, TTSProvider):
|
|
156
|
+
raise ValueError("返回的 Provider 不是 TTSProvider 类型")
|
|
157
|
+
return prov
|
|
149
158
|
|
|
150
|
-
def get_using_stt_provider(self, umo: str | None = None) -> STTProvider:
|
|
159
|
+
def get_using_stt_provider(self, umo: str | None = None) -> STTProvider | None:
|
|
151
160
|
"""
|
|
152
161
|
获取当前使用的用于 STT 任务的 Provider。
|
|
153
162
|
|
|
154
163
|
Args:
|
|
155
164
|
umo(str): unified_message_origin 值,如果传入,则使用该会话偏好的提供商。
|
|
156
165
|
"""
|
|
157
|
-
|
|
166
|
+
prov = self.provider_manager.get_using_provider(
|
|
158
167
|
provider_type=ProviderType.SPEECH_TO_TEXT,
|
|
159
168
|
umo=umo,
|
|
160
169
|
)
|
|
170
|
+
if prov and not isinstance(prov, STTProvider):
|
|
171
|
+
raise ValueError("返回的 Provider 不是 STTProvider 类型")
|
|
172
|
+
return prov
|
|
161
173
|
|
|
162
174
|
def get_config(self, umo: str | None = None) -> AstrBotConfig:
|
|
163
175
|
"""获取 AstrBot 的配置。"""
|
|
@@ -245,7 +257,11 @@ class Context:
|
|
|
245
257
|
"""
|
|
246
258
|
|
|
247
259
|
def register_llm_tool(
|
|
248
|
-
self,
|
|
260
|
+
self,
|
|
261
|
+
name: str,
|
|
262
|
+
func_args: list,
|
|
263
|
+
desc: str,
|
|
264
|
+
func_obj: Callable[..., Awaitable[Any]],
|
|
249
265
|
) -> None:
|
|
250
266
|
"""
|
|
251
267
|
为函数调用(function-calling / tools-use)添加工具。
|
|
@@ -267,9 +283,7 @@ class Context:
|
|
|
267
283
|
desc=desc,
|
|
268
284
|
)
|
|
269
285
|
star_handlers_registry.append(md)
|
|
270
|
-
self.provider_manager.llm_tools.add_func(
|
|
271
|
-
name, func_args, desc, func_obj, func_obj
|
|
272
|
-
)
|
|
286
|
+
self.provider_manager.llm_tools.add_func(name, func_args, desc, func_obj)
|
|
273
287
|
|
|
274
288
|
def unregister_llm_tool(self, name: str) -> None:
|
|
275
289
|
"""删除一个函数调用工具。如果再要启用,需要重新注册。"""
|
|
@@ -281,7 +295,7 @@ class Context:
|
|
|
281
295
|
command_name: str,
|
|
282
296
|
desc: str,
|
|
283
297
|
priority: int,
|
|
284
|
-
awaitable: Awaitable,
|
|
298
|
+
awaitable: Callable[..., Awaitable[Any]],
|
|
285
299
|
use_regex=False,
|
|
286
300
|
ignore_prefix=False,
|
|
287
301
|
):
|
|
@@ -13,8 +13,8 @@ class CommandGroupFilter(HandlerFilter):
|
|
|
13
13
|
def __init__(
|
|
14
14
|
self,
|
|
15
15
|
group_name: str,
|
|
16
|
-
alias: set = None,
|
|
17
|
-
parent_group: CommandGroupFilter = None,
|
|
16
|
+
alias: set | None = None,
|
|
17
|
+
parent_group: CommandGroupFilter | None = None,
|
|
18
18
|
):
|
|
19
19
|
self.group_name = group_name
|
|
20
20
|
self.alias = alias if alias else set()
|
|
@@ -54,8 +54,8 @@ class CommandGroupFilter(HandlerFilter):
|
|
|
54
54
|
self,
|
|
55
55
|
sub_command_filters: List[Union[CommandFilter, CommandGroupFilter]],
|
|
56
56
|
prefix: str = "",
|
|
57
|
-
event: AstrMessageEvent = None,
|
|
58
|
-
cfg: AstrBotConfig = None,
|
|
57
|
+
event: AstrMessageEvent | None = None,
|
|
58
|
+
cfg: AstrBotConfig | None = None,
|
|
59
59
|
) -> str:
|
|
60
60
|
result = ""
|
|
61
61
|
for sub_filter in sub_command_filters:
|
|
@@ -2,7 +2,6 @@ import enum
|
|
|
2
2
|
from . import HandlerFilter
|
|
3
3
|
from astrbot.core.platform.astr_message_event import AstrMessageEvent
|
|
4
4
|
from astrbot.core.config import AstrBotConfig
|
|
5
|
-
from typing import Union
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class PlatformAdapterType(enum.Flag):
|
|
@@ -19,6 +18,7 @@ class PlatformAdapterType(enum.Flag):
|
|
|
19
18
|
VOCECHAT = enum.auto()
|
|
20
19
|
WEIXIN_OFFICIAL_ACCOUNT = enum.auto()
|
|
21
20
|
SATORI = enum.auto()
|
|
21
|
+
MISSKEY = enum.auto()
|
|
22
22
|
ALL = (
|
|
23
23
|
AIOCQHTTP
|
|
24
24
|
| QQOFFICIAL
|
|
@@ -33,6 +33,7 @@ class PlatformAdapterType(enum.Flag):
|
|
|
33
33
|
| VOCECHAT
|
|
34
34
|
| WEIXIN_OFFICIAL_ACCOUNT
|
|
35
35
|
| SATORI
|
|
36
|
+
| MISSKEY
|
|
36
37
|
)
|
|
37
38
|
|
|
38
39
|
|
|
@@ -50,15 +51,19 @@ ADAPTER_NAME_2_TYPE = {
|
|
|
50
51
|
"vocechat": PlatformAdapterType.VOCECHAT,
|
|
51
52
|
"weixin_official_account": PlatformAdapterType.WEIXIN_OFFICIAL_ACCOUNT,
|
|
52
53
|
"satori": PlatformAdapterType.SATORI,
|
|
54
|
+
"misskey": PlatformAdapterType.MISSKEY,
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
|
|
56
58
|
class PlatformAdapterTypeFilter(HandlerFilter):
|
|
57
|
-
def __init__(self, platform_adapter_type_or_str:
|
|
58
|
-
|
|
59
|
+
def __init__(self, platform_adapter_type_or_str: PlatformAdapterType | str):
|
|
60
|
+
if isinstance(platform_adapter_type_or_str, str):
|
|
61
|
+
self.platform_type = ADAPTER_NAME_2_TYPE.get(platform_adapter_type_or_str)
|
|
62
|
+
else:
|
|
63
|
+
self.platform_type = platform_adapter_type_or_str
|
|
59
64
|
|
|
60
65
|
def filter(self, event: AstrMessageEvent, cfg: AstrBotConfig) -> bool:
|
|
61
66
|
adapter_name = event.get_platform_name()
|
|
62
|
-
if adapter_name in ADAPTER_NAME_2_TYPE:
|
|
63
|
-
return ADAPTER_NAME_2_TYPE[adapter_name] & self.
|
|
67
|
+
if adapter_name in ADAPTER_NAME_2_TYPE and self.platform_type is not None:
|
|
68
|
+
return bool(ADAPTER_NAME_2_TYPE[adapter_name] & self.platform_type)
|
|
64
69
|
return False
|
|
@@ -5,7 +5,9 @@ from astrbot.core.star import StarMetadata, star_map
|
|
|
5
5
|
_warned_register_star = False
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def register_star(
|
|
8
|
+
def register_star(
|
|
9
|
+
name: str, author: str, desc: str, version: str, repo: str | None = None
|
|
10
|
+
):
|
|
9
11
|
"""注册一个插件(Star)。
|
|
10
12
|
|
|
11
13
|
[DEPRECATED] 该装饰器已废弃,将在未来版本中移除。
|
|
@@ -12,7 +12,7 @@ from ..filter.platform_adapter_type import (
|
|
|
12
12
|
from ..filter.permission import PermissionTypeFilter, PermissionType
|
|
13
13
|
from ..filter.custom_filter import CustomFilterAnd, CustomFilterOr
|
|
14
14
|
from ..filter.regex import RegexFilter
|
|
15
|
-
from typing import Awaitable
|
|
15
|
+
from typing import Awaitable, Any, Callable
|
|
16
16
|
from astrbot.core.provider.func_tool_manager import SUPPORTED_TYPES
|
|
17
17
|
from astrbot.core.provider.register import llm_tools
|
|
18
18
|
from astrbot.core.agent.agent import Agent
|
|
@@ -20,15 +20,19 @@ from astrbot.core.agent.tool import FunctionTool
|
|
|
20
20
|
from astrbot.core.agent.handoff import HandoffTool
|
|
21
21
|
from astrbot.core.agent.hooks import BaseAgentRunHooks
|
|
22
22
|
from astrbot.core.astr_agent_context import AstrAgentContext
|
|
23
|
+
from astrbot.core import logger
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
def get_handler_full_name(awaitable: Awaitable) -> str:
|
|
26
|
+
def get_handler_full_name(awaitable: Callable[..., Awaitable[Any]]) -> str:
|
|
26
27
|
"""获取 Handler 的全名"""
|
|
27
28
|
return f"{awaitable.__module__}_{awaitable.__name__}"
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def get_handler_or_create(
|
|
31
|
-
handler: Awaitable,
|
|
32
|
+
handler: Callable[..., Awaitable[Any]],
|
|
33
|
+
event_type: EventType,
|
|
34
|
+
dont_add=False,
|
|
35
|
+
**kwargs,
|
|
32
36
|
) -> StarHandlerMetadata:
|
|
33
37
|
"""获取 Handler 或者创建一个新的 Handler"""
|
|
34
38
|
handler_full_name = get_handler_full_name(handler)
|
|
@@ -59,22 +63,35 @@ def get_handler_or_create(
|
|
|
59
63
|
|
|
60
64
|
|
|
61
65
|
def register_command(
|
|
62
|
-
command_name: str
|
|
66
|
+
command_name: str | None = None,
|
|
67
|
+
sub_command: str | None = None,
|
|
68
|
+
alias: set | None = None,
|
|
69
|
+
**kwargs,
|
|
63
70
|
):
|
|
64
71
|
"""注册一个 Command."""
|
|
65
72
|
new_command = None
|
|
66
73
|
add_to_event_filters = False
|
|
67
74
|
if isinstance(command_name, RegisteringCommandable):
|
|
68
75
|
# 子指令
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
if sub_command is not None:
|
|
77
|
+
parent_command_names = (
|
|
78
|
+
command_name.parent_group.get_complete_command_names()
|
|
79
|
+
)
|
|
80
|
+
new_command = CommandFilter(
|
|
81
|
+
sub_command, alias, None, parent_command_names=parent_command_names
|
|
82
|
+
)
|
|
83
|
+
command_name.parent_group.add_sub_command_filter(new_command)
|
|
84
|
+
else:
|
|
85
|
+
logger.warning(
|
|
86
|
+
f"注册指令{command_name} 的子指令时未提供 sub_command 参数。"
|
|
87
|
+
)
|
|
74
88
|
else:
|
|
75
89
|
# 裸指令
|
|
76
|
-
|
|
77
|
-
|
|
90
|
+
if command_name is None:
|
|
91
|
+
logger.warning("注册裸指令时未提供 command_name 参数。")
|
|
92
|
+
else:
|
|
93
|
+
new_command = CommandFilter(command_name, alias, None)
|
|
94
|
+
add_to_event_filters = True
|
|
78
95
|
|
|
79
96
|
def decorator(awaitable):
|
|
80
97
|
if not add_to_event_filters:
|
|
@@ -84,8 +101,9 @@ def register_command(
|
|
|
84
101
|
handler_md = get_handler_or_create(
|
|
85
102
|
awaitable, EventType.AdapterMessageEvent, **kwargs
|
|
86
103
|
)
|
|
87
|
-
new_command
|
|
88
|
-
|
|
104
|
+
if new_command:
|
|
105
|
+
new_command.init_handler_md(handler_md)
|
|
106
|
+
handler_md.event_filters.append(new_command)
|
|
89
107
|
return awaitable
|
|
90
108
|
|
|
91
109
|
return decorator
|
|
@@ -163,26 +181,38 @@ def register_custom_filter(custom_type_filter, *args, **kwargs):
|
|
|
163
181
|
|
|
164
182
|
|
|
165
183
|
def register_command_group(
|
|
166
|
-
command_group_name: str
|
|
184
|
+
command_group_name: str | None = None,
|
|
185
|
+
sub_command: str | None = None,
|
|
186
|
+
alias: set | None = None,
|
|
187
|
+
**kwargs,
|
|
167
188
|
):
|
|
168
189
|
"""注册一个 CommandGroup"""
|
|
169
190
|
new_group = None
|
|
170
191
|
if isinstance(command_group_name, RegisteringCommandable):
|
|
171
192
|
# 子指令组
|
|
172
|
-
|
|
173
|
-
sub_command
|
|
174
|
-
|
|
175
|
-
|
|
193
|
+
if sub_command is None:
|
|
194
|
+
logger.warning(f"{command_group_name} 指令组的子指令组 sub_command 未指定")
|
|
195
|
+
else:
|
|
196
|
+
new_group = CommandGroupFilter(
|
|
197
|
+
sub_command, alias, parent_group=command_group_name.parent_group
|
|
198
|
+
)
|
|
199
|
+
command_group_name.parent_group.add_sub_command_filter(new_group)
|
|
176
200
|
else:
|
|
177
201
|
# 根指令组
|
|
178
|
-
|
|
202
|
+
if command_group_name is None:
|
|
203
|
+
logger.warning("根指令组的名称未指定")
|
|
204
|
+
else:
|
|
205
|
+
new_group = CommandGroupFilter(command_group_name, alias)
|
|
179
206
|
|
|
180
207
|
def decorator(obj):
|
|
181
208
|
# 根指令组
|
|
182
|
-
|
|
183
|
-
|
|
209
|
+
if new_group:
|
|
210
|
+
handler_md = get_handler_or_create(
|
|
211
|
+
obj, EventType.AdapterMessageEvent, **kwargs
|
|
212
|
+
)
|
|
213
|
+
handler_md.event_filters.append(new_group)
|
|
184
214
|
|
|
185
|
-
|
|
215
|
+
return RegisteringCommandable(new_group)
|
|
186
216
|
|
|
187
217
|
return decorator
|
|
188
218
|
|
|
@@ -323,7 +353,7 @@ def register_on_llm_response(**kwargs):
|
|
|
323
353
|
return decorator
|
|
324
354
|
|
|
325
355
|
|
|
326
|
-
def register_llm_tool(name: str = None, **kwargs):
|
|
356
|
+
def register_llm_tool(name: str | None = None, **kwargs):
|
|
327
357
|
"""为函数调用(function-calling / tools-use)添加工具。
|
|
328
358
|
|
|
329
359
|
请务必按照以下格式编写一个工具(包括函数注释,AstrBot 会尝试解析该函数注释)
|
|
@@ -361,9 +391,10 @@ def register_llm_tool(name: str = None, **kwargs):
|
|
|
361
391
|
if kwargs.get("registering_agent"):
|
|
362
392
|
registering_agent = kwargs["registering_agent"]
|
|
363
393
|
|
|
364
|
-
def decorator(awaitable: Awaitable):
|
|
394
|
+
def decorator(awaitable: Callable[..., Awaitable[Any]]):
|
|
365
395
|
llm_tool_name = name_ if name_ else awaitable.__name__
|
|
366
|
-
|
|
396
|
+
func_doc = awaitable.__doc__ or ""
|
|
397
|
+
docstring = docstring_parser.parse(func_doc)
|
|
367
398
|
args = []
|
|
368
399
|
for arg in docstring.params:
|
|
369
400
|
if arg.type_name not in SUPPORTED_TYPES:
|
|
@@ -379,20 +410,18 @@ def register_llm_tool(name: str = None, **kwargs):
|
|
|
379
410
|
)
|
|
380
411
|
# print(llm_tool_name, registering_agent)
|
|
381
412
|
if not registering_agent:
|
|
413
|
+
doc_desc = docstring.description.strip() if docstring.description else ""
|
|
382
414
|
md = get_handler_or_create(awaitable, EventType.OnCallingFuncToolEvent)
|
|
383
|
-
llm_tools.add_func(
|
|
384
|
-
llm_tool_name, args, docstring.description.strip(), md.handler
|
|
385
|
-
)
|
|
415
|
+
llm_tools.add_func(llm_tool_name, args, doc_desc, md.handler)
|
|
386
416
|
else:
|
|
387
417
|
assert isinstance(registering_agent, RegisteringAgent)
|
|
388
418
|
# print(f"Registering tool {llm_tool_name} for agent", registering_agent._agent.name)
|
|
389
419
|
if registering_agent._agent.tools is None:
|
|
390
420
|
registering_agent._agent.tools = []
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
)
|
|
421
|
+
|
|
422
|
+
desc = docstring.description.strip() if docstring.description else ""
|
|
423
|
+
tool = llm_tools.spec_to_func(llm_tool_name, args, desc, awaitable)
|
|
424
|
+
registering_agent._agent.tools.append(tool)
|
|
396
425
|
|
|
397
426
|
return awaitable
|
|
398
427
|
|
|
@@ -413,8 +442,8 @@ class RegisteringAgent:
|
|
|
413
442
|
def register_agent(
|
|
414
443
|
name: str,
|
|
415
444
|
instruction: str,
|
|
416
|
-
tools: list[str | FunctionTool] = None,
|
|
417
|
-
run_hooks: BaseAgentRunHooks[AstrAgentContext] = None,
|
|
445
|
+
tools: list[str | FunctionTool] | None = None,
|
|
446
|
+
run_hooks: BaseAgentRunHooks[AstrAgentContext] | None = None,
|
|
418
447
|
):
|
|
419
448
|
"""注册一个 Agent
|
|
420
449
|
|
|
@@ -426,7 +455,7 @@ def register_agent(
|
|
|
426
455
|
"""
|
|
427
456
|
tools_ = tools or []
|
|
428
457
|
|
|
429
|
-
def decorator(awaitable: Awaitable):
|
|
458
|
+
def decorator(awaitable: Callable[..., Awaitable[Any]]):
|
|
430
459
|
AstrAgent = Agent[AstrAgentContext]
|
|
431
460
|
agent = AstrAgent(
|
|
432
461
|
name=name,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import enum
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import Awaitable, List, Dict, TypeVar, Generic
|
|
4
|
+
from typing import Callable, Awaitable, Any, List, Dict, TypeVar, Generic
|
|
5
5
|
from .filter import HandlerFilter
|
|
6
6
|
from .star import star_map
|
|
7
7
|
|
|
@@ -60,7 +60,7 @@ class StarHandlerRegistry(Generic[T]):
|
|
|
60
60
|
handlers.append(handler)
|
|
61
61
|
return handlers
|
|
62
62
|
|
|
63
|
-
def get_handler_by_full_name(self, full_name: str) -> StarHandlerMetadata:
|
|
63
|
+
def get_handler_by_full_name(self, full_name: str) -> StarHandlerMetadata | None:
|
|
64
64
|
return self.star_handlers_map.get(full_name, None)
|
|
65
65
|
|
|
66
66
|
def get_handlers_by_module_name(
|
|
@@ -87,7 +87,7 @@ class StarHandlerRegistry(Generic[T]):
|
|
|
87
87
|
return len(self._handlers)
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
star_handlers_registry = StarHandlerRegistry()
|
|
90
|
+
star_handlers_registry = StarHandlerRegistry() # type: ignore
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
class EventType(enum.Enum):
|
|
@@ -123,7 +123,7 @@ class StarHandlerMetadata:
|
|
|
123
123
|
handler_module_path: str
|
|
124
124
|
"""Handler 所在的模块路径。"""
|
|
125
125
|
|
|
126
|
-
handler: Awaitable
|
|
126
|
+
handler: Callable[..., Awaitable[Any]]
|
|
127
127
|
"""Handler 的函数对象,应当是一个异步函数"""
|
|
128
128
|
|
|
129
129
|
event_filters: List[HandlerFilter]
|
|
@@ -43,7 +43,7 @@ class PluginManager:
|
|
|
43
43
|
self.updator = PluginUpdator()
|
|
44
44
|
|
|
45
45
|
self.context = context
|
|
46
|
-
self.context._star_manager = self
|
|
46
|
+
self.context._star_manager = self # type: ignore
|
|
47
47
|
|
|
48
48
|
self.config = config
|
|
49
49
|
self.plugin_store_path = get_astrbot_plugin_path()
|
|
@@ -478,9 +478,10 @@ class PluginManager:
|
|
|
478
478
|
if isinstance(func_tool, HandoffTool):
|
|
479
479
|
need_apply = []
|
|
480
480
|
sub_tools = func_tool.agent.tools
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
481
|
+
if sub_tools:
|
|
482
|
+
for sub_tool in sub_tools:
|
|
483
|
+
if isinstance(sub_tool, FunctionTool):
|
|
484
|
+
need_apply.append(sub_tool)
|
|
484
485
|
else:
|
|
485
486
|
need_apply = [func_tool]
|
|
486
487
|
|
|
@@ -686,6 +687,9 @@ class PluginManager:
|
|
|
686
687
|
)
|
|
687
688
|
|
|
688
689
|
# 从 star_registry 和 star_map 中删除
|
|
690
|
+
if plugin.module_path is None or root_dir_name is None:
|
|
691
|
+
raise Exception(f"插件 {plugin_name} 数据不完整,无法卸载。")
|
|
692
|
+
|
|
689
693
|
await self._unbind_plugin(plugin_name, plugin.module_path)
|
|
690
694
|
|
|
691
695
|
try:
|
|
@@ -800,6 +804,8 @@ class PluginManager:
|
|
|
800
804
|
|
|
801
805
|
async def turn_on_plugin(self, plugin_name: str):
|
|
802
806
|
plugin = self.context.get_registered_star(plugin_name)
|
|
807
|
+
if plugin is None:
|
|
808
|
+
raise Exception(f"插件 {plugin_name} 不存在。")
|
|
803
809
|
inactivated_plugins: list = await sp.global_get("inactivated_plugins", [])
|
|
804
810
|
inactivated_llm_tools: list = await sp.global_get("inactivated_llm_tools", [])
|
|
805
811
|
if plugin.module_path in inactivated_plugins:
|
astrbot/core/star/star_tools.py
CHANGED
|
@@ -22,7 +22,7 @@ import inspect
|
|
|
22
22
|
import os
|
|
23
23
|
import uuid
|
|
24
24
|
from pathlib import Path
|
|
25
|
-
from typing import Union, Awaitable, List, Optional, ClassVar
|
|
25
|
+
from typing import Union, Awaitable, Callable, Any, List, Optional, ClassVar
|
|
26
26
|
from astrbot.core.message.components import BaseMessageComponent
|
|
27
27
|
from astrbot.core.message.message_event_result import MessageChain
|
|
28
28
|
from astrbot.api.platform import MessageMember, AstrBotMessage, MessageType
|
|
@@ -221,7 +221,11 @@ class StarTools:
|
|
|
221
221
|
|
|
222
222
|
@classmethod
|
|
223
223
|
def register_llm_tool(
|
|
224
|
-
cls,
|
|
224
|
+
cls,
|
|
225
|
+
name: str,
|
|
226
|
+
func_args: list,
|
|
227
|
+
desc: str,
|
|
228
|
+
func_obj: Callable[..., Awaitable[Any]],
|
|
225
229
|
) -> None:
|
|
226
230
|
"""
|
|
227
231
|
为函数调用(function-calling/tools-use)添加工具
|
astrbot/core/star/updator.py
CHANGED
|
@@ -32,6 +32,9 @@ class PluginUpdator(RepoZipUpdator):
|
|
|
32
32
|
if not repo_url:
|
|
33
33
|
raise Exception(f"插件 {plugin.name} 没有指定仓库地址。")
|
|
34
34
|
|
|
35
|
+
if not plugin.root_dir_name:
|
|
36
|
+
raise Exception(f"插件 {plugin.name} 的根目录名未指定。")
|
|
37
|
+
|
|
35
38
|
plugin_path = os.path.join(self.plugin_store_path, plugin.root_dir_name)
|
|
36
39
|
|
|
37
40
|
logger.info(f"正在更新插件,路径: {plugin_path},仓库地址: {repo_url}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: AstrBot
|
|
3
|
-
Version: 4.1.
|
|
3
|
+
Version: 4.1.5
|
|
4
4
|
Summary: 易上手的多平台 LLM 聊天机器人及开发框架
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -10,9 +10,11 @@ Requires-Dist: aiohttp>=3.11.18
|
|
|
10
10
|
Requires-Dist: aiosqlite>=0.21.0
|
|
11
11
|
Requires-Dist: anthropic>=0.51.0
|
|
12
12
|
Requires-Dist: apscheduler>=3.11.0
|
|
13
|
+
Requires-Dist: audioop-lts; python_full_version >= '3.13'
|
|
13
14
|
Requires-Dist: beautifulsoup4>=4.13.4
|
|
14
15
|
Requires-Dist: certifi>=2025.4.26
|
|
15
16
|
Requires-Dist: chardet~=5.1.0
|
|
17
|
+
Requires-Dist: click>=8.2.1
|
|
16
18
|
Requires-Dist: colorlog>=6.9.0
|
|
17
19
|
Requires-Dist: cryptography>=44.0.3
|
|
18
20
|
Requires-Dist: dashscope>=1.23.2
|
|
@@ -162,7 +164,6 @@ uv run main.py
|
|
|
162
164
|
|
|
163
165
|
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
|
|
164
166
|
|
|
165
|
-
|
|
166
167
|
## ⚡ 消息平台支持情况
|
|
167
168
|
|
|
168
169
|
| 平台 | 支持性 |
|
|
@@ -179,6 +180,8 @@ uv run main.py
|
|
|
179
180
|
| Discord | ✔ |
|
|
180
181
|
| [KOOK](https://github.com/wuyan1003/astrbot_plugin_kook_adapter) | ✔ |
|
|
181
182
|
| [VoceChat](https://github.com/HikariFroya/astrbot_plugin_vocechat) | ✔ |
|
|
183
|
+
| Satori | ✔ |
|
|
184
|
+
| Misskey | ✔ |
|
|
182
185
|
|
|
183
186
|
## ⚡ 提供商支持情况
|
|
184
187
|
|
|
@@ -224,7 +227,6 @@ pip install pre-commit
|
|
|
224
227
|
pre-commit install
|
|
225
228
|
```
|
|
226
229
|
|
|
227
|
-
|
|
228
230
|
## ❤️ Special Thanks
|
|
229
231
|
|
|
230
232
|
特别感谢所有 Contributors 和插件开发者对 AstrBot 的贡献 ❤️
|
|
@@ -252,14 +254,11 @@ pre-commit install
|
|
|
252
254
|
> 如果本项目对您的生活 / 工作产生了帮助,或者您关注本项目的未来发展,请给项目 Star,这是我维护这个开源项目的动力 <3
|
|
253
255
|
|
|
254
256
|
<div align="center">
|
|
255
|
-
|
|
257
|
+
|
|
256
258
|
[](https://star-history.com/#soulter/astrbot&Date)
|
|
257
259
|
|
|
258
260
|
</div>
|
|
259
261
|
|
|
260
|
-
|
|
261
262
|
</details>
|
|
262
263
|
|
|
263
|
-
|
|
264
264
|
_私は、高性能ですから!_
|
|
265
|
-
|