/** * CallLog — JSONL persistent record of every outbound voice call the agent * initiates through VoiceCall (and updates as VoiceStatus polls for status). * * Why a journal: BlockRun's gateway doesn't expose a "list my calls" endpoint — * /v1/voice/call/{id} works but you need to remember the id. Without local * persistence, the panel can't show a "recent calls" view and cross-session * memory ("did I already leave a voicemail at this number this week?") is * impossible. * * Why append-only with multiple rows per call_id: calls are async, status * mutates over time (queued → in_progress → completed). Append-only avoids * the JSONL-rewrite-race that an in-place update would introduce — readers * pick the latest row by call_id when summarizing. Same approach trade-log * uses for fills vs corrections. * * Schema (additive over time; readers tolerate missing optional fields): * timestamp: ms epoch of THIS log row (not the call start) * call_id: Bland.ai call identifier (stable across rows) * to / from: E.164 numbers * task: the natural-language instructions the AI followed * voice / max_duration_min / language: caller-side preferences (queue row only) * status: queued | in_progress | completed | failed | cancelled | * busy | no-answer | voicemail * duration_sec: actual call length once known * transcript: full conversation text once completed * recording_url: Bland-hosted MP3/WAV link * paid_usd: 0.54 charged on the initial POST; later rows carry 0 * tx_hash: x402 settlement hash for the initial POST */ export type CallStatus = 'queued' | 'in_progress' | 'completed' | 'failed' | 'cancelled' | 'busy' | 'no-answer' | 'voicemail'; export interface CallLogEntry { timestamp: number; call_id: string; to: string; from: string; task: string; voice?: string; max_duration_min?: number; language?: string; status: CallStatus; duration_sec?: number; transcript?: string; recording_url?: string; paid_usd: number; tx_hash?: string; } export declare function isTerminalStatus(s: unknown): s is CallStatus; export declare function defaultCallLogPath(): string; export declare class CallLog { private filePath; constructor(filePath?: string); append(entry: CallLogEntry): void; /** Read every entry on disk in chronological (append) order. */ all(): CallLogEntry[]; /** * Latest row for each call_id, newest first by initial-row timestamp. * This is the canonical "list of calls" view for the panel. */ summary(limit?: number): CallLogEntry[]; byCallId(callId: string): CallLogEntry | null; }