mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-10-26 01:54:43 +08:00
77 lines
2.7 KiB
TypeScript
77 lines
2.7 KiB
TypeScript
import { appendFileSync, mkdirSync, writeFileSync } from 'fs'
|
|
import { join } from 'path'
|
|
import { redactAgentValueForLog } from './agentTextRedaction'
|
|
|
|
const MAX_EVENT_CHARS = 48_000
|
|
const MAX_LOG_BYTES = 2 * 1024 * 1024
|
|
|
|
function safeRunId(value: string): string {
|
|
return String(value || 'run').replace(/[^a-zA-Z0-9_-]+/g, '-').slice(0, 80) || 'run'
|
|
}
|
|
|
|
function boundedJson(value: unknown): string {
|
|
let serialized = ''
|
|
try {
|
|
serialized = JSON.stringify(redactAgentValueForLog(value), (_key, nested) => {
|
|
if (typeof nested === 'string' && nested.length > 12_000) {
|
|
return `${nested.slice(0, 7_200)}\n…[调试字段已裁剪]…\n${nested.slice(-4_000)}`
|
|
}
|
|
if (Array.isArray(nested) && nested.length > 80) {
|
|
return [...nested.slice(0, 60), { debugTruncatedItems: nested.length - 70 }, ...nested.slice(-10)]
|
|
}
|
|
return nested
|
|
})
|
|
} catch (error) {
|
|
serialized = JSON.stringify({ serializationError: String(error || '未知序列化错误') })
|
|
}
|
|
if (serialized.length <= MAX_EVENT_CHARS) return serialized
|
|
return JSON.stringify({
|
|
debugTruncated: true,
|
|
originalChars: serialized.length,
|
|
preview: `${serialized.slice(0, 30_000)}\n…[调试事件已裁剪]…\n${serialized.slice(-12_000)}`,
|
|
})
|
|
}
|
|
|
|
export class AgentDebugLog {
|
|
readonly filePath: string
|
|
private bytesWritten = 0
|
|
private closed = false
|
|
|
|
constructor(rootDir: string, runId: string) {
|
|
const directory = join(rootDir, 'logs', 'agent-runs')
|
|
mkdirSync(directory, { recursive: true })
|
|
this.filePath = join(directory, `${new Date().toISOString().replace(/[:.]/g, '-')}-${safeRunId(runId)}.jsonl`)
|
|
const header = `${JSON.stringify({ schema: 'weflow-agent-debug-v1', runId, createdAt: Date.now() })}\n`
|
|
writeFileSync(this.filePath, header, 'utf8')
|
|
this.bytesWritten = Buffer.byteLength(header)
|
|
}
|
|
|
|
event(type: string, data: unknown = {}): void {
|
|
if (this.closed) return
|
|
try {
|
|
const line = `${boundedJson({ at: Date.now(), type, data })}\n`
|
|
const bytes = Buffer.byteLength(line)
|
|
if (this.bytesWritten + bytes > MAX_LOG_BYTES) {
|
|
const ending = `${JSON.stringify({ at: Date.now(), type: 'debug_log.truncated', data: { maxBytes: MAX_LOG_BYTES } })}\n`
|
|
appendFileSync(this.filePath, ending, 'utf8')
|
|
this.bytesWritten += Buffer.byteLength(ending)
|
|
this.closed = true
|
|
return
|
|
}
|
|
appendFileSync(this.filePath, line, 'utf8')
|
|
this.bytesWritten += bytes
|
|
} catch {
|
|
// 诊断日志绝不能中断用户正在执行的智能体任务。
|
|
this.closed = true
|
|
}
|
|
}
|
|
}
|
|
|
|
export function createAgentDebugLog(rootDir: string, runId: string): AgentDebugLog | null {
|
|
try {
|
|
return new AgentDebugLog(rootDir, runId)
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|