Skip to content

Commit 78c7a50

Browse files
合并 master 到 feat/plugin-manager-frontend
2 parents f7a088a + c64ffc1 commit 78c7a50

File tree

143 files changed

+14450
-1985
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+14450
-1985
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,7 @@ venv/*
5151
pytest.ini
5252
AGENTS.md
5353
IFLOW.md
54+
55+
# genie_tts data
56+
CharacterModels/
57+
GenieData/

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ AstrBot 是一个开源的一站式 Agent 聊天机器人平台,可接入主
4141
## 主要功能
4242

4343
1. 💯 免费 & 开源。
44-
1. ✨ AI 大模型对话,多模态,Agent,MCP,知识库,人格设定。
44+
1. ✨ AI 大模型对话,多模态,Agent,MCP,知识库,人格设定,自动压缩对话
4545
2. 🤖 支持接入 Dify、阿里云百炼、Coze 等智能体平台。
4646
2. 🌐 多平台,支持 QQ、企业微信、飞书、钉钉、微信公众号、Telegram、Slack 以及[更多](#支持的消息平台)
4747
3. 📦 插件扩展,已有近 800 个插件可一键安装。
48-
5. 💻 WebUI 支持。
49-
6. 🌐 国际化(i18n)支持。
48+
5. 🛡️ [Agent Sandbox](https://docs.astrbot.app/use/astrbot-agent-sandbox.html) 隔离化环境,安全地执行任何代码、调用 Shell、会话级资源复用。
49+
6. 💻 WebUI 支持。
50+
7. 🌈 Web ChatUI 支持,ChatUI 内置代理沙盒、网页搜索等。
51+
8. 🌐 国际化(i18n)支持。
5052

5153
## 快速开始
5254

astrbot/api/event/filter/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
)
2121
from astrbot.core.star.register import register_on_llm_request as on_llm_request
2222
from astrbot.core.star.register import register_on_llm_response as on_llm_response
23+
from astrbot.core.star.register import (
24+
register_on_llm_tool_respond as on_llm_tool_respond,
25+
)
2326
from astrbot.core.star.register import register_on_platform_loaded as on_platform_loaded
27+
from astrbot.core.star.register import register_on_using_llm_tool as on_using_llm_tool
2428
from astrbot.core.star.register import (
2529
register_on_waiting_llm_request as on_waiting_llm_request,
2630
)
@@ -53,4 +57,6 @@
5357
"permission_type",
5458
"platform_adapter_type",
5559
"regex",
60+
"on_using_llm_tool",
61+
"on_llm_tool_respond",
5662
]

astrbot/builtin_stars/astrbot/process_llm_request.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
from astrbot.api.message_components import Image, Reply
99
from astrbot.api.provider import Provider, ProviderRequest
1010
from astrbot.core.agent.message import TextPart
11+
from astrbot.core.pipeline.process_stage.utils import (
12+
CHATUI_SPECIAL_DEFAULT_PERSONA_PROMPT,
13+
)
1114
from astrbot.core.provider.func_tool_manager import ToolSet
1215

1316

@@ -22,7 +25,9 @@ def __init__(self, context: star.Context):
2225
else:
2326
logger.info(f"Timezone set to: {self.timezone}")
2427

25-
async def _ensure_persona(self, req: ProviderRequest, cfg: dict, umo: str):
28+
async def _ensure_persona(
29+
self, req: ProviderRequest, cfg: dict, umo: str, platform_type: str
30+
):
2631
"""确保用户人格已加载"""
2732
if not req.conversation:
2833
return
@@ -54,6 +59,12 @@ async def _ensure_persona(self, req: ProviderRequest, cfg: dict, umo: str):
5459
if default_persona:
5560
persona_id = default_persona.get("name") or persona_id
5661

62+
# ChatUI special default persona
63+
if platform_type == "webchat":
64+
# non-existent persona_id to let following codes not working
65+
persona_id = "_chatui_default_"
66+
req.system_prompt += CHATUI_SPECIAL_DEFAULT_PERSONA_PROMPT
67+
5768
persona = next(
5869
builtins.filter(
5970
lambda persona: persona["name"] == persona_id,
@@ -193,7 +204,10 @@ async def process_llm_request(self, event: AstrMessageEvent, req: ProviderReques
193204
img_cap_prov_id: str = cfg.get("default_image_caption_provider_id") or ""
194205
if req.conversation:
195206
# inject persona for this request
196-
await self._ensure_persona(req, cfg, event.unified_msg_origin)
207+
platform_type = event.get_platform_name()
208+
await self._ensure_persona(
209+
req, cfg, event.unified_msg_origin, platform_type
210+
)
197211

198212
# image caption
199213
if img_cap_prov_id and req.image_urls:

astrbot/builtin_stars/builtin_commands/commands/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from .setunset import SetUnsetCommands
1212
from .sid import SIDCommand
1313
from .t2i import T2ICommand
14-
from .tool import ToolCommands
1514
from .tts import TTSCommand
1615

1716
__all__ = [
@@ -27,5 +26,4 @@
2726
"SetUnsetCommands",
2827
"T2ICommand",
2928
"TTSCommand",
30-
"ToolCommands",
3129
]

astrbot/builtin_stars/builtin_commands/commands/persona.py

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,55 @@
11
import builtins
2+
from typing import TYPE_CHECKING
23

34
from astrbot.api import sp, star
45
from astrbot.api.event import AstrMessageEvent, MessageEventResult
56

7+
if TYPE_CHECKING:
8+
from astrbot.core.db.po import Persona
9+
610

711
class PersonaCommands:
812
def __init__(self, context: star.Context):
913
self.context = context
1014

15+
def _build_tree_output(
16+
self,
17+
folder_tree: list[dict],
18+
all_personas: list["Persona"],
19+
depth: int = 0,
20+
) -> list[str]:
21+
"""递归构建树状输出,使用短线条表示层级"""
22+
lines: list[str] = []
23+
# 使用短线条作为缩进前缀,每层只用 "│" 加一个空格
24+
prefix = "│ " * depth
25+
26+
for folder in folder_tree:
27+
# 输出文件夹
28+
lines.append(f"{prefix}├ 📁 {folder['name']}/")
29+
30+
# 获取该文件夹下的人格
31+
folder_personas = [
32+
p for p in all_personas if p.folder_id == folder["folder_id"]
33+
]
34+
child_prefix = "│ " * (depth + 1)
35+
36+
# 输出该文件夹下的人格
37+
for persona in folder_personas:
38+
lines.append(f"{child_prefix}├ 👤 {persona.persona_id}")
39+
40+
# 递归处理子文件夹
41+
children = folder.get("children", [])
42+
if children:
43+
lines.extend(
44+
self._build_tree_output(
45+
children,
46+
all_personas,
47+
depth + 1,
48+
)
49+
)
50+
51+
return lines
52+
1153
async def persona(self, message: AstrMessageEvent):
1254
l = message.message_str.split(" ") # noqa: E741
1355
umo = message.unified_msg_origin
@@ -69,12 +111,32 @@ async def persona(self, message: AstrMessageEvent):
69111
.use_t2i(False),
70112
)
71113
elif l[1] == "list":
72-
parts = ["人格列表:\n"]
73-
for persona in self.context.provider_manager.personas:
74-
parts.append(f"- {persona['name']}\n")
75-
parts.append("\n\n*输入 `/persona view 人格名` 查看人格详细信息")
76-
msg = "".join(parts)
77-
message.set_result(MessageEventResult().message(msg))
114+
# 获取文件夹树和所有人格
115+
folder_tree = await self.context.persona_manager.get_folder_tree()
116+
all_personas = self.context.persona_manager.personas
117+
118+
lines = ["📂 人格列表:\n"]
119+
120+
# 构建树状输出
121+
tree_lines = self._build_tree_output(folder_tree, all_personas)
122+
lines.extend(tree_lines)
123+
124+
# 输出根目录下的人格(没有文件夹的)
125+
root_personas = [p for p in all_personas if p.folder_id is None]
126+
if root_personas:
127+
if tree_lines: # 如果有文件夹内容,加个空行
128+
lines.append("")
129+
for persona in root_personas:
130+
lines.append(f"👤 {persona.persona_id}")
131+
132+
# 统计信息
133+
total_count = len(all_personas)
134+
lines.append(f"\n{total_count} 个人格")
135+
lines.append("\n*使用 `/persona <人格名>` 设置人格")
136+
lines.append("*使用 `/persona view <人格名>` 查看详细信息")
137+
138+
msg = "\n".join(lines)
139+
message.set_result(MessageEventResult().message(msg).use_t2i(False))
78140
elif l[1] == "view":
79141
if len(l) == 2:
80142
message.set_result(MessageEventResult().message("请输入人格情景名"))

astrbot/builtin_stars/builtin_commands/commands/tool.py

Lines changed: 0 additions & 31 deletions
This file was deleted.

astrbot/builtin_stars/builtin_commands/main.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
SetUnsetCommands,
1414
SIDCommand,
1515
T2ICommand,
16-
ToolCommands,
1716
TTSCommand,
1817
)
1918

@@ -24,7 +23,6 @@ def __init__(self, context: star.Context) -> None:
2423

2524
self.help_c = HelpCommand(self.context)
2625
self.llm_c = LLMCommands(self.context)
27-
self.tool_c = ToolCommands(self.context)
2826
self.plugin_c = PluginCommands(self.context)
2927
self.admin_c = AdminCommands(self.context)
3028
self.conversation_c = ConversationCommands(self.context)
@@ -47,30 +45,6 @@ async def llm(self, event: AstrMessageEvent):
4745
"""开启/关闭 LLM"""
4846
await self.llm_c.llm(event)
4947

50-
@filter.command_group("tool")
51-
def tool(self):
52-
"""函数工具管理"""
53-
54-
@tool.command("ls")
55-
async def tool_ls(self, event: AstrMessageEvent):
56-
"""查看函数工具列表"""
57-
await self.tool_c.tool_ls(event)
58-
59-
@tool.command("on")
60-
async def tool_on(self, event: AstrMessageEvent, tool_name: str):
61-
"""启用一个函数工具"""
62-
await self.tool_c.tool_on(event, tool_name)
63-
64-
@tool.command("off")
65-
async def tool_off(self, event: AstrMessageEvent, tool_name: str):
66-
"""停用一个函数工具"""
67-
await self.tool_c.tool_off(event, tool_name)
68-
69-
@tool.command("off_all")
70-
async def tool_all_off(self, event: AstrMessageEvent):
71-
"""停用所有函数工具"""
72-
await self.tool_c.tool_all_off(event)
73-
7448
@filter.command_group("plugin")
7549
def plugin(self):
7650
"""插件管理"""

0 commit comments

Comments
 (0)