主要变更: - 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>
155 lines
5.4 KiB
Go
155 lines
5.4 KiB
Go
// Package agentcli 是 Agent CLI 引擎的顶层入口。 // Logan.Li
|
||
// 组装 llm 客户端 + 工具注册中心(含 ssh_execute)+ 安全控制器 + Evolver + ReAct 核心,
|
||
// 对外暴露 Engine,由 controller 通过依赖注入(EventCallback / ConfirmFn / SSH 凭据)驱动。
|
||
//
|
||
// 设计原则(参考 opsxcli,适配为 aiops 后端库):
|
||
// - 零业务依赖:不 import model/controller,所有持久化与 WS 由 controller 层负责。
|
||
// - 复用 aiops 既有能力:LLM 走 OpenAI 兼容(model.LLMConfig),SSH 走 pkg/remoteexec。
|
||
// - 安全:危险命令黑名单硬拒,高危命令经 ConfirmFn 由前端确认。
|
||
// - 自进化:Evolver 异步学习经验并注入下次 Prompt,失败优雅降级。
|
||
package agentcli
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
|
||
"ezops/pkg/agentcli/core"
|
||
"ezops/pkg/agentcli/evolver"
|
||
"ezops/pkg/agentcli/llm"
|
||
"ezops/pkg/agentcli/safety"
|
||
"ezops/pkg/agentcli/tools"
|
||
k8sclient "ezops/pkg/kubernetesclient"
|
||
"ezops/pkg/remoteexec"
|
||
)
|
||
|
||
// RunMode Agent 运行模式 // Logan.Li
|
||
const (
|
||
RunModeHost = "host"
|
||
RunModeKubernetes = "kubernetes"
|
||
)
|
||
|
||
// NormalizeRunMode 规范化运行模式(兼容旧 k8s 参数) // Logan.Li
|
||
func NormalizeRunMode(mode string) string {
|
||
if mode == "k8s" || mode == RunModeKubernetes {
|
||
return RunModeKubernetes
|
||
}
|
||
if mode == "" {
|
||
return RunModeHost
|
||
}
|
||
return mode
|
||
}
|
||
|
||
// KubernetesTarget Kubernetes 模式目标上下文(由 controller 注入) // Logan.Li
|
||
type KubernetesTarget struct {
|
||
Client *k8sclient.Client
|
||
ClusterName string
|
||
Namespace string
|
||
PodName string
|
||
Container string
|
||
}
|
||
|
||
// EngineConfig 引擎配置(由 controller 从 model.LLMConfig + 目标上下文构建后注入) // Logan.Li
|
||
type EngineConfig struct {
|
||
Mode string // host | kubernetes
|
||
LLM llm.Config // LLM 客户端配置(endpoint 已解析)
|
||
SSH remoteexec.SSHConfig // 主机模式 SSH 配置
|
||
Kubernetes *KubernetesTarget // Kubernetes 模式目标
|
||
SafetyMode safety.Mode // 安全模式(默认 balanced)
|
||
Core *core.Config // ReAct 配置(nil 用默认)
|
||
MemoryDir string // Evolver 记忆目录(空则 data/agentcli)
|
||
}
|
||
|
||
// Engine Agent CLI 引擎实例(每个 WebSocket 连接 / 任务一个) // Logan.Li
|
||
type Engine struct {
|
||
agent *core.Agent
|
||
safety *safety.Controller
|
||
tools *tools.Registry
|
||
evolver *evolver.EvolverEngine
|
||
}
|
||
|
||
// NewEngine 组装引擎并注册默认工具集 // Logan.Li
|
||
func NewEngine(cfg EngineConfig) (*Engine, error) {
|
||
coreCfg := cfg.Core
|
||
if coreCfg == nil {
|
||
coreCfg = core.DefaultConfig()
|
||
}
|
||
if cfg.MemoryDir != "" {
|
||
coreCfg.MemoryDir = cfg.MemoryDir
|
||
}
|
||
safetyMode := cfg.SafetyMode
|
||
if safetyMode == "" {
|
||
safetyMode = safety.ModeBalanced
|
||
}
|
||
|
||
// LLM 客户端
|
||
client := llm.NewClient(cfg.LLM)
|
||
|
||
// 工具注册中心:按模式注册互斥工具集 // Logan.Li
|
||
registry := tools.NewRegistry()
|
||
runMode := NormalizeRunMode(cfg.Mode)
|
||
coreCfg.Mode = runMode
|
||
|
||
switch runMode {
|
||
case RunModeKubernetes:
|
||
if cfg.Kubernetes == nil || cfg.Kubernetes.Client == nil {
|
||
return nil, fmt.Errorf("Kubernetes 模式缺少集群客户端")
|
||
}
|
||
kt := cfg.Kubernetes
|
||
registry.Register(tools.NewKubernetesGetTool(kt.Client, kt.Namespace))
|
||
registry.Register(tools.NewPodLogsTool(kt.Client, kt.Namespace, kt.PodName, kt.Container))
|
||
registry.Register(tools.NewPodExecuteTool(kt.Client, kt.Namespace, kt.PodName, kt.Container, coreCfg.ToolTimeout))
|
||
registry.Register(tools.NewKubernetesActionTool(kt.Client, kt.Namespace))
|
||
default:
|
||
sshTool, err := tools.NewSSHExecuteTool(cfg.SSH, coreCfg.ToolTimeout)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("ssh_execute 初始化失败: %w", err)
|
||
}
|
||
registry.Register(sshTool)
|
||
}
|
||
registry.Register(tools.NewAnalyzeOutputTool())
|
||
|
||
// 安全控制器
|
||
sc := safety.NewController(safetyMode)
|
||
|
||
// Evolver(LLM 可用时启用学习;失败降级)
|
||
ev, err := evolver.NewEvolverEngine(coreCfg.MemoryDir, client)
|
||
if err != nil {
|
||
ev = nil // 降级:无自学习,不影响主流程
|
||
}
|
||
|
||
agent := core.NewAgent(client, registry, coreCfg, sc, ev)
|
||
return &Engine{agent: agent, safety: sc, tools: registry, evolver: ev}, nil
|
||
}
|
||
|
||
// SetCallback 注入事件回调(驱动前端渲染 + DB 持久化) // Logan.Li
|
||
func (e *Engine) SetCallback(cb core.EventCallback) { e.agent.SetCallback(cb) }
|
||
|
||
// SetConfirmFn 注入高危确认回调(controller 推 WS confirm 事件并阻塞等前端回传) // Logan.Li
|
||
func (e *Engine) SetConfirmFn(fn safety.ConfirmFn) { e.safety.SetConfirmFn(fn) }
|
||
|
||
// SetAutoApprove 测试用:自动批准(生产禁用) // Logan.Li
|
||
func (e *Engine) SetAutoApprove(b bool) { e.safety.SetAutoApprove(b) }
|
||
|
||
// Run 执行任务(ReAct 循环);targetInfo 为目标上下文摘要;prior 为上一轮对话历史(不含 system) // Logan.Li
|
||
func (e *Engine) Run(ctx context.Context, query, targetInfo string, prior []llm.Message, priorTokens int) (*core.RunResult, error) {
|
||
return e.agent.Run(ctx, query, targetInfo, prior, priorTokens)
|
||
}
|
||
|
||
// EvolveStats 进化统计(供审计展示) // Logan.Li
|
||
func (e *Engine) EvolveStats() map[string]interface{} {
|
||
if e.evolver == nil {
|
||
return map[string]interface{}{"enabled": false}
|
||
}
|
||
return e.evolver.GetStats()
|
||
}
|
||
|
||
// Close 释放资源(含 SSH 长连接) // Logan.Li
|
||
func (e *Engine) Close() {
|
||
if e.tools != nil {
|
||
e.tools.Close()
|
||
}
|
||
if e.agent != nil {
|
||
e.agent.Close()
|
||
}
|
||
}
|