- Agent 支持 SSE(步骤边推、正文分块),JSON 非流式 fallback - tool calling 覆盖 openai-chat / anthropic / responses(单测解析回灌) - P1:mcp.json mode=read_write 才可写;需 confirm_danger;Agent 剥离模型自带令牌 - GET /api/ai/mcp-status、POST /api/ai/agent/confirm;审计 source=mcp|agent
58 lines
1.3 KiB
Go
58 lines
1.3 KiB
Go
package aitools
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// AuditEntry MCP/Agent 工具审计;不含密码与大结果全文。 // Logan.Li
|
|
type AuditEntry struct {
|
|
Time string `json:"time"`
|
|
Tool string `json:"tool"`
|
|
ConnectionID string `json:"connection_id,omitempty"`
|
|
Mode string `json:"mode"`
|
|
Source string `json:"source,omitempty"` // mcp | agent
|
|
OK bool `json:"ok"`
|
|
Summary string `json:"summary,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
var auditMu sync.Mutex
|
|
|
|
func AuditPath() (string, error) {
|
|
dir, err := opsxdbDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return filepath.Join(dir, "logs", "mcp-audit.jsonl"), nil
|
|
}
|
|
|
|
// AppendAudit 追加一行 JSONL;失败静默(不影响工具主路径)。
|
|
func AppendAudit(e AuditEntry) {
|
|
if e.Time == "" {
|
|
e.Time = time.Now().Format(time.RFC3339)
|
|
}
|
|
path, err := AuditPath()
|
|
if err != nil {
|
|
return
|
|
}
|
|
auditMu.Lock()
|
|
defer auditMu.Unlock()
|
|
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
|
|
return
|
|
}
|
|
b, err := json.Marshal(e)
|
|
if err != nil {
|
|
return
|
|
}
|
|
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer f.Close()
|
|
_, _ = f.Write(append(b, '\n'))
|
|
}
|