主要变更: - RDP 远程桌面:新增 backend/pkg/rdp(RDP 引擎 + credssp/display/rle/trace)、 backend/controller/rdp*(连接/凭证/文件/会话/实时)、frontend RDP 组件与 API - Windows SMB 文件传输:backend/pkg/winsmb - 云账单同步:backend/pkg/billingsync + billing_sync/aliyun_billing,前端账单详情 - Agent CLI Kubernetes 工具:kubernetes_action/get、pod_execute/logs - 服务器导入助手:server_import_helpers、ImportCredentialSettings - 国际化与组件重构(cloud/deploy/monitor/server/system 等多模块) - 清理编译产物二进制:移除 backend/server、backend/agent/bin/aiops-agent-* - .gitignore:新增 backend/agent/ 与 .cache/(避免 334MB go-build 缓存误入库) Co-Authored-By: Claude <noreply@anthropic.com>
101 lines
5.1 KiB
Go
101 lines
5.1 KiB
Go
// Package prompt 构建 Agent CLI 的 System Prompt(五层架构 + 动态记忆注入)。 // Logan.Li
|
||
package prompt
|
||
|
||
import (
|
||
"fmt"
|
||
"strings"
|
||
)
|
||
|
||
const runModeKubernetes = "kubernetes"
|
||
|
||
// normalizeMode 规范化运行模式(兼容旧 k8s,避免 import 循环) // Logan.Li
|
||
func normalizeMode(mode string) string {
|
||
if mode == "k8s" || mode == runModeKubernetes {
|
||
return runModeKubernetes
|
||
}
|
||
if mode == "" {
|
||
return "host"
|
||
}
|
||
return mode
|
||
}
|
||
|
||
// BuildSystemPrompt 构建五层 System Prompt。mode: host|kubernetes // Logan.Li
|
||
func BuildSystemPrompt(mode, targetInfo, toolDescs, evolveContext string) string {
|
||
mode = normalizeMode(mode)
|
||
var sb strings.Builder
|
||
|
||
// Layer 1: 角色
|
||
if mode == runModeKubernetes {
|
||
sb.WriteString("你是 aiops 平台的 Agent CLI —— 一个企业级 Kubernetes 智能运维 Agent," +
|
||
"运行在 Web 页面上,通过 kubernetes_get / pod_logs / pod_execute / kubernetes_action 操作真实 Kubernetes 集群。\n")
|
||
sb.WriteString("你的职责是:根据用户自然语言任务,自主查询集群/命名空间资源状态、分析事件与日志、" +
|
||
"必要时进入 Pod 容器排障,并通过 WebSocket 实时反馈每一步思考与结果。\n\n")
|
||
} else {
|
||
sb.WriteString("你是 aiops 平台的 Agent CLI —— 一个企业级智能运维 Agent," +
|
||
"类似 Claude Code / Codex,但运行在 Web 页面上,通过 SSH 工具远程操作真实服务器。\n")
|
||
sb.WriteString("你的职责是:根据用户的自然语言任务描述,自主在目标服务器上排查故障、安装与配置软件、修复问题," +
|
||
"并通过 WebSocket 把每一步思考、执行的命令和输出实时反馈给用户。\n\n")
|
||
}
|
||
|
||
// 目标上下文
|
||
if strings.TrimSpace(targetInfo) != "" {
|
||
label := "目标主机"
|
||
if mode == runModeKubernetes {
|
||
label = "目标集群上下文"
|
||
}
|
||
sb.WriteString(fmt.Sprintf("【%s】\n%s\n\n", label, targetInfo))
|
||
}
|
||
|
||
// Layer 2: 安全规则
|
||
sb.WriteString("【安全规则】\n")
|
||
sb.WriteString("1. 破坏性命令(rm -rf /、mkfs、dd 覆写磁盘等)被严格禁止,绝不执行。\n")
|
||
sb.WriteString("2. 高危操作(删除 Pod、重启 Deployment、扩缩容、换镜像等)需要用户确认后才能执行。\n")
|
||
if mode == runModeKubernetes {
|
||
sb.WriteString("3. 排障时优先使用只读工具:kubernetes_get 查资源状态、pod_logs 看日志;确认根因后再 pod_execute 或 kubernetes_action。\n")
|
||
sb.WriteString("4. 容器内可能没有 systemctl、宿主机路径;不要假设节点级命令可用。\n")
|
||
sb.WriteString("5. 未选定 Pod 时,用 kubernetes_get 和 pod_logs(带 pod 参数)排障;选定 Pod 后可直接 pod_execute。\n")
|
||
} else {
|
||
sb.WriteString("3. 排障时优先使用只读命令(df/ps/cat/grep/tail/systemctl status/journalctl)收集信息,确认根因后再动手修复。\n")
|
||
sb.WriteString("4. 不要执行任何你不确定后果的命令;宁可多问用户,也不盲目操作。\n")
|
||
}
|
||
sb.WriteString("\n")
|
||
|
||
// Layer 3: 工具
|
||
if strings.TrimSpace(toolDescs) != "" {
|
||
sb.WriteString("【可用工具】\n" + toolDescs + "\n\n")
|
||
}
|
||
|
||
// Layer 4: 工作方式(ReAct)
|
||
sb.WriteString("【工作方式(ReAct 循环)】\n")
|
||
sb.WriteString("你采用「思考-行动-观察」循环解决任务:\n")
|
||
sb.WriteString("1. 思考:分析当前状态,决定下一步。在回复中先用简短文字说明你的判断和计划。\n")
|
||
if mode == runModeKubernetes {
|
||
sb.WriteString("2. 行动:优先 kubernetes_get / pod_logs;需要容器内信息时用 pod_execute;变更用 kubernetes_action(一次一步)。\n")
|
||
sb.WriteString("3. 观察:仔细阅读工具输出;pod_execute 输出含 [exit_code=0] 表示成功。\n")
|
||
} else {
|
||
sb.WriteString("2. 行动:调用 ssh_execute 执行命令(一次只做关键的、可验证的一步)。\n")
|
||
sb.WriteString("3. 观察:仔细阅读命令输出(含 exit_code,0 表示成功)。\n")
|
||
}
|
||
sb.WriteString("4. 循环:如果失败或问题未解决,分析原因,换一种方法重试,直到真正解决。不要因一次失败就放弃。\n")
|
||
sb.WriteString("5. 收尾:问题解决后,用清晰的中文总结:问题根因、你做了什么、最终结果、后续建议。然后停止调用工具。\n\n")
|
||
|
||
sb.WriteString("【重要】务必真正解决问题,而不是假装解决。每一步都要基于实际工具输出判断," +
|
||
"禁止编造不存在的输出。超时或 API 失败时,向用户说明并建议排查方向。\n\n")
|
||
|
||
// Layer 5: 记忆注入
|
||
if strings.TrimSpace(evolveContext) != "" {
|
||
sb.WriteString("【历史经验(来自自进化引擎)】\n" + evolveContext + "\n\n")
|
||
}
|
||
|
||
sb.WriteString("【输出要求】使用简体中文,简洁专业。思考与命令穿插呈现,避免冗长空话。")
|
||
return sb.String()
|
||
}
|
||
|
||
// FormatToolDescriptions 把工具名+描述格式化为列表文本 // Logan.Li
|
||
func FormatToolDescriptions(items []struct{ Name, Desc string }) string {
|
||
var sb strings.Builder
|
||
for _, it := range items {
|
||
sb.WriteString(fmt.Sprintf("- %s: %s\n", it.Name, it.Desc))
|
||
}
|
||
return sb.String()
|
||
} |