Spaces:
Sleeping
Sleeping
| import { randomUUID } from 'node:crypto'; | |
| import { appendFile, mkdir } from 'node:fs/promises'; | |
| import { dirname, join } from 'node:path'; | |
| import { homedir, hostname } from 'node:os'; | |
| import { TEMPLATE_AGENT_ID, TEMPLATE_AGENT_NAME, TEMPLATE_AGENT_NAMESPACE } from '../../metadata.js'; | |
| import { getSupabaseClient } from '../../supabase.js'; | |
| export type TemplateLogLevel = 'info' | 'warn' | 'error' | 'debug'; | |
| export type TemplateLogStatus = 'started' | 'accepted' | 'completed' | 'failed'; | |
| export type TemplateLogEntry = { | |
| agentId: string; | |
| agentName: string; | |
| namespace: string; | |
| runId: string; | |
| requestId: string; | |
| surface: string; | |
| event: string; | |
| action?: string; | |
| level: TemplateLogLevel; | |
| status: TemplateLogStatus; | |
| details?: Record<string, unknown>; | |
| durationMs?: number; | |
| createdAt: string; | |
| }; | |
| export const TEMPLATE_LOG_PATH = join(homedir(), '.config', 'sin', TEMPLATE_AGENT_ID, 'events.ndjson'); | |
| export const TEMPLATE_TELEMETRY_TABLE = 'fleet_telemetry'; | |
| export class TemplateLogger { | |
| readonly runId: string; | |
| constructor(runId: string = randomUUID()) { | |
| this.runId = runId; | |
| } | |
| async log(input: { | |
| surface: string; | |
| event: string; | |
| level?: TemplateLogLevel; | |
| status?: TemplateLogStatus; | |
| action?: string; | |
| details?: Record<string, unknown>; | |
| durationMs?: number; | |
| requestId?: string; | |
| }) { | |
| const entry: TemplateLogEntry = { | |
| agentId: TEMPLATE_AGENT_ID, | |
| agentName: TEMPLATE_AGENT_NAME, | |
| namespace: TEMPLATE_AGENT_NAMESPACE, | |
| runId: this.runId, | |
| requestId: input.requestId || randomUUID(), | |
| surface: input.surface, | |
| event: input.event, | |
| action: input.action, | |
| level: input.level || 'info', | |
| status: input.status || 'completed', | |
| details: input.details, | |
| durationMs: input.durationMs, | |
| createdAt: new Date().toISOString(), | |
| }; | |
| await mkdir(dirname(TEMPLATE_LOG_PATH), { recursive: true }); | |
| await appendFile(TEMPLATE_LOG_PATH, `${JSON.stringify(entry)}\n`, 'utf8'); | |
| try { | |
| await getSupabaseClient().from(TEMPLATE_TELEMETRY_TABLE).insert({ | |
| agent_id: entry.agentId, | |
| run_id: entry.runId, | |
| level: entry.level, | |
| event: entry.event, | |
| details: { | |
| ...(entry.details || {}), | |
| action: entry.action, | |
| requestId: entry.requestId, | |
| surface: entry.surface, | |
| status: entry.status, | |
| hostname: hostname(), | |
| }, | |
| duration_ms: entry.durationMs, | |
| created_at: entry.createdAt, | |
| }); | |
| } catch {} | |
| const line = `[${entry.createdAt}] [${entry.agentId}] [${entry.surface}] [${entry.level.toUpperCase()}] ${entry.event}`; | |
| if (entry.level === 'error') { | |
| console.error(line, entry.details || ''); | |
| } else if (entry.level === 'warn') { | |
| console.warn(line, entry.details || ''); | |
| } else { | |
| console.log(line, entry.details || ''); | |
| } | |
| return entry; | |
| } | |
| started(surface: string, event: string, details?: Record<string, unknown>, requestId?: string, action?: string) { | |
| return this.log({ surface, event, details, requestId, action, level: 'info', status: 'started' }); | |
| } | |
| accepted(surface: string, event: string, details?: Record<string, unknown>, requestId?: string, action?: string) { | |
| return this.log({ surface, event, details, requestId, action, level: 'info', status: 'accepted' }); | |
| } | |
| succeeded( | |
| surface: string, | |
| event: string, | |
| details?: Record<string, unknown>, | |
| durationMs?: number, | |
| requestId?: string, | |
| action?: string, | |
| ) { | |
| return this.log({ | |
| surface, | |
| event, | |
| details, | |
| durationMs, | |
| requestId, | |
| action, | |
| level: 'info', | |
| status: 'completed', | |
| }); | |
| } | |
| failed(surface: string, event: string, error: unknown, durationMs?: number, requestId?: string, action?: string) { | |
| const details = error instanceof Error ? { error: error.message } : { error: String(error) }; | |
| return this.log({ | |
| surface, | |
| event, | |
| details, | |
| durationMs, | |
| requestId, | |
| action, | |
| level: 'error', | |
| status: 'failed', | |
| }); | |
| } | |
| } | |
| export function createTemplateLogger(runId?: string) { | |
| return new TemplateLogger(runId); | |
| } | |