/** * @license * Copyright 2026 Qwen * SPDX-License-Identifier: Apache-2.0 */ export type SessionLogEventType = 'session.start' | 'session.end' | 'vad.speech_started' | 'vad.speech_stopped' | 'audio.input_mute_changed' | 'audio.input_heartbeat' | 'transcript.user' | 'transcript.assistant' | 'response.created' | 'response.done' | 'response.cancelled' | 'realtime.protocol' | 'tool.call' | 'task.authorization_rejected' | 'tool.result' | 'backend.event' | 'proactive.debug' | 'failure' | 'instruction.delivery' | 'session.report' | 'search.delivery' | 'visual.analysis' | 'inject.context' | 'inject.speech' | 'permission.request' | 'permission.decision' | 'playback.started' | 'playback.cleared' | 'error'; export interface SessionLogOptions { directory: string; liveSessionId: string; maxBytes?: number; now?: () => number; /** Optional opt-in debug timeline mirror; never affects the normal log. */ onEvent?: (event: Record) => void; } export declare class SessionLog { private readonly options; private stream; private readonly path; private readonly maxBytes; private readonly now; private seq; private bytes; private rotations; private failed; private closed; constructor(options: SessionLogOptions); /** * Logging must never take the call down: failures flip to no-op mode, and * writes after close() are dropped (a reopened stream would only lose its * buffer at process.exit). */ write(type: SessionLogEventType, payload: Record): void; /** Terminal: later write() calls are documented no-ops. */ close(): Promise; get filePath(): string; private ensureStream; /** * Rotation must complete before the next line is written, or the freshly * reopened stream would share the old inode and the rename would drag it * along (observed as reordered lines in the rotated file and a missing * main file). Rename synchronously first, then let the old stream flush * its remaining buffer into the rotated file it already points at. */ private rotate; }