(event: {
level?: DiagnosticLevel;
phase: string;
durationMs?: number;
data?: Record<string, unknown>;
})
| 106 | } |
| 107 | |
| 108 | export function emitDiagnostic(event: { |
| 109 | level?: DiagnosticLevel; |
| 110 | phase: string; |
| 111 | durationMs?: number; |
| 112 | data?: Record<string, unknown>; |
| 113 | }): void { |
| 114 | const scope = diagnosticsStorage.getStore(); |
| 115 | if (!scope) return; |
| 116 | const payload: DiagnosticEvent = { |
| 117 | ts: new Date().toISOString(), |
| 118 | level: event.level ?? 'info', |
| 119 | phase: event.phase, |
| 120 | session: scope.session, |
| 121 | requestId: scope.requestId, |
| 122 | command: scope.command, |
| 123 | durationMs: event.durationMs, |
| 124 | data: event.data ? redactDiagnosticData(event.data) : undefined, |
| 125 | }; |
| 126 | scope.events.push(payload); |
| 127 | scope.phaseCounts.set(event.phase, (scope.phaseCounts.get(event.phase) ?? 0) + 1); |
| 128 | if (!scope.debug) return; |
| 129 | const fileLine = `${JSON.stringify(payload)}\n`; |
| 130 | try { |
| 131 | if (scope.logPath) { |
| 132 | appendDiagnosticLine(scope.logPath, fileLine); |
| 133 | scope.liveWrittenEventCount = scope.events.length; |
| 134 | } |
| 135 | if (scope.traceLogPath) { |
| 136 | appendDiagnosticLine(scope.traceLogPath, fileLine); |
| 137 | } |
| 138 | if (!scope.logPath && !scope.traceLogPath) { |
| 139 | process.stderr.write(`[agent-device][diag] ${fileLine}`); |
| 140 | } |
| 141 | } catch { |
| 142 | // Best-effort diagnostics should not break request flow. |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | export async function withDiagnosticTimer<T>( |
| 147 | phase: string, |
no test coverage detected