import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle"; import { IFileService } from "@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service"; import { ILogService } from "@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service"; import { IStorageService } from "@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage.service"; import { IUserDataProfilesService } from "@codingame/monaco-vscode-api/vscode/vs/platform/userDataProfile/common/userDataProfile.service"; import { ILifecycleService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/services/lifecycle/common/lifecycle.service"; import { IVoiceTranscriptStore } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/agentsVoice/common/voiceTranscriptStore.service"; /** * Discriminates what produced this entry. Only ``user_voice`` and * ``agent_voice`` are rendered in the transcripts UI; ``agent_tool_call`` and * ``coding_event`` are persisted so we can replay them as cross-session * context to the backend without polluting the visible transcript. * * user_voice — what the user said (ASR-committed) * agent_voice — what the voice agent spoke back (TTS text) * agent_tool_call — a tool the voice agent dispatched (send_to_chat, etc.) * coding_event — a status transition on a Copilot coding session * (started, finished, needs-input, errored) */ export type VoiceTranscriptKind = "user_voice" | "agent_voice" | "agent_tool_call" | "coding_event"; /** * Free-form metadata for non-voice entries. Field meaning depends on ``kind``: * agent_tool_call: { toolName, toolArgs? } * coding_event: { codingSessionId, codingStatus, codingSessionLabel? } */ export interface IVoiceTranscriptEntryMetadata { readonly toolName?: string; readonly toolArgs?: Record; readonly codingSessionId?: string; readonly codingStatus?: string; readonly codingSessionLabel?: string; } /** * One committed entry in a voice conversation timeline. Persisted as a single * JSON line in the user's transcript JSONL file. * * Local-only — voice_code's backend does not have persistent conversation * memory today. Entry IDs are generated client-side; ``ancestorIds`` chains * the entries we have written so far. * * Backwards-compat note: older builds wrote entries without ``kind`` / * ``metadata`` and only with ``role``. The store auto-wipes any such file on * first read so we never have to read mixed-schema data in memory. */ export interface IVoiceTranscriptTurn { /** Locally-generated entry id. */ readonly turnId: string; /** Local ancestor entry ids, root → parent (the previous entry's turnId, or empty for the first entry). */ readonly ancestorIds: readonly string[]; /** What produced this entry. */ readonly kind: VoiceTranscriptKind; /** * Legacy/display role. Kept so the existing transcripts ViewPane can * label rows without inspecting ``kind``. For non-voice kinds this is set * to ``'assistant'`` (the entry is something the agent did). */ readonly role: "user" | "assistant"; /** * Human-readable text for this entry. For voice kinds this is the spoken * sentence. For tool-call / coding-event kinds it is a one-line summary * suitable for context replay (e.g. ``"called send_to_chat(text=...)"``). */ readonly text: string; /** Wall-clock time at the moment of persistence. ISO 8601 string. */ readonly timestamp: string; /** Optional kind-specific structured fields. */ readonly metadata?: IVoiceTranscriptEntryMetadata; } /** * Index of all transcripts known on this machine. Persisted via * ``IStorageService`` (scope PROFILE, target MACHINE). One entry per * GitHub login that has ever spoken on this machine. */ export interface IVoiceTranscriptIndex { readonly entries: { [userId: string]: IVoiceTranscriptIndexEntry; }; readonly version: 1; } export interface IVoiceTranscriptIndexEntry { /** GitHub login — partition key, doubles as filename stem. */ readonly userId: string; /** ISO timestamp of first ever turn for this user. */ readonly createdAt: string; /** ISO timestamp of most recent appended turn. */ readonly lastUpdatedAt: string; /** Total turn count for this user. */ readonly turnCount: number; /** Optional archive cutoff. Turns with timestamp < archivedBefore are hidden in the UI by default. */ readonly archivedBefore?: string; } /** * Local on-disk transcript store for the Agents Voice feature. * * Layout (mirrors the chatSessionStore precedent, adapted for the per-user * single-conversation model used by voice): * * /voiceTranscripts/.jsonl (append-only) * IStorageService[AgentsVoiceStorageKeys.TranscriptIndex] (PROFILE/MACHINE) * * Writes are serialized via a ``Sequencer`` so simultaneous appendTurn calls * preserve line ordering. A shutdown flush is registered so a final append * completes before the window closes. */ export declare class VoiceTranscriptStore extends Disposable implements IVoiceTranscriptStore { private readonly fileService; private readonly storageService; private readonly lifecycleService; private readonly logService; readonly _serviceBrand: undefined; private readonly storageRoot; private readonly writeQueue; /** Cached snapshot of the index; we read once at startup and write through. */ private indexCache; private pendingWrite; private shuttingDown; constructor(fileService: IFileService, storageService: IStorageService, userDataProfilesService: IUserDataProfilesService, lifecycleService: ILifecycleService, logService: ILogService); appendTurn(userId: string, turn: IVoiceTranscriptTurn): Promise; loadTurns(userId: string, opts?: { since?: string; limit?: number; }): Promise; getIndexEntry(userId: string): IVoiceTranscriptIndexEntry | undefined; archiveUpTo(userId: string, cutoff: string): Promise; unarchive(userId: string): Promise; deleteAll(userId: string): Promise; private fileFor; private doAppendTurn; private updateIndexEntry; private flushIndex; private readIndexFromStorage; }