337 lines
10 KiB
TypeScript
337 lines
10 KiB
TypeScript
/**
|
|
* Type declarations for `audio-agent-client.js`.
|
|
*
|
|
* The SDK is plain ESM with no build step; this file exists so TypeScript
|
|
* consumers get autocompletion and type checking. Keep it in sync with the JS.
|
|
*/
|
|
|
|
export interface AudioFormat {
|
|
readonly sampleRate: 44100;
|
|
readonly frameSamples: 882;
|
|
readonly frameBytes: 1764;
|
|
readonly sttSampleRate: 16000;
|
|
}
|
|
|
|
export const AUDIO: AudioFormat;
|
|
|
|
export const CLIENT_EVENTS: readonly string[];
|
|
|
|
/** Union accepted by every audio-sending helper. */
|
|
export type AudioChunk =
|
|
| Int16Array
|
|
| Float32Array
|
|
| ArrayBuffer
|
|
| ArrayBufferView
|
|
| number[];
|
|
|
|
export function int16ArrayFromBytes(buffer: ArrayBuffer | ArrayBufferView): Int16Array;
|
|
export function float32ToInt16(floats: Float32Array | number[]): Int16Array;
|
|
export function int16ToFloat32(ints: Int16Array): Float32Array;
|
|
export function toInt16(chunk: AudioChunk): Int16Array;
|
|
|
|
/** Any object with a `type` discriminator, as emitted by the engine. */
|
|
export interface ServerEvent {
|
|
type: string;
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
/** Server-assigned session id, sent once at connect time. */
|
|
export interface SessionEvent extends ServerEvent {
|
|
type: 'session';
|
|
id: string;
|
|
}
|
|
export interface CuesEvent extends ServerEvent {
|
|
type: 'cues';
|
|
lang: string;
|
|
config: Record<string, unknown>;
|
|
}
|
|
export interface UserEvent extends ServerEvent {
|
|
type: 'user';
|
|
text: string;
|
|
}
|
|
export interface AssistantDeltaEvent extends ServerEvent {
|
|
type: 'assistant_delta';
|
|
text: string;
|
|
}
|
|
export interface AssistantMarkdownEvent extends ServerEvent {
|
|
type: 'assistant_markdown';
|
|
text: string;
|
|
}
|
|
export interface AssistantEndEvent extends ServerEvent {
|
|
type: 'assistant_end';
|
|
}
|
|
export interface CueEvent extends ServerEvent {
|
|
type: 'cue';
|
|
kind: 'filler' | 'start_filler' | 'backchannel';
|
|
name: string;
|
|
category?: string;
|
|
pause_ms?: number;
|
|
}
|
|
export interface BargeInEvent extends ServerEvent {
|
|
type: 'barge_in';
|
|
source: string;
|
|
prob?: number;
|
|
}
|
|
export interface ToolCallEvent extends ServerEvent {
|
|
type: 'tool_call';
|
|
name: string;
|
|
arguments: unknown;
|
|
}
|
|
export interface AudioSourceEvent extends ServerEvent {
|
|
type: 'audio_source';
|
|
state: 'loading' | 'playing' | 'stopped' | 'error';
|
|
url: string;
|
|
text?: string;
|
|
}
|
|
export interface ErrorEvent extends ServerEvent {
|
|
type: 'error';
|
|
text: string;
|
|
}
|
|
|
|
/** Payload of the local `audio` event: one decoded PCM frame. */
|
|
export interface AudioFrame {
|
|
samples: Int16Array;
|
|
buffer: ArrayBuffer;
|
|
sampleRate: number;
|
|
}
|
|
|
|
/** Payload of the local `close` event. */
|
|
export interface CloseEvent {
|
|
code: number;
|
|
reason: string;
|
|
wasClean: boolean;
|
|
}
|
|
|
|
/** Payload for connection-level failures (as opposed to a server `error` event). */
|
|
export interface TransportError {
|
|
error: Error;
|
|
event?: unknown;
|
|
fatal: boolean;
|
|
}
|
|
|
|
export interface AudioAgentClientOptions {
|
|
/** Full `ws://`/`wss://` URL; wins over `baseUrl`. */
|
|
url?: string;
|
|
/** Engine origin, e.g. `http://localhost:8787`; `/ws` is appended. */
|
|
baseUrl?: string;
|
|
/** Path appended to `baseUrl` (default `/ws`). */
|
|
path?: string;
|
|
/** Reconnect automatically after an unexpected close (default `false`). */
|
|
autoReconnect?: boolean;
|
|
reconnectMinDelayMs?: number;
|
|
reconnectMaxDelayMs?: number;
|
|
/** WebSocket implementation to use (required on Node < 22, e.g. the `ws` package). */
|
|
WebSocket?: typeof WebSocket;
|
|
}
|
|
|
|
export type ConnectionState = 'idle' | 'connecting' | 'open' | 'closed';
|
|
|
|
export class AudioAgentClient {
|
|
constructor(options?: AudioAgentClientOptions);
|
|
readonly url: string;
|
|
autoReconnect: boolean;
|
|
reconnectMinDelayMs: number;
|
|
reconnectMaxDelayMs: number;
|
|
readonly state: ConnectionState;
|
|
readonly connected: boolean;
|
|
|
|
connect(): Promise<this>;
|
|
close(code?: number, reason?: string): void;
|
|
|
|
sendAudio(chunk: AudioChunk): boolean;
|
|
sendText(text: string): boolean;
|
|
sendControl(message: Record<string, unknown>): boolean;
|
|
sendUserText(text: string): boolean;
|
|
interrupt(): boolean;
|
|
playAudioSource(url: string): boolean;
|
|
stopAudioSource(): boolean;
|
|
setAudioSourceVolume(gain: number): boolean;
|
|
setReference(path: string, text?: string): boolean;
|
|
clearReference(): boolean;
|
|
speak(text: string): boolean;
|
|
|
|
on(type: 'audio', handler: (frame: AudioFrame) => void): () => void;
|
|
on(type: 'open', handler: (info: { url: string }) => void): () => void;
|
|
on(type: 'close', handler: (info: CloseEvent) => void): () => void;
|
|
on(type: 'state', handler: (state: ConnectionState) => void): () => void;
|
|
on(
|
|
type: 'reconnecting',
|
|
handler: (info: { attempt: number; delay: number }) => void,
|
|
): () => void;
|
|
on(type: 'error', handler: (payload: TransportError | ErrorEvent) => void): () => void;
|
|
on(type: 'event' | 'unknown', handler: (event: ServerEvent) => void): () => void;
|
|
on(type: string, handler: (payload: any) => void): () => void;
|
|
|
|
once(type: string, handler: (payload: any) => void): () => void;
|
|
off(type: string, handler: (payload: any) => void): void;
|
|
emit(type: string, payload?: unknown): void;
|
|
}
|
|
|
|
export interface AudioAgentRestOptions {
|
|
fetch?: typeof fetch;
|
|
headers?: Record<string, string>;
|
|
}
|
|
|
|
export interface ToolsResponse {
|
|
ok: boolean;
|
|
count: number;
|
|
source: 'file' | 'request' | 'none';
|
|
tools: object[];
|
|
}
|
|
|
|
export interface PhrasesResponse {
|
|
default: string;
|
|
languages: Array<{ code: string; label: string; phrase: string }>;
|
|
}
|
|
|
|
export interface SetVoiceResponse {
|
|
ok: boolean;
|
|
lang: string;
|
|
audio: string;
|
|
phrase: string;
|
|
}
|
|
|
|
export interface TranscribeResponse {
|
|
ok: boolean;
|
|
text: string;
|
|
duration_ms: number;
|
|
tokens: number;
|
|
}
|
|
|
|
/** Where the effective system prompt comes from (decreasing precedence). */
|
|
export type PromptSource = 'session' | 'global' | 'env' | 'default' | 'none';
|
|
|
|
/** Response of `GET`/`POST /api/prompt`. */
|
|
export interface PromptResponse {
|
|
ok: boolean;
|
|
session_id: string | null;
|
|
source: PromptSource;
|
|
prompt: string;
|
|
has_override: boolean;
|
|
direct_answers_applied: boolean;
|
|
}
|
|
|
|
/** Response of `POST /api/auth/phone-login` (upstream AquaChile payload). */
|
|
export interface PhoneLoginResponse {
|
|
sessionToken?: string;
|
|
user?: Record<string, any>;
|
|
[key: string]: any;
|
|
}
|
|
|
|
/** Error thrown by {@link AudioAgentRest}, carrying the HTTP status and body. */
|
|
export interface RestError extends Error {
|
|
status: number;
|
|
body: unknown;
|
|
}
|
|
|
|
export class AudioAgentRest {
|
|
constructor(baseUrl: string, options?: AudioAgentRestOptions);
|
|
readonly baseUrl: string;
|
|
|
|
health(): Promise<string>;
|
|
getTools(): Promise<ToolsResponse>;
|
|
setTools(tools: object[]): Promise<ToolsResponse>;
|
|
getPrompt(sessionId?: string): Promise<PromptResponse>;
|
|
setPrompt(prompt: string | null, sessionId?: string | null): Promise<PromptResponse>;
|
|
phoneLogin(phoneNumber: string, sessionId?: string | null): Promise<PhoneLoginResponse>;
|
|
getCustomVoicePhrases(): Promise<PhrasesResponse>;
|
|
setCustomVoice(
|
|
lang: string,
|
|
audio: Blob | ArrayBuffer | ArrayBufferView,
|
|
text?: string,
|
|
): Promise<SetVoiceResponse>;
|
|
clearCustomVoice(): Promise<{ ok: boolean }>;
|
|
transcribe(audio: Blob | ArrayBuffer | ArrayBufferView): Promise<TranscribeResponse>;
|
|
openapi(): Promise<object>;
|
|
}
|
|
|
|
export interface MicCaptureOptions {
|
|
sampleRate?: number;
|
|
frameSamples?: number;
|
|
constraints?: MediaStreamConstraints;
|
|
}
|
|
|
|
export class MicCapture {
|
|
constructor(options?: MicCaptureOptions);
|
|
readonly sampleRate: number;
|
|
readonly frameSamples: number;
|
|
readonly contextSampleRate: number | null;
|
|
start(): Promise<void>;
|
|
stop(): void;
|
|
on(type: 'frame', handler: (samples: Int16Array) => void): () => void;
|
|
on(type: 'start', handler: (info: { sampleRate: number }) => void): () => void;
|
|
on(type: 'stop', handler: () => void): () => void;
|
|
on(type: string, handler: (payload: any) => void): () => void;
|
|
once(type: string, handler: (payload: any) => void): () => void;
|
|
off(type: string, handler: (payload: any) => void): void;
|
|
}
|
|
|
|
export interface PcmPlayerOptions {
|
|
sampleRate?: number;
|
|
bufferMs?: number;
|
|
gain?: number;
|
|
}
|
|
|
|
export class PcmPlayer {
|
|
constructor(options?: PcmPlayerOptions);
|
|
readonly sampleRate: number;
|
|
bufferMs: number;
|
|
gain: number;
|
|
resume(): Promise<void>;
|
|
push(chunk: AudioChunk): void;
|
|
setGain(value: number): void;
|
|
flush(): void;
|
|
close(): void;
|
|
isIdle(): boolean;
|
|
on(type: 'chunk', handler: (info: { startAt: number; samples: number }) => void): () => void;
|
|
on(type: 'flush', handler: () => void): () => void;
|
|
on(type: 'idle', handler: () => void): () => void;
|
|
on(type: string, handler: (payload: any) => void): () => void;
|
|
once(type: string, handler: (payload: any) => void): () => void;
|
|
off(type: string, handler: (payload: any) => void): void;
|
|
}
|
|
|
|
export interface AudioSessionOptions extends AudioAgentClientOptions {
|
|
client?: AudioAgentClient;
|
|
player?: PcmPlayer;
|
|
/** Playback jitter buffer in ms (default 150). */
|
|
bufferMs?: number;
|
|
/** Stream the microphone automatically (default `true`). */
|
|
forwardMic?: boolean;
|
|
}
|
|
|
|
export class AudioSession {
|
|
constructor(options?: AudioSessionOptions);
|
|
readonly client: AudioAgentClient;
|
|
readonly player: PcmPlayer;
|
|
readonly mic: MicCapture | null;
|
|
forwardMic: boolean;
|
|
|
|
start(options?: { microphone?: boolean }): Promise<void>;
|
|
stop(): Promise<void>;
|
|
sendUserText(text: string): boolean;
|
|
interrupt(): boolean;
|
|
|
|
on(type: 'audio' | 'session' | 'assistant_delta' | 'assistant_markdown' | 'cues' | 'user' | 'cue' | 'barge_in'
|
|
| 'tool_call' | 'audio_source' | 'error' | 'assistant_end' | 'open' | 'close'
|
|
| 'state' | 'reconnecting' | string, handler: (payload: any) => void): () => void;
|
|
once(type: string, handler: (payload: any) => void): () => void;
|
|
off(type: string, handler: (payload: any) => void): void;
|
|
emit(type: string, payload?: unknown): void;
|
|
}
|
|
|
|
declare const _default: {
|
|
AUDIO: AudioFormat;
|
|
CLIENT_EVENTS: readonly string[];
|
|
int16ArrayFromBytes: typeof int16ArrayFromBytes;
|
|
float32ToInt16: typeof float32ToInt16;
|
|
int16ToFloat32: typeof int16ToFloat32;
|
|
toInt16: typeof toInt16;
|
|
AudioAgentClient: typeof AudioAgentClient;
|
|
AudioAgentRest: typeof AudioAgentRest;
|
|
MicCapture: typeof MicCapture;
|
|
PcmPlayer: typeof PcmPlayer;
|
|
AudioSession: typeof AudioSession;
|
|
};
|
|
export default _default;
|