interface Prompt { prompt_id: string; name: string; description?: string; system_prompt: string; require_document?: boolean; intro_message?: string; } interface SessionCapability { name: SessionCapabilityName; description?: string | null; } interface Document { document_id: string; title: string; file: string; description?: string; search_count?: number; ef_search?: number | null; processed: boolean; processed_v2: boolean; created_at: string; updated_at: string; } interface LLMType { name: string; service?: string; } interface TTSType { name: string; streamable?: boolean; service: string; model?: string | null; voice?: string | null; voice_settings?: unknown | null; style?: string | null; voice_extra_data?: unknown | null; } interface STTType { name: string; service: string; options?: unknown | null; } /** * Response from POST /api/v1/session/{session_id}/stt/. * * The wire payload includes additional fields (e.g., `locale`, * `normalized_text`) that the SDK intentionally does not expose. */ interface STTResponse { text: string; } interface TextNormalizationConfig { textnormalizationconfig_id: string; name: string; created_at: string; } interface ModelStyleConfig { modelstyleconfig_id: string; key: string; value: string; } interface AIHumanModelFile { name: string; file?: string | null; } interface ModelStyle { name: string; model: string; model_file?: string | null; model_files: AIHumanModelFile[]; style: string; file?: string | null; platform_type?: string; configs: ModelStyleConfig[]; } interface BackgroundImage { backgroundimage_id: string; title: string; image: string; created_at: string; } interface MCPServer { mcpserver_id: string; name: string; description?: string; url: string; transport_protocol?: string; server_timeout_sec?: number; extra_data?: unknown | null; } interface SessionTemplate { sessiontemplate_id: string; name: string; description: string | null; prompt: Prompt; capability: SessionCapability[]; document: Document | null; llm_type: LLMType; tts_type: TTSType; stt_type: STTType; text_normalization_config?: TextNormalizationConfig | null; text_normalization_locale?: string | null; stt_text_normalization_config?: TextNormalizationConfig | null; stt_text_normalization_locale?: string | null; model_style: ModelStyle; background_image: BackgroundImage | null; agent: string | null; padding_left: number | null; padding_top: number | null; padding_height: number | null; extra_data: unknown | null; mcp_servers?: MCPServer[]; created_at: string; last_used_at: string | null; } declare enum SessionCapabilityName { LLM = "LLM", TTS = "TTS", STT = "STT", STF_ONPREMISE = "STF_ONPREMISE", STF_WEBRTC = "STF_WEBRTC" } declare enum SessionEvent { SESSION_START = "SESSION_START", SESSION_DURING = "SESSION_DURING", SESSION_LOG = "SESSION_LOG", SESSION_END = "SESSION_END", SESSION_ERROR = "SESSION_ERROR", SESSION_TTS = "SESSION_TTS", SESSION_STT = "SESSION_STT", SESSION_LLM = "SESSION_LLM" } interface TextNormalizationDownload { config_id: string; config_name: string; file_url: string; } declare class PersoUtil { /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "name": string * } * ] */ static getLLMs(apiServer: string, apiKey: string): Promise; /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "name": string, * "model": string, * "style": string * } * ] */ static getModelStyles(apiServer: string, apiKey: string): Promise; /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "backgroundimage_id": string, * "title": string, * "image": string * "created_at": string // ex) "2024-05-02T09:05:55.395Z" * } * ] */ static getBackgroundImages(apiServer: string, apiKey: string): Promise; /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "name": string, * "service": string, * "speaker": string * } * ] */ static getTTSs(apiServer: string, apiKey: string): Promise; /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "name": string, * "service": string * } * ] */ static getSTTs(apiServer: string, apiKey: string): Promise; /** * Sends text to the TTS API and returns Base64-encoded audio. * @param apiServer Perso Interactive API Server * @param params Session ID and text to synthesize. * @returns JSON with Base64 audio string. * { * "audio": string * } */ static makeTTS(apiServer: string, { sessionId, text, locale, output_format }: { sessionId: string; text: string; locale?: string; output_format?: string; }): Promise<{ audio: string; }>; /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "name": string, * "description": string, * "prompt_id": string, * "system_prompt": string, * "require_document": boolean, * "intro_message": string * } * ] */ static getPrompts(apiServer: string, apiKey: string): Promise; /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "document_id": string, * "title": string, * "description": string, * "search_count": number, * "processed": boolean, * "created_at": string, // ex) "2024-05-02T09:05:55.395Z", * "updated_at": string // ex) "2024-05-02T09:05:55.395Z" * } * ] */ static getDocuments(apiServer: string, apiKey: string): Promise; /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "mcpserver_id": string, * "name": string, * "url": string, * "description": string * } * ] */ /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * [ * { * "textnormalizationconfig_id": string, * "name": string, * "created_at": string * } * ] */ static getTextNormalizations(apiServer: string, apiKey: string): Promise; /** * Downloads the ruleset data file for a Text Normalization Config. * Returns a pre-signed Blob Storage URL for the CSV file. * The client can download the file directly from this URL and leverage Azure Blob Storage ETag for caching. * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @param configId Text Normalization Config ID * @returns JSON * { * "config_id": string, * "config_name": string, * "file_url": string * } */ static downloadTextNormalization(apiServer: string, apiKey: string, configId: string): Promise; /** * Retrieves the list of session templates. * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns Array of SessionTemplate objects */ static getSessionTemplates(apiServer: string, apiKey: string): Promise; /** * Retrieves a single session template by ID. * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @param sessionTemplateId Session Template ID * @returns SessionTemplate object */ static getSessionTemplate(apiServer: string, apiKey: string, sessionTemplateId: string): Promise; static getMcpServers(apiServer: string, apiKey: string): Promise; /** * @param apiServer Perso Interactive API Server * @param apiKey Perso Interactive API Key * @returns JSON * { * "session_id": string, * "client_sdp": string, * "server_sdp": string, * "prompt": { * "name": string, * "description": string, * "prompt_id": string, * "system_prompt": string, * "require_document": boolean, * "intro_message": string * }, * "document": string, * "llm_type": { * "name": string * }, * "model_style": { * "name": string, * "model": string, * "model_file": string, * "style": string, * "file": string * }, * "tts_type": { * "name": string, * "service": string, * "model": string, * "voice": string, * "style": string, * "voice_extra_data": string * }, * "ice_servers": Array, * "status": string, // "CREATED", "EXCHANGED", "IN_PROGRESS", "TERMINATED" * "termination_reason": string, // "GRACEFUL_TERMINATION", "SESSION_EXPIRED_BEFORE_CONNECTION", "SESSION_LOST_AFTER_CONNECTION", "SESSION_MISC_ERROR", "MAX_ACTIVE_SESSION_QUOTA_EXCEEDED", "MAX_MIN_PER_SESSION_QUOTA_EXCEEDED", "TOTAL_MIN_PER_MONTH_QUOTA_EXCEEDED" * "duration_sec": number, * "created_at": string, // ex) "2024-05-02T09:05:55.395Z" * "padding_left": number, * "padding_top": number, * "padding_height": number, * "background_image": { * "backgroundimage_id": string, * "title": string, * "image": string, * "created_at": string // ex) "2024-05-02T09:05:55.395Z" * }, * "extra_data": string, * "capability": Array<{ * "name": string, // "LLM" | "TTS" | "STT" | "STF_ONPREMISE" | "STF_WEBRTC" * "description": string * }> * } */ static getSessionInfo(apiServer: string, sessionId: string): Promise; static sessionEvent(apiServer: string, sessionId: string, sessionEvent: SessionEvent, detail?: string): Promise; /** * Sends audio data to the STT API endpoint for speech-to-text conversion. * @param apiServer Perso Interactive API Server * @param sessionId Session ID for the current session * @param audioFile Audio file (WAV format) * @param language Optional language code (e.g., 'ko', 'en') * @returns STTResponse with only the transcribed text. * * The server returns additional fields (e.g., `locale`, `normalized_text`) * which are intentionally not exposed by the SDK. */ static makeSTT(apiServer: string, sessionId: string, audioFile: File, language?: string): Promise; /** * Initiates an LLM streaming request and returns the response body reader. * @param apiServer Perso Interactive API Server * @param sessionId Session ID for the current session * @param body Request body containing messages and tools * @param signal Optional AbortSignal to cancel the request * @returns ReadableStreamDefaultReader for SSE streaming response * @throws ApiError when response is not ok */ static makeLLM(apiServer: string, sessionId: string, body: { messages: Array; tools: Array; }, signal?: AbortSignal): Promise>; /** * Fetches ICE server configuration for WebRTC peer connection setup. * @param apiServer Perso Interactive API Server * @param sessionId Session ID * @returns Array of RTCIceServer configurations. */ static getIceServers(apiServer: string, sessionId: string): Promise>; /** * Exchanges the client SDP offer with the server and returns the server SDP answer. * @param apiServer Perso Interactive API Server * @param sessionId Session ID * @param offer Client SDP offer from RTCPeerConnection.createOffer(). * @returns Server SDP answer to set as remote description. */ static exchangeSDP(apiServer: string, sessionId: string, offer: RTCSessionDescriptionInit): Promise; static parseJson(response: Response): Promise; } interface Chat { text: string; isUser: boolean; timestamp: Date; } declare enum ChatState { RECORDING = "RECORDING", LLM = "LLM", ANALYZING = "ANALYZING", SPEAKING = "SPEAKING", TTS = "TTS" } declare class ChatTool { name: string; description: string; parameters: object; call: (arg: TArg) => TResult | Promise; executeOnly: boolean; constructor(name: string, description: string, parameters: object, call: (arg: TArg) => TResult | Promise, executeOnly?: boolean); } type LLMStreamChunk = { type: 'message'; chunks: string[]; message: string; finish: boolean; } | ({ type: 'tool_call'; tool_calls: Array; } & Record) | ({ type: 'tool_result'; tool_call_id: string; result: object; } & Record) | { type: 'error'; error: Error; }; interface ProcessLLMOptions { message: string; tools?: Array; signal?: AbortSignal; } /** * High-level controller around a WebRTC PeerConnection that proxies Perso's * real-time APIs through convenience helpers. */ declare class Perso extends EventTarget { #private; pc: RTCPeerConnection; dc: RTCDataChannel; streams: Array; pingTime: number; pingIntervalId: ReturnType | null; /** * Hooks a peer/data channel pair to status/ping listeners so consumers can * interact with the remote Perso session through a single object. * @param pc WebRTC peer connection that handles the media tracks. * @param dc Data channel dedicated to control-plane messages. */ constructor(pc: RTCPeerConnection, dc: RTCDataChannel); /** * Negotiates WebRTC connectivity and waits until the first remote stream is ready. * * When an optional `stream` is provided (legacy bidirectional mode), the stream's * tracks are added to the peer connection so the server can receive client audio. * Without a stream the audio transceiver is set to receive-only. * * @param apiServer Perso API server URL. * @param sessionId Session identifier created via `createSessionId`. * @param width Desired avatar canvas width. * @param height Desired avatar canvas height. * @param stream Optional local media stream for bidirectional audio (legacy mode). * @returns Ready-to-use `Perso` instance, or `null` when the session has no STF capability. * @throws ApiError When session event or WebRTC negotiation fails. * @throws Timeout When remote streams fail to arrive in time. */ static create(apiServer: string, sessionId: string, width: number, height: number, stream?: MediaStream): Promise; /** * Configures a browser `RTCPeerConnection` with the ICE servers provided by * the Perso API. * @param iceServers ICE server configuration list. * @returns Initialized RTCPeerConnection. */ private static createPeerConnection; /** * Resolves once `condition()` passes or throws a `Timeout` when the maximum * number of checks is exceeded. * @param condition Predicate that signals readiness. * @param interval Interval between checks in milliseconds. * @param times Maximum number of attempts before timing out. * @throws Timeout When the predicate never returns true. */ private static waitFor; /** * Returns true when the first remote track has been attached and the data * channel is open. * @returns Whether the instance is ready for interaction. */ isReady(): boolean; /** * Subscribes to status updates and returns an unsubscribe helper to mirror * the EventTarget subscription pattern. * @param callback Listener invoked for each status event. * @returns Unsubscribe function that removes the listener. */ subscribeStatus(callback: (event: CustomEvent) => void): () => void; /** * Returns the first incoming remote stream if available. * @returns Primary remote `MediaStream`. */ getStream(): MediaStream; /** * Sends a typed JSON payload through the control data channel. All higher * level helpers eventually defer to this method. * @param type Message type identifier. * @param data Arbitrary JSON-serializable payload. */ sendMessage(type: string, data: object): void; /** * Requests a TTS-to-face (TTSTF) playback with the provided text. * @param message Text to synthesize and animate. */ ttstf(message: string): void; private static readonly BACKPRESSURE_THRESHOLD; private static readonly FILE_TRANSFER_TIMEOUT; /** * Sends a file to the remote peer via a dedicated WebRTC data channel. * The file is chunked and transmitted in binary format. Applies * backpressure when the channel's buffer exceeds 512 KB to avoid * SCTP overflow on large files. * @param file The file blob to send. * @param chunksize Size of each chunk in bytes (default: 65536). * @returns Promise resolving to the file reference string from the server. */ sendFile(file: Blob, chunksize?: number): Promise; /** * Sends an audio file for Speech-to-Face (STF) processing. * The avatar will lip-sync to the provided audio. * @param file Audio file blob (mp3 or wav). * @param format Audio format ('mp3' or 'wav'). * @param message Optional text message associated with the audio. * @returns Promise resolving to the file reference string. */ stf(file: Blob, format: string, message: string): Promise; /** * Signals the remote agent to start buffering microphone audio. */ recordStart(): void; /** * Stops recording and asks the server to run speech-to-text optionally using * a specific language. * @param language Optional language code for STT. */ recordEndStt(language?: string): void; /** * Stops recording and translates the captured speech from `src_lang` to * `dst_lang`. * @param src_lang Source language code. * @param dst_lang Destination language code. */ recordEndTranslate(src_lang: string, dst_lang: string): void; /** * Resizes the render canvas of the avatar/video surface on the remote side. * @param width Target width in CSS pixels. * @param height Target height in CSS pixels. */ changeSize(width: number, height: number): void; /** * Switches the avatar template (model + dress) at runtime. * @param model Optional avatar model ID. * @param dress Optional outfit ID. */ setTemplate(model?: string, dress?: string): void; /** * Drops any buffered speech or text that has not been processed yet. */ clearBuffer(): void; /** * Sends a heartbeat over the data channel to keep the connection alive. */ ping(): void; /** * Registers a data-channel handler for a specific message `type` and returns * a remover so callers can dispose of the listener cleanly. * @param type Message type to watch for. * @param callback Handler invoked with the parsed payload. * @returns Function that removes the listener. */ setMessageCallback(type: string, callback: (data: T) => void): () => void; tts(base64: string, resample?: boolean): Promise; /** * Tears down the PeerConnection due to remote/network failure and emits a * timeout status so the UI can inform users. */ private close; /** * Allows callers to gracefully terminate a session themselves and emit a * successful status code for analytics. */ closeSelf(): void; } /** * Manages a full Perso chat session including UI state, LLM orchestration, * microphone handling, and speech synthesis triggers. */ declare class Session { apiServer: string; sessionId: string; perso: Perso | null; clientTools: Array; private chatStatesHandler; private chatLogHandler; private sttEventHandler; private errorHandler; private lastStfTimeoutHandle; private stfTotalDuration; private stfTimeoutStartTime; private messageHistory; private chatLog; private llmProcessor; private chatStateMap; private sttRecorder; private sttTimeoutHandle; private sttTimeoutAudioFile; private heartbeatIntervalId; private readonly legacyVoiceChatMode; private readonly stream; /** * Sets up message listeners and chat-state trackers for a Perso session. * @param apiServer Perso API server URL. * @param sessionId Id of the session negotiated with the backend. * @param perso Underlying Perso WebRTC controller. * @param clientTools Tools exposed to the LLM for function calling. * @param options Optional configuration. * @param options.stream Local audio stream for legacy bidirectional mode. * @param options.legacyVoiceChatMode Whether legacy voice chat mode is enabled. */ constructor(apiServer: string, sessionId: string, perso: Perso | null, clientTools: Array, options?: { stream?: MediaStream; legacyVoiceChatMode?: boolean; }); private llmJob; /** * Sends a user utterance through Perso's internal LLM and speaks the result * while automatically updating history, chat logs, and chat states. * @param message User message to forward to the LLM. * @remarks * - Emits entries via `subscribeChatLog`. * - Updates all chat states published through `subscribeChatStates`. * - Maintains `messageHistory` for subsequent LLM calls. */ processChat(message: string): Promise; processLLM(options: ProcessLLMOptions): AsyncGenerator; getMessageHistory(): ReadonlyArray; /** @deprecated Use processTTSTF() with explicit history management instead. */ processCustomChat(message: string): void; /** * Sends an assistant message to the LLM history and triggers TTSTF playback. * @param message Assistant output that should be spoken immediately. */ processTTSTF(message: string): void; transcribeAudio(audio: Blob | File, language?: string): Promise; /** * Same as transcribeAudio but returns the full STTResponse object. * * The SDK currently exposes only `text`. Other server-side fields * (e.g., `locale`, `normalized_text`) are intentionally omitted. */ transcribeAudioDetailed(audio: Blob | File, language?: string): Promise; /** * Sends an audio file for Speech-to-Face processing. * * `format` is optional — when omitted, undefined, or supplied as a MIME type * (`audio/wav` / `audio/mpeg`), it's normalized via `normalizeAudioFormat`, * which falls back to `file.type`. Pass `'wav'` or `'mp3'` directly when the * source format is already known and authoritative. * * @param file Audio blob to lip-sync. * @param format Optional format hint. Canonical (`'wav'`/`'mp3'`), MIME, or omitted. * @param message Optional text caption. * @returns File reference returned by the server. */ processSTF(file: Blob, format?: string, message?: string): Promise; processTTS(message: string, options?: { resample?: boolean; locale?: string; output_format?: string; }): Promise; /** * Triggers the recording state and instructs Perso to buffer microphone * audio for speech-to-text. * * In legacy mode this sends a `record-start` DataChannel message to the * server which begins buffering the bidirectional audio stream. * * @returns Result of `perso.recordStart()`. * @deprecated Use startProcessSTT() instead. Legacy voice chat mode will be removed in a future version. */ startVoiceChat(): void; /** * Stops the microphone capture, transitions the UI to analyzing, and sends * the buffered audio to STT. * * In legacy mode this sends a `record-end-stt` DataChannel message. The * server responds with a `"stt"` message which is handled by the * `setMessageCallback("stt")` listener in the constructor, triggering * `processChat` automatically. * * @deprecated Use stopProcessSTT() instead. Legacy voice chat mode will be removed in a future version. */ stopVoiceChat(): void; /** * Starts recording audio for STT processing. * Uses Web Audio API internally to capture microphone input and encode to WAV format. * @param timeout Optional timeout in milliseconds to automatically stop recording. * @throws Error if already recording or if microphone access is denied. */ startProcessSTT(timeout?: number): Promise; /** * Result of STT processing including transcribed text and recorded audio. */ lastRecordedAudioFile: File | null; /** * Stops STT recording and sends the audio to the STT API for transcription. * @param language Optional language code for STT (e.g., 'ko', 'en'). * @returns Promise resolving to the transcribed text. * @throws STTError if the API call fails. * @throws Error if not currently recording. */ stopProcessSTT(language?: string): Promise; /** * Checks if STT recording is currently in progress or has audio pending processing. * @returns True if recording is active or audio is pending from timeout. */ isSTTRecording(): boolean; /** * Resizes the avatar video canvas on the remote renderer. * @param width Target width in CSS pixels. * @param height Target height in CSS pixels. */ changeSize(width: number, height: number): void; /** * Cancels any ongoing LLM/TTS jobs, clears remote buffers, and resets all * chat-state timers. */ clearBuffer(): Promise; /** * Assigns the remote video stream to a DOM video tag. * @param element Target video element. */ setSrc(element: HTMLVideoElement): void; /** * Returns the first remote stream exposed by the Perso renderer. * @returns Remote `MediaStream`. */ getRemoteStream(): MediaStream | undefined; /** * Returns the local microphone stream associated with the session. * Only available in legacy voice chat mode. * @returns Local `MediaStream` or `null` if not in legacy mode. * @deprecated Legacy voice chat mode will be removed in a future version. */ getLocalStream(): MediaStream | null; /** * Gracefully closes the session and remote connection. */ stopSession(): void; /** * Subscribes to Perso status events and notifies the caller when the session * closes (distinguishing manual/automatic closure). * * In non-WebRTC mode (perso is null), the callback is never invoked and a * no-op unsubscribe is returned. Use `setErrorHandler` to detect session * termination caused by heartbeat failure instead. * * @param callback Invoked with `true` when closed manually. * @returns Function to unsubscribe the listener. */ onClose(callback: (manualClosed: boolean) => void): () => void; /** * Subscribes to chat-state updates. * @param callback Handler receiving the active state set. * @returns Function to unsubscribe. */ subscribeChatStates(callback: (chatStates: Set) => void): () => void; /** * Subscribes to chat-log updates (most recent message first). * @param callback Handler receiving the full chat log snapshot. * @returns Function to unsubscribe. */ subscribeChatLog(callback: (chatLog: Array) => void): () => void; /** * Streams raw STT text results to the provided callback instead of routing * them back into the LLM pipeline automatically. * @param callback Handler for STT transcripts. * @returns Function to unsubscribe/reset STT event handling. */ setSttResultCallback(callback: (text: string) => void): () => void; /** * Allows UI code to react to LLM/streaming errors. * @param callback Handler receiving the raised error. * @returns Function to unsubscribe. */ setErrorHandler(callback: (error: Error) => void): () => void; /** * @returns Session identifier assigned by the backend. */ getSessionId(): string; private processChatInternal; /** * Looks up a tool definition by the function name provided in a tool_call. * @param clientTools Registered tools. * @param funcName Name requested by the LLM. * @returns Matching `ChatTool` or null. */ private getChatTool; /** * Cancels any in-flight LLM stream by flipping the cancellation flag and * awaiting the pending promise if necessary. */ private llmCancel; private pipelineSuppressed; private clearLLMJob; /** * Filters/sanitizes text and sends it to Perso's TTSTF endpoint while toggling * the ANALYZING chat state. * @param message Assistant message to speak aloud. */ private processTTSTFInternal; /** * Adds an entry at the top of the chat log and notifies subscribers. * @param message Text to store. * @param isUser Whether the entry was produced by the user. */ private addMessageToChatLog; /** * Adjusts the internal reference-counted chat-state map and emits changes as * needed. * @param add State(s) to activate/increment. * @param remove State(s) to deactivate/decrement. */ private setChatState; /** * Resets all chat states to an idle baseline and emits the update. */ private resetChatState; /** * Converts the ref-counted map into a set of active chat states. * @param state Current state map. * @returns Set of states whose count is > 0. */ private exchangeChatStateMapToSet; /** * Broadcasts chat-state updates via the internal EventTarget. * @param newChatStateSet Active state set. */ private dispatchChatState; /** * Compares two chat-state sets for equality. */ private isEqualChatStateMap; /** * Sends a SESSION_LOG event for the current session. * @param detail Optional event description. Strings are sent as-is; objects are JSON-stringified. */ logSessionEvent(detail?: string | Record): Promise; /** * Emits an error event for UI subscribers. */ private setError; /** * Gracefully closes the underlying Perso connection on behalf of the session. */ private close; private startHeartbeat; private stopHeartbeat; } declare const DEFAULT_API_SERVER = "https://platform.perso.ai"; /** * Callbacks that LlmProcessor uses to notify the host of side effects. */ interface LlmProcessorCallbacks { onChatStateChange: (add: ChatState | null, remove: ChatState | null) => void; onError: (error: Error) => void; onChatLog: (message: string, isUser: boolean) => void; onTTSTF: (message: string) => void; } /** * Configuration for LlmProcessor construction. */ interface LlmProcessorConfig { apiServer: string; sessionId: string; clientTools: Array; callbacks: LlmProcessorCallbacks; } /** * Handles LLM streaming, SSE parsing, tool execution, and message history * management as a standalone module. */ declare class LlmProcessor { private config; private messageHistory; constructor(config: LlmProcessorConfig); /** * Streams LLM responses as an AsyncGenerator, yielding {@link LLMStreamChunk} * discriminated by `type`: `assistant`, `tool_call`, `tool_result`, `error`. * * Consumers get pull-based control over the stream — backpressure, * early exit via `break`, and `AbortSignal` cancellation are handled * naturally by the generator protocol. * * **Yield strategy**: message-type SSE events within a single `reader.read()` * are batched into one `assistant` chunk (accumulated `chunks[]` + `message`). * Non-message events (`tool_call`, `tool`) flush pending message chunks first * to preserve ordering. * * **Tool execution** happens internally — `tool_call` and `tool_result` chunks * are yielded for observability. If tools require a follow-up LLM call, * the generator loops transparently. * * @param options - Message, optional tool overrides, and optional AbortSignal. * @yields {LLMStreamChunk} Streaming chunks. The final `assistant` chunk * has `finish: true` and contains the complete `chunks[]` / `message`. * @throws {Error} If `options.message` is empty. * @throws {LLMError} Re-thrown when the initial fetch fails with a non-API error. */ processLLM(options: ProcessLLMOptions): AsyncGenerator; private parseSSEStream; private executeToolCalls; addToHistory(entry: object): void; getHistory(): ReadonlyArray; } interface WavRecorderOptions { channels?: number; targetSampleRate?: number; } /** * Records audio from the microphone and produces WAV files using Web Audio API. * Uses AudioWorklet (standard API) for cross-browser compatibility. * * Browser Support: * - Chrome 66+ * - Firefox 76+ * - Safari 14.1+ * - iOS Safari 14.5+ * - Edge 79+ */ declare class WavRecorder { private audioContext; private mediaStream; private workletNode; private sourceNode; private audioChunks; private isRecordingState; private channels; private targetSampleRate; constructor(options?: WavRecorderOptions); /** * Starts recording audio from the microphone. * Requests microphone permission via getUserMedia. * @throws Error if already recording or if microphone access is denied. */ start(): Promise; /** * Stops recording and returns the recorded audio as a WAV File. * Uses bidirectional communication with AudioWorklet to ensure all audio data is captured. * @returns Promise resolving to a File containing the recorded WAV audio. * @throws Error if not currently recording. */ stop(): Promise; isRecording(): boolean; } /** * Factory function to create a WavRecorder. * @param options Optional configuration. * @returns A new WavRecorder instance. */ declare function createWavRecorder(options?: WavRecorderOptions): WavRecorder; type ApiKeyOptions = { apiKey: string; apiServer?: string; }; /** * Retrieves the list of available LLM providers from the API. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getLLMs(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getLLMs(apiServer: string, apiKey: string): ReturnType; /** * Retrieves available TTS providers. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getTTSs(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getTTSs(apiServer: string, apiKey: string): ReturnType; /** * Retrieves available STT providers. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getSTTs(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getSTTs(apiServer: string, apiKey: string): ReturnType; /** * Fetches avatar model styles. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getModelStyles(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getModelStyles(apiServer: string, apiKey: string): ReturnType; /** * Fetches preset background images. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getBackgroundImages(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getBackgroundImages(apiServer: string, apiKey: string): ReturnType; /** * Returns predefined prompt templates. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getPrompts(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getPrompts(apiServer: string, apiKey: string): ReturnType; /** * Returns supporting document metadata usable by the session. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getDocuments(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getDocuments(apiServer: string, apiKey: string): ReturnType; /** * Lists MCP server identifiers configured for the tenant. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getMcpServers(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getMcpServers(apiServer: string, apiKey: string): ReturnType; /** * Retrieves available text normalization options. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getTextNormalizations(options: ApiKeyOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getTextNormalizations(apiServer: string, apiKey: string): ReturnType; type GetTextNormalizationOptions = { apiKey: string; configId: string; apiServer?: string; }; /** * Downloads the ruleset data file for a Text Normalization Config. * Returns a pre-signed Blob Storage URL for the CSV file. * * @param options.apiKey API key used for authentication. * @param options.configId Identifier of the Text Normalization Config to download. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getTextNormalization(options: GetTextNormalizationOptions): Promise; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. * @param configId Identifier of the Text Normalization Config to download. */ declare function getTextNormalization(apiServer: string, apiKey: string, configId: string): Promise; /** * Retrieves the list of session templates. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getSessionTemplates(options: ApiKeyOptions): Promise; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getSessionTemplates(apiServer: string, apiKey: string): Promise; type GetSessionTemplateOptions = { apiKey: string; sessionTemplateId: string; apiServer?: string; }; type AllSettings = { llms: Awaited>; ttsTypes: Awaited>; sttTypes: Awaited>; modelStyles: Awaited>; backgroundImages: Awaited>; prompts: Awaited>; documents: Awaited>; mcpServers: Awaited>; textNormalizations: Awaited> | []; }; /** * Convenience helper that fetches every dropdown-friendly resource needed to * build a Perso session configuration screen in one call chain. * * @param options.apiKey API key used for authentication. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getAllSettings(options: ApiKeyOptions): Promise; /** * @param apiServer Perso API server URL. * @param apiKey API key used for authentication. */ declare function getAllSettings(apiServer: string, apiKey: string): Promise; type MakeTTSParams = { sessionId: string; text: string; locale?: string; output_format?: string; }; type MakeTTSOptions = MakeTTSParams & { apiServer?: string; }; /** * Sends text to the TTS API and returns Base64-encoded audio. * * @param options.sessionId Identifier of the active session. * @param options.text Text to synthesize. * @param options.locale Optional locale override for the TTS voice. * @param options.output_format Optional output audio format. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function makeTTS(options: MakeTTSOptions): Promise<{ audio: string; }>; /** * @param apiServer Perso API server URL. * @param params TTS request parameters (`sessionId`, `text`, optional `locale`, `output_format`). */ declare function makeTTS(apiServer: string, params: MakeTTSParams): Promise<{ audio: string; }>; type GetSessionInfoOptions = { sessionId: string; apiServer?: string; }; /** * Retrieves metadata for an existing session. * * @param options.sessionId Identifier of the session to look up. * @param options.apiServer Perso API server URL. Defaults to `https://platform.perso.ai`. */ declare function getSessionInfo(options: GetSessionInfoOptions): ReturnType; /** * @param apiServer Perso API server URL. * @param sessionId Identifier of the session to look up. */ declare function getSessionInfo(apiServer: string, sessionId: string): ReturnType; type CreateSessionObjectOptions = { sessionId: string; width: number; height: number; clientTools: Array; apiServer?: string; }; /** @overload Object-form. Uses DEFAULT_API_SERVER when apiServer is omitted. */ declare function createSession(options: CreateSessionObjectOptions): Promise; /** * Creates a Session with REST-based STT/TTS (current mode). */ declare function createSession(apiServer: string, sessionId: string, width: number, height: number, clientTools: Array): Promise; /** * Creates a Session with bidirectional WebRTC audio (legacy mode). * @deprecated Legacy voice chat mode will be removed in a future version. * Use the 5-argument overload with REST-based STT/TTS instead. */ declare function createSession(apiServer: string, sessionId: string, width: number, height: number, enableVoiceChat: boolean, clientTools: Array): Promise; type CreateSessionIdBody = { using_stf_webrtc: boolean; model_style: string; prompt: string; document?: string; background_image?: string; mcp_servers?: Array; padding_left?: number; padding_top?: number; padding_height?: number; llm_type?: string; tts_type?: string; stt_type?: string; text_normalization_config?: string; text_normalization_locale?: string | null; stt_text_normalization_config?: string; stt_text_normalization_locale?: string | null; }; type CreateSessionIdObjectOptions = { apiKey: string; params: CreateSessionIdBody; apiServer?: string; } | { apiKey: string; sessionTemplateId: string; apiServer?: string; }; /** @overload Object-form. Uses DEFAULT_API_SERVER when apiServer is omitted. */ declare function createSessionId(options: CreateSessionIdObjectOptions): Promise; /** @overload Positional form — SessionTemplate ID. */ declare function createSessionId(apiServer: string, apiKey: string, sessionTemplateId: string): Promise; /** @overload Positional form — explicit params. */ declare function createSessionId(apiServer: string, apiKey: string, params: CreateSessionIdBody): Promise; declare class ApiError extends Error { errorCode: number; code: string; detail: string; attr?: string | undefined; constructor(errorCode: number, code: string, detail: string, attr?: string | undefined); } declare class LLMError extends Error { underlyingError: ApiError | LLMStreamingResponseError; constructor(underlyingError: ApiError | LLMStreamingResponseError); } declare class LLMStreamingResponseError extends Error { description: string; constructor(description: string); } declare class STTError extends Error { underlyingError: ApiError; constructor(underlyingError: ApiError); } declare class TTSError extends Error { underlyingError: ApiError | TTSDecodeError; constructor(underlyingError: ApiError | TTSDecodeError); } declare class TTSDecodeError extends Error { description: string; constructor(description: string); } /** * Domain error thrown by `createSessionId()` (and the `getSessionTemplate` * path) when the underlying API returns an `ApiError`. The raw * `errorCode`, `code`, `detail`, and `attr` fields are preserved as-is — * callers inspect them to decide how to react (e.g. treat * `code === 'invalid'` with a "not found" detail as feature-unavailable * per LIV-1681). * * Extends `ApiError`, so existing `instanceof ApiError` branches keep * working. */ declare class SessionCreationError extends ApiError { constructor(source: ApiError); } /** * Session creation failed because a referenced resource does not exist. * Triggered when the server returns `code === 'does_not_exist'` — for * example, a `prompt_id` that has been deleted or never existed. The * `attr` field, when present, identifies which input field referenced * the missing resource (e.g. `'prompt'`). */ declare class DoesNotExistError extends SessionCreationError { constructor(source: ApiError); } /** * Session creation failed because a referenced resource is not assigned * to the caller's organization. Triggered when the server returns * `code === 'not_in_organization'` — for example, an LLM/TTS/STT type * that exists in the platform catalog but is not enabled for this * organization. The `attr` field, when present, identifies which input * field referenced the unavailable resource. */ declare class NotInOrganizationError extends SessionCreationError { constructor(source: ApiError); } declare function getWavSampleRate(arrayBuffer: ArrayBuffer): number; declare const TTS_TARGET_SAMPLE_RATE = 16000; export { ApiError, ChatState, ChatTool, DEFAULT_API_SERVER, DoesNotExistError, LLMError, LLMStreamingResponseError, LlmProcessor, NotInOrganizationError, STTError, Session, SessionCreationError, TTSDecodeError, TTSError, TTS_TARGET_SAMPLE_RATE, WavRecorder, createSession, createSessionId, createWavRecorder, getAllSettings, getBackgroundImages, getDocuments, getLLMs, getMcpServers, getModelStyles, getPrompts, getSTTs, getSessionInfo, getSessionTemplates, getTTSs, getTextNormalization, getTextNormalizations, getWavSampleRate, makeTTS }; export type { AIHumanModelFile, ApiKeyOptions, BackgroundImage, Chat, CreateSessionObjectOptions, Document, GetSessionInfoOptions, GetSessionTemplateOptions, GetTextNormalizationOptions, LLMStreamChunk, LLMType, LlmProcessorCallbacks, LlmProcessorConfig, MCPServer, MakeTTSOptions, ModelStyle, ModelStyleConfig, ProcessLLMOptions, Prompt, STTResponse, STTType, SessionCapability, SessionTemplate, TTSType, TextNormalizationConfig, TextNormalizationDownload, WavRecorderOptions };