主要变更: - 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>
107 lines
3.3 KiB
Go
107 lines
3.3 KiB
Go
// builtin.go - 内置只读工具 // Logan.Li
|
||
// analyze_output:对冗长命令输出做摘要/错误提取,避免 token 爆炸,辅助 LLM 聚焦关键线索。
|
||
package tools
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"strings"
|
||
)
|
||
|
||
// AnalyzeOutputTool 输出分析工具(只读,Safe) // Logan.Li
|
||
type AnalyzeOutputTool struct{}
|
||
|
||
// NewAnalyzeOutputTool 创建输出分析工具 // Logan.Li
|
||
func NewAnalyzeOutputTool() *AnalyzeOutputTool { return &AnalyzeOutputTool{} }
|
||
|
||
// Name 工具名 // Logan.Li
|
||
func (t *AnalyzeOutputTool) Name() string { return "analyze_output" }
|
||
|
||
// Description 给 LLM 的说明 // Logan.Li
|
||
func (t *AnalyzeOutputTool) Description() string {
|
||
return "分析一段(可能很长的)命令输出文本:统计行数、提取疑似错误/告警行、必要时截断保留首尾。" +
|
||
"当 ssh_execute 或 pod_execute 返回内容过长时调用此工具提炼关键信息再继续推理。"
|
||
}
|
||
|
||
// Parameters 参数定义 // Logan.Li
|
||
func (t *AnalyzeOutputTool) Parameters() map[string]interface{} {
|
||
return map[string]interface{}{
|
||
"type": "object",
|
||
"properties": map[string]interface{}{
|
||
"output": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "待分析的文本输出",
|
||
},
|
||
"focus": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "可选关注点,如 error、memory、disk",
|
||
},
|
||
},
|
||
"required": []string{"output"},
|
||
}
|
||
}
|
||
|
||
// RiskLevel 静态风险(只读安全) // Logan.Li
|
||
func (t *AnalyzeOutputTool) RiskLevel() RiskLevel { return RiskSafe }
|
||
|
||
// Execute 执行输出分析 // Logan.Li
|
||
func (t *AnalyzeOutputTool) Execute(ctx context.Context, args map[string]interface{}) (*Result, error) {
|
||
output := StringParam(args, "output")
|
||
focus := strings.ToLower(StringParam(args, "focus"))
|
||
if output == "" {
|
||
return &Result{Success: true, Output: "(空输出)"}, nil
|
||
}
|
||
|
||
lines := strings.Split(output, "\n")
|
||
total := len(lines)
|
||
|
||
// 超长截断:保留前 40 + 后 40 行,中间用省略标注
|
||
truncated := false
|
||
if total > 120 {
|
||
head := lines[:40]
|
||
tail := lines[total-40:]
|
||
lines = append(append(head, fmt.Sprintf("... [已省略 %d 行] ...", total-80)), tail...)
|
||
truncated = true
|
||
}
|
||
|
||
// 提取疑似错误/告警行
|
||
errorKeywords := []string{"error", "fail", "exception", "traceback", "denied",
|
||
"permission", "timeout", "refused", "unavailable", "critical", "fatal",
|
||
"错误", "失败", "拒绝", "超时", "无法", "异常"}
|
||
if focus != "" {
|
||
errorKeywords = append([]string{focus}, errorKeywords...)
|
||
}
|
||
var errorLines []string
|
||
for _, line := range lines {
|
||
low := strings.ToLower(line)
|
||
for _, kw := range errorKeywords {
|
||
if strings.Contains(low, kw) {
|
||
errorLines = append(errorLines, strings.TrimSpace(line))
|
||
break
|
||
}
|
||
}
|
||
}
|
||
if len(errorLines) > 20 {
|
||
errorLines = errorLines[:20]
|
||
}
|
||
|
||
// 组装分析摘要
|
||
var sb strings.Builder
|
||
sb.WriteString(fmt.Sprintf("总行数: %d", total))
|
||
if truncated {
|
||
sb.WriteString("(已截断保留首尾)")
|
||
}
|
||
sb.WriteString("\n")
|
||
if len(errorLines) > 0 {
|
||
sb.WriteString(fmt.Sprintf("疑似错误/告警行 (%d):\n", len(errorLines)))
|
||
for _, l := range errorLines {
|
||
sb.WriteString(" " + l + "\n")
|
||
}
|
||
} else {
|
||
sb.WriteString("未发现明显错误关键词\n")
|
||
}
|
||
sb.WriteString("\n输出片段:\n" + strings.Join(lines, "\n"))
|
||
|
||
return &Result{Success: true, Output: sb.String()}, nil
|
||
}
|