feat: inject available shell commands into agent prompt

This commit is contained in:
jxxghp
2026-05-19 18:16:09 +08:00
parent 7866aee1de
commit c4eb4d9b95
2 changed files with 123 additions and 0 deletions

View File

@@ -1,5 +1,6 @@
"""提示词管理器"""
import shutil
import socket
from dataclasses import dataclass, field
from pathlib import Path
@@ -22,6 +23,82 @@ from app.utils.system import SystemUtils
SYSTEM_TASKS_FILE = "System Tasks.yaml"
SYSTEM_TASKS_SCHEMA_VERSION = 2
COMMON_SHELL_COMMANDS = (
"ssh",
"scp",
"sftp",
"rsync",
"git",
"gh",
"rg",
"fd",
"find",
"grep",
"sed",
"awk",
"jq",
"yq",
"curl",
"wget",
"tar",
"gzip",
"gunzip",
"zip",
"unzip",
"xz",
"7z",
"docker",
"docker-compose",
"kubectl",
"helm",
"sqlite3",
"psql",
"mysql",
"redis-cli",
"python",
"python3",
"pip",
"pip3",
"uv",
"node",
"npm",
"yarn",
"pnpm",
"bun",
"ffmpeg",
"ffprobe",
"mediainfo",
"rclone",
"aria2c",
"yt-dlp",
"openssl",
"base64",
"sha256sum",
"shasum",
"du",
"df",
"ps",
"top",
"lsof",
"netstat",
"ss",
"ping",
"traceroute",
"dig",
"nslookup",
"nc",
"telnet",
"crontab",
"systemctl",
"service",
"journalctl",
"launchctl",
"brew",
"apt",
"apk",
"yum",
"dnf",
)
class PromptConfigError(ValueError):
@@ -305,8 +382,30 @@ class PromptManager:
f"- 系统安装目录: {settings.ROOT_PATH}",
]
available_commands = PromptManager._get_available_shell_commands()
if available_commands:
info_lines.append("- 可用系统命令(可通过 `execute_command` 调用):")
info_lines.extend(
f" - {command}: {path}" for command, path in available_commands
)
return "\n".join(info_lines)
@staticmethod
def _get_available_shell_commands() -> list[tuple[str, str]]:
"""
探测 PATH 中已经安装的常用命令。
这里只使用 shutil.which 做无副作用查找,不实际执行命令;执行权限、
高风险操作确认和输出限制仍由 execute_command 工具负责。
"""
available_commands: list[tuple[str, str]] = []
for command in COMMON_SHELL_COMMANDS:
command_path = shutil.which(command)
if command_path:
available_commands.append((command, command_path))
return available_commands
@staticmethod
def _generate_formatting_instructions(caps: ChannelCapabilities) -> str:
"""

View File

@@ -38,6 +38,30 @@ class TestAgentPromptStyle(unittest.TestCase):
self.assertIn("当前日期", prompt)
self.assertNotIn("当前时间", prompt)
def test_base_prompt_injects_available_shell_commands(self):
"""系统信息应注入 PATH 中已安装的常用命令,帮助 Agent 选择 execute_command。"""
command_paths = {
"ssh": "/usr/bin/ssh",
"rg": "/opt/homebrew/bin/rg",
}
with patch(
"app.agent.prompt.shutil.which",
side_effect=lambda command: command_paths.get(command),
):
prompt = prompt_manager.get_agent_prompt()
self.assertIn("- 可用系统命令(可通过 `execute_command` 调用):", prompt)
self.assertIn(" - ssh: /usr/bin/ssh", prompt)
self.assertIn(" - rg: /opt/homebrew/bin/rg", prompt)
self.assertNotIn(" - git:", prompt)
def test_base_prompt_omits_shell_command_section_when_none_available(self):
"""PATH 中没有命中白名单命令时,不注入空的系统命令段落。"""
with patch("app.agent.prompt.shutil.which", return_value=None):
prompt = prompt_manager.get_agent_prompt()
self.assertNotIn("可用系统命令", prompt)
def test_runtime_config_middleware_injects_persona_only(self):
middleware = RuntimeConfigMiddleware()
updated_request = middleware.modify_request(_FakeRequest())