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 RunID string `json:"run_id,omitempty"` 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')) }