import type { ChatConfig, ChatConfigProvider } from "./types/config.js"; import type { UserIdentity } from "./types/messaging.js"; import type { ToolCallHandler } from "./types/tools.js"; import { type VoiceMachine } from "./voice-machine.js"; declare global { interface Window { __YAK_INTERNAL_DEV__?: boolean; } } export type VoiceStateListener = (machine: VoiceMachine) => void; export interface YakVoiceSessionConfig { appId: string; /** Tool call handler. Same shape as `YakClientConfig.onToolCall`. */ onToolCall?: ToolCallHandler; onRedirect?: (path: string) => void; /** * Static chat config (routes + tools). Sent to the mint endpoint so the LLM * knows what tools are available. Use this OR `getConfig`. */ chatConfig?: ChatConfig; /** * Async provider for chat config. Called on every session start — useful when * tools/routes depend on the current page or user. Takes precedence over * `chatConfig` if both are provided. */ getConfig?: ChatConfigProvider; /** * Override the API origin (where voice sessions are minted). Defaults to * `https://chat.yak.io`. Most integrators never set this. */ apiOrigin?: string; /** * Privacy opt-out: stop sending any page context (URL, title, visible text) * with the voice session. The session still works; the assistant just won't * be aware of the current page. */ disablePageContent?: boolean; /** * Signed end-user identity. Same shape and contract as `YakClientConfig.user`: * when supplied, the voice session persists its transcript server-side keyed * to this user (so insights + memory work) and the model recalls the user's * memory at session start. The `hash` must be HMAC-SHA256(apiSecret, id) * computed on the integrator's backend — never expose `apiSecret` to the * browser. */ user?: UserIdentity; } export declare class YakVoiceSession { private config; private machine; private resources; private dispatchedCallIds; private listeners; private pageHideHandler; /** Per-session token totals, accumulated from each `response.done` event. */ private usage; /** * Reverse map: hashed tool id (what OpenAI calls back with) → original host * tool name (what `onToolCall` expects). Populated on every `start()` from * the resolved chat config. */ private toolNameById; /** Assigns each settled transcript a stable order key and tracks unacked sends. */ private transcript; /** Latched once the server says this session won't persist (storage off / no row). */ private persistenceOff; /** At most one persist POST in flight; a newer flush coalesces behind it. */ private persistInFlight; private persistAgain; /** * The voice session id used for transcript persistence. Mirrors * `resources.voiceSessionId` but is kept separate so a final flush during * `teardown()` (which clears `resources`) can still address the session. */ private persistSessionId; constructor(config: YakVoiceSessionConfig); /** * Resolve the API origin lazily on each call. Environment-dependent defaults * (e.g. a local chat UI) may not be ready at construction time, so resolving * eagerly would risk baking in the production URL. */ private get apiOrigin(); /** Update mutable config fields (handlers, getConfig). */ updateConfig(patch: Partial): void; getState(): VoiceMachine; /** * The current API origin (defaults to `https://chat.yak.io`). Useful for * building URLs to static assets like the brand logo. */ getApiOrigin(): string; onStateChange(listener: VoiceStateListener): () => void; /** * Begin a voice session. Should be invoked from a user gesture (button * click) so `getUserMedia` and audio playback both have transient activation. */ start(): Promise; /** Stop the session and tear down all resources. */ stop(): Promise; /** Tear down everything and remove listeners. Call once before discarding the instance. */ destroy(): void; private buildMessageContext; private accumulateUsage; private resetTranscriptState; /** * Drive the sequencer from a transcript event, then flush. A `user_turn` * reserves an ordering slot (its transcript completes asynchronously and can * land after the assistant has replied); a failed transcription releases that * slot; a settled `transcript` becomes a message to append. Each settled * message triggers a flush of everything still unacked. */ private handleTranscriptEvent; /** * Send everything still unacked as one additive batch. The server mints each * message's id from its boundary `ts` (idempotent, K-sortable) and creates the * conversation on the first user turn — so a re-sent batch is a safe no-op, and * the unacked set doubles as the retry + greeting-defer + `pagehide`-beacon * queue. Normally the batch is a single just-settled message. */ private flushTranscripts; private buildTranscriptBody; private persistMessages; private beaconTranscript; private sendOverDataChannel; private routeToolCall; /** * Relay an MCP tool call to the server, which holds the org's credentials * and executes against the remote MCP server. The browser only ever passes * through the tool name, args, and the opaque result. */ private execMcpTool; private mintToken; /** * Decorate the host's tool manifest with readable, collision-free model-facing ids * and populate `this.toolNameById` for reverse lookup. Mirrors the decoration the * chat-ui iframe applies before sending tools to `/api/chat`. GraphQL/REST tools are * ordinary manifest entries here (contributed by their adapters), so no special-casing * is needed. */ private buildDecoratedManifest; private exchangeSdp; private buildStopEventBody; private postSessionEvent; private teardown; private failWith; private dispatch; private safeExtractPageContext; private attachPageHide; } //# sourceMappingURL=voice-session.d.ts.map