AstrBot 4.12.4__py3-none-any.whl → 4.13.1__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/builtin_stars/astrbot/process_llm_request.py +42 -1
- astrbot/cli/__init__.py +1 -1
- astrbot/core/agent/runners/tool_loop_agent_runner.py +91 -1
- astrbot/core/agent/tool.py +61 -20
- astrbot/core/astr_agent_tool_exec.py +2 -2
- astrbot/core/{sandbox → computer}/booters/base.py +4 -4
- astrbot/core/{sandbox → computer}/booters/boxlite.py +2 -2
- astrbot/core/computer/booters/local.py +234 -0
- astrbot/core/{sandbox → computer}/booters/shipyard.py +2 -2
- astrbot/core/computer/computer_client.py +102 -0
- astrbot/core/{sandbox → computer}/tools/__init__.py +2 -1
- astrbot/core/{sandbox → computer}/tools/fs.py +1 -1
- astrbot/core/computer/tools/python.py +94 -0
- astrbot/core/{sandbox → computer}/tools/shell.py +13 -5
- astrbot/core/config/default.py +61 -9
- astrbot/core/db/__init__.py +3 -0
- astrbot/core/db/po.py +23 -61
- astrbot/core/db/sqlite.py +19 -1
- astrbot/core/message/components.py +2 -2
- astrbot/core/persona_mgr.py +8 -0
- astrbot/core/pipeline/context_utils.py +2 -2
- astrbot/core/pipeline/preprocess_stage/stage.py +1 -1
- astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py +21 -6
- astrbot/core/pipeline/process_stage/utils.py +19 -4
- astrbot/core/pipeline/scheduler.py +1 -1
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +3 -3
- astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py +5 -7
- astrbot/core/provider/manager.py +31 -0
- astrbot/core/provider/sources/gemini_source.py +12 -9
- astrbot/core/skills/__init__.py +3 -0
- astrbot/core/skills/skill_manager.py +238 -0
- astrbot/core/star/command_management.py +1 -1
- astrbot/core/star/config.py +1 -1
- astrbot/core/star/filter/command.py +1 -1
- astrbot/core/star/filter/custom_filter.py +2 -2
- astrbot/core/star/register/star_handler.py +1 -1
- astrbot/core/utils/astrbot_path.py +6 -0
- astrbot/dashboard/routes/__init__.py +2 -0
- astrbot/dashboard/routes/config.py +236 -2
- astrbot/dashboard/routes/persona.py +7 -0
- astrbot/dashboard/routes/skills.py +148 -0
- astrbot/dashboard/routes/util.py +102 -0
- astrbot/dashboard/server.py +19 -5
- {astrbot-4.12.4.dist-info → astrbot-4.13.1.dist-info}/METADATA +2 -2
- {astrbot-4.12.4.dist-info → astrbot-4.13.1.dist-info}/RECORD +52 -47
- astrbot/core/sandbox/sandbox_client.py +0 -52
- astrbot/core/sandbox/tools/python.py +0 -74
- /astrbot/core/{sandbox → computer}/olayer/__init__.py +0 -0
- /astrbot/core/{sandbox → computer}/olayer/filesystem.py +0 -0
- /astrbot/core/{sandbox → computer}/olayer/python.py +0 -0
- /astrbot/core/{sandbox → computer}/olayer/shell.py +0 -0
- {astrbot-4.12.4.dist-info → astrbot-4.13.1.dist-info}/WHEEL +0 -0
- {astrbot-4.12.4.dist-info → astrbot-4.13.1.dist-info}/entry_points.txt +0 -0
- {astrbot-4.12.4.dist-info → astrbot-4.13.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import uuid
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from astrbot.api import logger
|
|
7
|
+
from astrbot.core.skills.skill_manager import SANDBOX_SKILLS_ROOT
|
|
8
|
+
from astrbot.core.star.context import Context
|
|
9
|
+
from astrbot.core.utils.astrbot_path import (
|
|
10
|
+
get_astrbot_skills_path,
|
|
11
|
+
get_astrbot_temp_path,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from .booters.base import ComputerBooter
|
|
15
|
+
from .booters.local import LocalBooter
|
|
16
|
+
|
|
17
|
+
session_booter: dict[str, ComputerBooter] = {}
|
|
18
|
+
local_booter: ComputerBooter | None = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def _sync_skills_to_sandbox(booter: ComputerBooter) -> None:
|
|
22
|
+
skills_root = get_astrbot_skills_path()
|
|
23
|
+
if not os.path.isdir(skills_root):
|
|
24
|
+
return
|
|
25
|
+
if not any(Path(skills_root).iterdir()):
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
temp_dir = get_astrbot_temp_path()
|
|
29
|
+
os.makedirs(temp_dir, exist_ok=True)
|
|
30
|
+
zip_base = os.path.join(temp_dir, "skills_bundle")
|
|
31
|
+
zip_path = f"{zip_base}.zip"
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
if os.path.exists(zip_path):
|
|
35
|
+
os.remove(zip_path)
|
|
36
|
+
shutil.make_archive(zip_base, "zip", skills_root)
|
|
37
|
+
remote_zip = Path(SANDBOX_SKILLS_ROOT) / "skills.zip"
|
|
38
|
+
await booter.shell.exec(f"mkdir -p {SANDBOX_SKILLS_ROOT}")
|
|
39
|
+
upload_result = await booter.upload_file(zip_path, str(remote_zip))
|
|
40
|
+
if not upload_result.get("success", False):
|
|
41
|
+
raise RuntimeError("Failed to upload skills bundle to sandbox.")
|
|
42
|
+
await booter.shell.exec(
|
|
43
|
+
f"unzip -o {remote_zip} -d {SANDBOX_SKILLS_ROOT} && rm -f {remote_zip}"
|
|
44
|
+
)
|
|
45
|
+
finally:
|
|
46
|
+
if os.path.exists(zip_path):
|
|
47
|
+
try:
|
|
48
|
+
os.remove(zip_path)
|
|
49
|
+
except Exception:
|
|
50
|
+
logger.warning(f"Failed to remove temp skills zip: {zip_path}")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def get_booter(
|
|
54
|
+
context: Context,
|
|
55
|
+
session_id: str,
|
|
56
|
+
) -> ComputerBooter:
|
|
57
|
+
config = context.get_config(umo=session_id)
|
|
58
|
+
|
|
59
|
+
sandbox_cfg = config.get("provider_settings", {}).get("sandbox", {})
|
|
60
|
+
booter_type = sandbox_cfg.get("booter", "shipyard")
|
|
61
|
+
|
|
62
|
+
if session_id in session_booter:
|
|
63
|
+
booter = session_booter[session_id]
|
|
64
|
+
if not await booter.available():
|
|
65
|
+
# rebuild
|
|
66
|
+
session_booter.pop(session_id, None)
|
|
67
|
+
if session_id not in session_booter:
|
|
68
|
+
uuid_str = uuid.uuid5(uuid.NAMESPACE_DNS, session_id).hex
|
|
69
|
+
if booter_type == "shipyard":
|
|
70
|
+
from .booters.shipyard import ShipyardBooter
|
|
71
|
+
|
|
72
|
+
ep = sandbox_cfg.get("shipyard_endpoint", "")
|
|
73
|
+
token = sandbox_cfg.get("shipyard_access_token", "")
|
|
74
|
+
ttl = sandbox_cfg.get("shipyard_ttl", 3600)
|
|
75
|
+
max_sessions = sandbox_cfg.get("shipyard_max_sessions", 10)
|
|
76
|
+
|
|
77
|
+
client = ShipyardBooter(
|
|
78
|
+
endpoint_url=ep, access_token=token, ttl=ttl, session_num=max_sessions
|
|
79
|
+
)
|
|
80
|
+
elif booter_type == "boxlite":
|
|
81
|
+
from .booters.boxlite import BoxliteBooter
|
|
82
|
+
|
|
83
|
+
client = BoxliteBooter()
|
|
84
|
+
else:
|
|
85
|
+
raise ValueError(f"Unknown booter type: {booter_type}")
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
await client.boot(uuid_str)
|
|
89
|
+
await _sync_skills_to_sandbox(client)
|
|
90
|
+
except Exception as e:
|
|
91
|
+
logger.error(f"Error booting sandbox for session {session_id}: {e}")
|
|
92
|
+
raise e
|
|
93
|
+
|
|
94
|
+
session_booter[session_id] = client
|
|
95
|
+
return session_booter[session_id]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def get_local_booter() -> ComputerBooter:
|
|
99
|
+
global local_booter
|
|
100
|
+
if local_booter is None:
|
|
101
|
+
local_booter = LocalBooter()
|
|
102
|
+
return local_booter
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
from .fs import FileDownloadTool, FileUploadTool
|
|
2
|
-
from .python import PythonTool
|
|
2
|
+
from .python import LocalPythonTool, PythonTool
|
|
3
3
|
from .shell import ExecuteShellTool
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
6
|
"FileUploadTool",
|
|
7
7
|
"PythonTool",
|
|
8
|
+
"LocalPythonTool",
|
|
8
9
|
"ExecuteShellTool",
|
|
9
10
|
"FileDownloadTool",
|
|
10
11
|
]
|
|
@@ -9,7 +9,7 @@ from astrbot.core.astr_agent_context import AstrAgentContext
|
|
|
9
9
|
from astrbot.core.message.components import File
|
|
10
10
|
from astrbot.core.utils.astrbot_path import get_astrbot_temp_path
|
|
11
11
|
|
|
12
|
-
from ..
|
|
12
|
+
from ..computer_client import get_booter
|
|
13
13
|
|
|
14
14
|
# @dataclass
|
|
15
15
|
# class CreateFileTool(FunctionTool):
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
import mcp
|
|
4
|
+
|
|
5
|
+
from astrbot.api import FunctionTool
|
|
6
|
+
from astrbot.core.agent.run_context import ContextWrapper
|
|
7
|
+
from astrbot.core.agent.tool import ToolExecResult
|
|
8
|
+
from astrbot.core.astr_agent_context import AstrAgentContext
|
|
9
|
+
from astrbot.core.computer.computer_client import get_booter, get_local_booter
|
|
10
|
+
|
|
11
|
+
param_schema = {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"properties": {
|
|
14
|
+
"code": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "The Python code to execute.",
|
|
17
|
+
},
|
|
18
|
+
"silent": {
|
|
19
|
+
"type": "boolean",
|
|
20
|
+
"description": "Whether to suppress the output of the code execution.",
|
|
21
|
+
"default": False,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
"required": ["code"],
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def handle_result(result: dict) -> ToolExecResult:
|
|
29
|
+
data = result.get("data", {})
|
|
30
|
+
output = data.get("output", {})
|
|
31
|
+
error = data.get("error", "")
|
|
32
|
+
images: list[dict] = output.get("images", [])
|
|
33
|
+
text: str = output.get("text", "")
|
|
34
|
+
|
|
35
|
+
resp = mcp.types.CallToolResult(content=[])
|
|
36
|
+
|
|
37
|
+
if error:
|
|
38
|
+
resp.content.append(mcp.types.TextContent(type="text", text=f"error: {error}"))
|
|
39
|
+
|
|
40
|
+
if images:
|
|
41
|
+
for img in images:
|
|
42
|
+
resp.content.append(
|
|
43
|
+
mcp.types.ImageContent(
|
|
44
|
+
type="image", data=img["image/png"], mimeType="image/png"
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
if text:
|
|
48
|
+
resp.content.append(mcp.types.TextContent(type="text", text=text))
|
|
49
|
+
|
|
50
|
+
if not resp.content:
|
|
51
|
+
resp.content.append(mcp.types.TextContent(type="text", text="No output."))
|
|
52
|
+
|
|
53
|
+
return resp
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class PythonTool(FunctionTool):
|
|
58
|
+
name: str = "astrbot_execute_ipython"
|
|
59
|
+
description: str = "Run codes in an IPython shell."
|
|
60
|
+
parameters: dict = field(default_factory=lambda: param_schema)
|
|
61
|
+
|
|
62
|
+
async def call(
|
|
63
|
+
self, context: ContextWrapper[AstrAgentContext], code: str, silent: bool = False
|
|
64
|
+
) -> ToolExecResult:
|
|
65
|
+
sb = await get_booter(
|
|
66
|
+
context.context.context,
|
|
67
|
+
context.context.event.unified_msg_origin,
|
|
68
|
+
)
|
|
69
|
+
try:
|
|
70
|
+
result = await sb.python.exec(code, silent=silent)
|
|
71
|
+
return handle_result(result)
|
|
72
|
+
except Exception as e:
|
|
73
|
+
return f"Error executing code: {str(e)}"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
class LocalPythonTool(FunctionTool):
|
|
78
|
+
name: str = "astrbot_execute_python"
|
|
79
|
+
description: str = "Execute codes in a Python environment."
|
|
80
|
+
|
|
81
|
+
parameters: dict = field(default_factory=lambda: param_schema)
|
|
82
|
+
|
|
83
|
+
async def call(
|
|
84
|
+
self, context: ContextWrapper[AstrAgentContext], code: str, silent: bool = False
|
|
85
|
+
) -> ToolExecResult:
|
|
86
|
+
if context.context.event.role != "admin":
|
|
87
|
+
return "error: Permission denied. Local Python execution is only allowed for admin users. Tell user to set admins in AstrBot WebUI."
|
|
88
|
+
|
|
89
|
+
sb = get_local_booter()
|
|
90
|
+
try:
|
|
91
|
+
result = await sb.python.exec(code, silent=silent)
|
|
92
|
+
return handle_result(result)
|
|
93
|
+
except Exception as e:
|
|
94
|
+
return f"Error executing code: {str(e)}"
|
|
@@ -6,7 +6,7 @@ from astrbot.core.agent.run_context import ContextWrapper
|
|
|
6
6
|
from astrbot.core.agent.tool import ToolExecResult
|
|
7
7
|
from astrbot.core.astr_agent_context import AstrAgentContext
|
|
8
8
|
|
|
9
|
-
from ..
|
|
9
|
+
from ..computer_client import get_booter, get_local_booter
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@dataclass
|
|
@@ -37,6 +37,8 @@ class ExecuteShellTool(FunctionTool):
|
|
|
37
37
|
}
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
+
is_local: bool = False
|
|
41
|
+
|
|
40
42
|
async def call(
|
|
41
43
|
self,
|
|
42
44
|
context: ContextWrapper[AstrAgentContext],
|
|
@@ -44,10 +46,16 @@ class ExecuteShellTool(FunctionTool):
|
|
|
44
46
|
background: bool = False,
|
|
45
47
|
env: dict = {},
|
|
46
48
|
) -> ToolExecResult:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
if context.context.event.role != "admin":
|
|
50
|
+
return "error: Permission denied. Shell execution is only allowed for admin users. Tell user to Set admins in AstrBot WebUI."
|
|
51
|
+
|
|
52
|
+
if self.is_local:
|
|
53
|
+
sb = get_local_booter()
|
|
54
|
+
else:
|
|
55
|
+
sb = await get_booter(
|
|
56
|
+
context.context.context,
|
|
57
|
+
context.context.event.unified_msg_origin,
|
|
58
|
+
)
|
|
51
59
|
try:
|
|
52
60
|
result = await sb.shell.exec(command, background=background, env=env)
|
|
53
61
|
return json.dumps(result)
|
astrbot/core/config/default.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import Any, TypedDict
|
|
|
5
5
|
|
|
6
6
|
from astrbot.core.utils.astrbot_path import get_astrbot_data_path
|
|
7
7
|
|
|
8
|
-
VERSION = "4.
|
|
8
|
+
VERSION = "4.13.1"
|
|
9
9
|
DB_PATH = os.path.join(get_astrbot_data_path(), "data_v4.db")
|
|
10
10
|
|
|
11
11
|
WEBHOOK_SUPPORTED_PLATFORMS = [
|
|
@@ -106,6 +106,7 @@ DEFAULT_CONFIG = {
|
|
|
106
106
|
"reachability_check": False,
|
|
107
107
|
"max_agent_step": 30,
|
|
108
108
|
"tool_call_timeout": 60,
|
|
109
|
+
"tool_schema_mode": "full",
|
|
109
110
|
"llm_safety_mode": True,
|
|
110
111
|
"safety_mode_strategy": "system_prompt", # TODO: llm judge
|
|
111
112
|
"file_extract": {
|
|
@@ -121,6 +122,7 @@ DEFAULT_CONFIG = {
|
|
|
121
122
|
"shipyard_ttl": 3600,
|
|
122
123
|
"shipyard_max_sessions": 10,
|
|
123
124
|
},
|
|
125
|
+
"skills": {"runtime": "sandbox"},
|
|
124
126
|
},
|
|
125
127
|
"provider_stt_settings": {
|
|
126
128
|
"enable": False,
|
|
@@ -166,6 +168,7 @@ DEFAULT_CONFIG = {
|
|
|
166
168
|
"jwt_secret": "",
|
|
167
169
|
"host": "0.0.0.0",
|
|
168
170
|
"port": 6185,
|
|
171
|
+
"disable_access_log": True,
|
|
169
172
|
},
|
|
170
173
|
"platform": [],
|
|
171
174
|
"platform_specific": {
|
|
@@ -773,27 +776,21 @@ CONFIG_METADATA_2 = {
|
|
|
773
776
|
"interval_method": {
|
|
774
777
|
"type": "string",
|
|
775
778
|
"options": ["random", "log"],
|
|
776
|
-
"hint": "分段回复的间隔时间计算方法。random 为随机时间,log 为根据消息长度计算,$y=log_<log_base>(x)$,x为字数,y的单位为秒。",
|
|
777
779
|
},
|
|
778
780
|
"interval": {
|
|
779
781
|
"type": "string",
|
|
780
|
-
"hint": "`random` 方法用。每一段回复的间隔时间,格式为 `最小时间,最大时间`。如 `0.75,2.5`",
|
|
781
782
|
},
|
|
782
783
|
"log_base": {
|
|
783
784
|
"type": "float",
|
|
784
|
-
"hint": "`log` 方法用。对数函数的底数。默认为 2.6",
|
|
785
785
|
},
|
|
786
786
|
"words_count_threshold": {
|
|
787
787
|
"type": "int",
|
|
788
|
-
"hint": "分段回复的字数上限。只有字数小于此值的消息才会被分段,超过此值的长消息将直接发送(不分段)。默认为 150",
|
|
789
788
|
},
|
|
790
789
|
"regex": {
|
|
791
790
|
"type": "string",
|
|
792
|
-
"hint": "用于分隔一段消息。默认情况下会根据句号、问号等标点符号分隔。re.findall(r'<regex>', text)",
|
|
793
791
|
},
|
|
794
792
|
"content_cleanup_rule": {
|
|
795
793
|
"type": "string",
|
|
796
|
-
"hint": "移除分段后的内容中的指定的内容。支持正则表达式。如填写 `[。?!]` 将移除所有的句号、问号、感叹号。re.sub(r'<regex>', '', text)",
|
|
797
794
|
},
|
|
798
795
|
},
|
|
799
796
|
},
|
|
@@ -2187,6 +2184,9 @@ CONFIG_METADATA_2 = {
|
|
|
2187
2184
|
"tool_call_timeout": {
|
|
2188
2185
|
"type": "int",
|
|
2189
2186
|
},
|
|
2187
|
+
"tool_schema_mode": {
|
|
2188
|
+
"type": "string",
|
|
2189
|
+
},
|
|
2190
2190
|
"file_extract": {
|
|
2191
2191
|
"type": "object",
|
|
2192
2192
|
"items": {
|
|
@@ -2201,6 +2201,17 @@ CONFIG_METADATA_2 = {
|
|
|
2201
2201
|
},
|
|
2202
2202
|
},
|
|
2203
2203
|
},
|
|
2204
|
+
"skills": {
|
|
2205
|
+
"type": "object",
|
|
2206
|
+
"items": {
|
|
2207
|
+
"enable": {
|
|
2208
|
+
"type": "bool",
|
|
2209
|
+
},
|
|
2210
|
+
"runtime": {
|
|
2211
|
+
"type": "string",
|
|
2212
|
+
},
|
|
2213
|
+
},
|
|
2214
|
+
},
|
|
2204
2215
|
},
|
|
2205
2216
|
},
|
|
2206
2217
|
"provider_stt_settings": {
|
|
@@ -2578,6 +2589,7 @@ CONFIG_METADATA_3 = {
|
|
|
2578
2589
|
# },
|
|
2579
2590
|
"sandbox": {
|
|
2580
2591
|
"description": "Agent 沙箱环境",
|
|
2592
|
+
"hint": "",
|
|
2581
2593
|
"type": "object",
|
|
2582
2594
|
"items": {
|
|
2583
2595
|
"provider_settings.sandbox.enable": {
|
|
@@ -2589,6 +2601,7 @@ CONFIG_METADATA_3 = {
|
|
|
2589
2601
|
"description": "沙箱环境驱动器",
|
|
2590
2602
|
"type": "string",
|
|
2591
2603
|
"options": ["shipyard"],
|
|
2604
|
+
"labels": ["Shipyard"],
|
|
2592
2605
|
"condition": {
|
|
2593
2606
|
"provider_settings.sandbox.enable": True,
|
|
2594
2607
|
},
|
|
@@ -2631,6 +2644,27 @@ CONFIG_METADATA_3 = {
|
|
|
2631
2644
|
},
|
|
2632
2645
|
},
|
|
2633
2646
|
},
|
|
2647
|
+
"condition": {
|
|
2648
|
+
"provider_settings.agent_runner_type": "local",
|
|
2649
|
+
"provider_settings.enable": True,
|
|
2650
|
+
},
|
|
2651
|
+
},
|
|
2652
|
+
"skills": {
|
|
2653
|
+
"description": "Skills",
|
|
2654
|
+
"type": "object",
|
|
2655
|
+
"items": {
|
|
2656
|
+
"provider_settings.skills.runtime": {
|
|
2657
|
+
"description": "Skill Runtime",
|
|
2658
|
+
"type": "string",
|
|
2659
|
+
"options": ["local", "sandbox"],
|
|
2660
|
+
"labels": ["本地", "沙箱"],
|
|
2661
|
+
"hint": "选择 Skills 运行环境。使用沙箱时需先启用沙箱环境。",
|
|
2662
|
+
},
|
|
2663
|
+
},
|
|
2664
|
+
"condition": {
|
|
2665
|
+
"provider_settings.agent_runner_type": "local",
|
|
2666
|
+
"provider_settings.enable": True,
|
|
2667
|
+
},
|
|
2634
2668
|
},
|
|
2635
2669
|
"truncate_and_compress": {
|
|
2636
2670
|
"description": "上下文管理策略",
|
|
@@ -2691,6 +2725,10 @@ CONFIG_METADATA_3 = {
|
|
|
2691
2725
|
},
|
|
2692
2726
|
},
|
|
2693
2727
|
},
|
|
2728
|
+
"condition": {
|
|
2729
|
+
"provider_settings.agent_runner_type": "local",
|
|
2730
|
+
"provider_settings.enable": True,
|
|
2731
|
+
},
|
|
2694
2732
|
},
|
|
2695
2733
|
"others": {
|
|
2696
2734
|
"description": "其他配置",
|
|
@@ -2778,6 +2816,16 @@ CONFIG_METADATA_3 = {
|
|
|
2778
2816
|
"provider_settings.agent_runner_type": "local",
|
|
2779
2817
|
},
|
|
2780
2818
|
},
|
|
2819
|
+
"provider_settings.tool_schema_mode": {
|
|
2820
|
+
"description": "工具调用模式",
|
|
2821
|
+
"type": "string",
|
|
2822
|
+
"options": ["skills_like", "full"],
|
|
2823
|
+
"labels": ["Skills-like(两阶段)", "Full(完整参数)"],
|
|
2824
|
+
"hint": "skills-like 先下发工具名称与描述,再下发参数;full 一次性下发完整参数。",
|
|
2825
|
+
"condition": {
|
|
2826
|
+
"provider_settings.agent_runner_type": "local",
|
|
2827
|
+
},
|
|
2828
|
+
},
|
|
2781
2829
|
"provider_settings.wake_prefix": {
|
|
2782
2830
|
"description": "LLM 聊天额外唤醒前缀 ",
|
|
2783
2831
|
"type": "string",
|
|
@@ -3045,7 +3093,8 @@ CONFIG_METADATA_3 = {
|
|
|
3045
3093
|
"type": "bool",
|
|
3046
3094
|
},
|
|
3047
3095
|
"platform_settings.segmented_reply.interval_method": {
|
|
3048
|
-
"description": "
|
|
3096
|
+
"description": "间隔方法。",
|
|
3097
|
+
"hint": "random 为随机时间,log 为根据消息长度计算,$y=log_<log_base>(x)$,x为字数,y的单位为秒。",
|
|
3049
3098
|
"type": "string",
|
|
3050
3099
|
"options": ["random", "log"],
|
|
3051
3100
|
},
|
|
@@ -3060,13 +3109,14 @@ CONFIG_METADATA_3 = {
|
|
|
3060
3109
|
"platform_settings.segmented_reply.log_base": {
|
|
3061
3110
|
"description": "对数底数",
|
|
3062
3111
|
"type": "float",
|
|
3063
|
-
"hint": "对数间隔的底数,默认为 2.
|
|
3112
|
+
"hint": "对数间隔的底数,默认为 2.6。取值范围为 1.0-10.0。",
|
|
3064
3113
|
"condition": {
|
|
3065
3114
|
"platform_settings.segmented_reply.interval_method": "log",
|
|
3066
3115
|
},
|
|
3067
3116
|
},
|
|
3068
3117
|
"platform_settings.segmented_reply.words_count_threshold": {
|
|
3069
3118
|
"description": "分段回复字数阈值",
|
|
3119
|
+
"hint": "分段回复的字数上限。只有字数小于此值的消息才会被分段,超过此值的长消息将直接发送(不分段)。默认为 150",
|
|
3070
3120
|
"type": "int",
|
|
3071
3121
|
},
|
|
3072
3122
|
"platform_settings.segmented_reply.split_mode": {
|
|
@@ -3077,6 +3127,7 @@ CONFIG_METADATA_3 = {
|
|
|
3077
3127
|
},
|
|
3078
3128
|
"platform_settings.segmented_reply.regex": {
|
|
3079
3129
|
"description": "分段正则表达式",
|
|
3130
|
+
"hint": "用于分隔一段消息。默认情况下会根据句号、问号等标点符号分隔。如填写 `[。?!]` 将移除所有的句号、问号、感叹号。re.findall(r'<regex>', text)",
|
|
3080
3131
|
"type": "string",
|
|
3081
3132
|
"condition": {
|
|
3082
3133
|
"platform_settings.segmented_reply.split_mode": "regex",
|
|
@@ -3246,6 +3297,7 @@ DEFAULT_VALUE_MAP = {
|
|
|
3246
3297
|
"string": "",
|
|
3247
3298
|
"text": "",
|
|
3248
3299
|
"list": [],
|
|
3300
|
+
"file": [],
|
|
3249
3301
|
"object": {},
|
|
3250
3302
|
"template_list": [],
|
|
3251
3303
|
}
|
astrbot/core/db/__init__.py
CHANGED
|
@@ -254,6 +254,7 @@ class BaseDatabase(abc.ABC):
|
|
|
254
254
|
system_prompt: str,
|
|
255
255
|
begin_dialogs: list[str] | None = None,
|
|
256
256
|
tools: list[str] | None = None,
|
|
257
|
+
skills: list[str] | None = None,
|
|
257
258
|
folder_id: str | None = None,
|
|
258
259
|
sort_order: int = 0,
|
|
259
260
|
) -> Persona:
|
|
@@ -264,6 +265,7 @@ class BaseDatabase(abc.ABC):
|
|
|
264
265
|
system_prompt: System prompt for the persona
|
|
265
266
|
begin_dialogs: Optional list of initial dialog strings
|
|
266
267
|
tools: Optional list of tool names (None means all tools, [] means no tools)
|
|
268
|
+
skills: Optional list of skill names (None means all skills, [] means no skills)
|
|
267
269
|
folder_id: Optional folder ID to place the persona in (None means root)
|
|
268
270
|
sort_order: Sort order within the folder (default 0)
|
|
269
271
|
"""
|
|
@@ -286,6 +288,7 @@ class BaseDatabase(abc.ABC):
|
|
|
286
288
|
system_prompt: str | None = None,
|
|
287
289
|
begin_dialogs: list[str] | None = None,
|
|
288
290
|
tools: list[str] | None = None,
|
|
291
|
+
skills: list[str] | None = None,
|
|
289
292
|
) -> Persona | None:
|
|
290
293
|
"""Update a persona's system prompt or begin dialogs."""
|
|
291
294
|
...
|