@upliftai/sdk-js 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Official Node.js SDK for the [UpliftAI](https://upliftai.org) API. Build Urdu voice agents, add text-to-speech to WhatsApp bots, or transcribe call center audio.
4
4
 
5
- [Documentation](https://docs.upliftai.org) · [Voices](https://docs.upliftai.org/orator_voices) · [API Reference](https://docs.upliftai.org/api-reference)
5
+ [Documentation](https://docs.upliftai.org) · [Voices](https://docs.upliftai.org/orator_voices) · [API Reference](https://docs.upliftai.org/introduction)
6
6
 
7
7
  ## Install
8
8
 
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var UpliftAIRateLimitError = class extends UpliftAIError {
69
69
  };
70
70
 
71
71
  // src/http.ts
72
- var SDK_VERSION = "0.1.0";
72
+ var SDK_VERSION = "0.1.1";
73
73
  var DEFAULT_TIMEOUT = 3e4;
74
74
  var DEFAULT_MAX_RETRIES = 2;
75
75
  var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/tts.ts","../src/phrase-replacements.ts","../src/ws.ts","../src/stt.ts","../src/client.ts"],"sourcesContent":["import { UpliftAI } from './client';\n\nexport { UpliftAI } from './client';\nexport { UpliftAIError, UpliftAIAuthError, UpliftAIInsufficientBalanceError, UpliftAIRateLimitError } from './errors';\nexport type {\n UpliftAIOptions,\n OutputFormat,\n TTSRequest,\n AudioMetadata,\n AudioResponse,\n StreamResponse,\n EnqueueResponse,\n WSAudioStart,\n WSAudio,\n WSAudioEnd,\n WSError,\n TTSStreamEvent,\n TranscriptionRequest,\n TranscriptionRequestFromPath,\n TranscriptionRequestFromBuffer,\n TranscriptionResponse,\n PhraseReplacement,\n PhraseReplacementConfig,\n TTSStream,\n TTSWebSocket,\n WSReadyState,\n} from './types';\n\nexport default UpliftAI;\n","export class UpliftAIError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly code?: string,\n public readonly requestId?: string,\n ) {\n super(message);\n this.name = 'UpliftAIError';\n }\n}\n\nexport class UpliftAIAuthError extends UpliftAIError {\n constructor(message = 'Authentication failed. Check your API key.', requestId?: string) {\n super(message, 401, 'auth_error', requestId);\n this.name = 'UpliftAIAuthError';\n }\n}\n\nexport class UpliftAIInsufficientBalanceError extends UpliftAIError {\n constructor(message = 'Insufficient balance. Please add credits to your account.', requestId?: string) {\n super(message, 402, 'insufficient_balance', requestId);\n this.name = 'UpliftAIInsufficientBalanceError';\n }\n}\n\nexport class UpliftAIRateLimitError extends UpliftAIError {\n constructor(message = 'Rate limit exceeded.', requestId?: string) {\n super(message, 429, 'rate_limited', requestId);\n this.name = 'UpliftAIRateLimitError';\n }\n}\n","import { UpliftAIAuthError, UpliftAIError, UpliftAIInsufficientBalanceError, UpliftAIRateLimitError } from './errors';\n\nconst SDK_VERSION = '0.1.0';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n\nexport interface HttpClientOptions {\n baseUrl: string;\n apiKey: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class HttpClient {\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n private maxRetries: number;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\n this.apiKey = options.apiKey;\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n }\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n Authorization: `Bearer ${this.apiKey}`,\n 'User-Agent': `upliftai-js/${SDK_VERSION}`,\n Connection: 'keep-alive',\n ...extra,\n };\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, retriesLeft = this.maxRetries): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, { ...init, signal: controller.signal });\n\n if (!res.ok && retriesLeft > 0 && RETRYABLE_STATUS_CODES.has(res.status)) {\n const delay = this.retryDelay(this.maxRetries - retriesLeft);\n await sleep(delay);\n return this.fetchWithRetry(url, init, retriesLeft - 1);\n }\n\n return res;\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw new UpliftAIError('Request timed out', undefined, 'timeout');\n }\n if (retriesLeft > 0) {\n const delay = this.retryDelay(this.maxRetries - retriesLeft);\n await sleep(delay);\n return this.fetchWithRetry(url, init, retriesLeft - 1);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private retryDelay(attempt: number): number {\n const base = Math.min(500 * Math.pow(2, attempt), 5000);\n const jitter = base * 0.25 * Math.random();\n return base + jitter;\n }\n\n async postJSON<T>(path: string, body: Record<string, unknown>): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async postJSONForBuffer(path: string, body: Record<string, unknown>): Promise<{ buffer: Buffer; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const buffer = Buffer.from(await res.arrayBuffer());\n return { buffer, headers: res.headers };\n }\n\n async postJSONForStream(path: string, body: Record<string, unknown>): Promise<{ body: ReadableStream<Uint8Array>; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n if (!res.body) {\n throw new UpliftAIError('Response body is null');\n }\n\n return { body: res.body, headers: res.headers };\n }\n\n async postMultipart<T>(path: string, formData: FormData): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers(),\n body: formData,\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async get<T>(path: string): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'GET',\n headers: this.headers(),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async getStream(path: string, query?: Record<string, string>): Promise<{ body: ReadableStream<Uint8Array>; headers: Headers }> {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n url.searchParams.set(k, v);\n }\n }\n\n const res = await this.fetchWithRetry(url.toString(), {\n method: 'GET',\n headers: this.headers(),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n if (!res.body) {\n throw new UpliftAIError('Response body is null');\n }\n\n return { body: res.body, headers: res.headers };\n }\n\n private async throwForStatus(res: Response): Promise<never> {\n const requestId = res.headers.get('x-uplift-ai-request-id') ?? undefined;\n const body = await this.safeText(res);\n if (res.status === 401) throw new UpliftAIAuthError(undefined, requestId);\n if (res.status === 402) throw new UpliftAIInsufficientBalanceError(undefined, requestId);\n if (res.status === 429) throw new UpliftAIRateLimitError(undefined, requestId);\n throw new UpliftAIError(`HTTP ${res.status}: ${body}`, res.status, undefined, requestId);\n }\n\n private async safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return '';\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { Readable } from 'node:stream';\nimport { HttpClient } from './http';\nimport { PhraseReplacements } from './phrase-replacements';\nimport { TTSWebSocketImpl } from './ws';\nimport type {\n TTSRequest,\n AudioResponse,\n AudioMetadata,\n EnqueueResponse,\n StreamResponse,\n TTSWebSocket,\n} from './types';\n\nconst DEFAULT_OUTPUT_FORMAT = 'WAV_22050_32';\n\nfunction buildTTSBody(request: TTSRequest): Record<string, unknown> {\n const body: Record<string, unknown> = {\n text: request.text,\n voiceId: request.voiceId,\n outputFormat: request.outputFormat ?? DEFAULT_OUTPUT_FORMAT,\n };\n if (request.phraseReplacementConfigId) body.phraseReplacementConfigId = request.phraseReplacementConfigId;\n return body;\n}\n\nfunction parseAudioMetadata(headers: Headers): AudioMetadata {\n return {\n requestId: headers.get('x-uplift-ai-request-id') ?? '',\n duration: Number(headers.get('x-uplift-ai-audio-duration') ?? 0),\n contentType: headers.get('content-type') ?? 'application/octet-stream',\n sampleRate: Number(headers.get('x-uplift-ai-sample-rate') ?? 0),\n bitRate: Number(headers.get('x-uplift-ai-bit-rate') ?? 0),\n };\n}\n\nfunction readableFromWeb(webStream: ReadableStream<Uint8Array>): Readable {\n const reader = webStream.getReader();\n return new Readable({\n async read() {\n const { done, value } = await reader.read();\n if (done) {\n this.push(null);\n } else {\n this.push(Buffer.from(value));\n }\n },\n destroy(_err, callback) {\n reader.cancel().then(() => callback(null), callback);\n },\n });\n}\n\n/** Text-to-speech resource. Access via `client.tts`. */\nexport class TTS {\n private http: HttpClient;\n private apiKey: string;\n private baseUrl: string;\n private wsBaseUrl: string;\n\n /** Manage phrase replacement configs for pronunciation control. */\n readonly phraseReplacements: PhraseReplacements;\n\n constructor(http: HttpClient, apiKey: string, baseUrl: string, wsBaseUrl: string) {\n this.http = http;\n this.apiKey = apiKey;\n this.baseUrl = baseUrl;\n this.wsBaseUrl = wsBaseUrl;\n this.phraseReplacements = new PhraseReplacements(http);\n }\n\n /**\n * Synthesize text and return the full audio buffer.\n *\n * Generates the complete audio before returning. Faster end-to-end than\n * streaming, but the caller must wait for the entire file. Best for\n * batch/offline use cases where latency to first byte doesn't matter.\n *\n * @example\n * const { audio, metadata } = await client.tts.create({ text: 'سلام', voiceId: 'v_meklc281' });\n * fs.writeFileSync('output.mp3', audio);\n */\n async create(request: TTSRequest): Promise<AudioResponse> {\n const { buffer, headers } = await this.http.postJSONForBuffer(\n '/v1/synthesis/text-to-speech',\n buildTTSBody(request),\n );\n return {\n audio: buffer,\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Synthesize text and return a readable stream of audio chunks.\n *\n * The first chunk arrives quickly, but total generation is slower than\n * `create()`. Use this in latency-sensitive environments like live agents,\n * phone calls, or real-time playback where you want audio to start playing\n * immediately rather than waiting for the full file.\n *\n * @example\n * const { stream, metadata } = await client.tts.createStream({ text: 'سلام', voiceId: 'v_meklc281' });\n * for await (const chunk of stream) speaker.write(chunk);\n */\n async createStream(request: TTSRequest): Promise<StreamResponse> {\n const { body, headers } = await this.http.postJSONForStream(\n '/v1/synthesis/text-to-speech/stream',\n buildTTSBody(request),\n );\n return {\n stream: readableFromWeb(body),\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Enqueue an async TTS job. Returns a `mediaId` to retrieve the audio later.\n *\n * Use for batch processing or when you don't need audio immediately.\n * Poll or call `retrieve(mediaId)` when the audio is ready.\n *\n * @example\n * const { mediaId, temporaryUrl } = await client.tts.enqueue({ text: 'سلام', voiceId: 'v_meklc281' });\n * // retrieve server-side\n * const audio = await client.tts.retrieve(mediaId);\n * // or pass URL directly to a client/browser\n * console.log(temporaryUrl);\n */\n async enqueue(request: TTSRequest): Promise<EnqueueResponse> {\n const { data } = await this.http.postJSON<{ mediaId: string; token: string }>(\n '/v1/synthesis/text-to-speech-async',\n buildTTSBody(request),\n );\n return {\n ...data,\n temporaryUrl: this.buildTemporaryUrl(data.mediaId, data.token),\n };\n }\n\n /**\n * Enqueue an async TTS job with streaming retrieval.\n *\n * Same as `enqueue()`, but when retrieved via `retrieve(mediaId)` the audio\n * streams in chunks instead of arriving as a single buffer.\n *\n * @example\n * const { mediaId, temporaryUrl } = await client.tts.enqueueStream({ text: 'سلام', voiceId: 'v_meklc281' });\n * const stream = await client.tts.retrieve(mediaId);\n * for await (const chunk of stream) speaker.write(chunk);\n */\n async enqueueStream(request: TTSRequest): Promise<EnqueueResponse> {\n const { data } = await this.http.postJSON<{ mediaId: string; token: string }>(\n '/v1/synthesis/text-to-speech/stream-async',\n buildTTSBody(request),\n );\n return {\n ...data,\n temporaryUrl: this.buildTemporaryUrl(data.mediaId, data.token),\n };\n }\n\n /**\n * Retrieve audio from a previously enqueued job.\n *\n * Returns the audio stream along with metadata (encoding, sample rate, etc.)\n * from response headers.\n *\n * @example\n * const { stream, metadata } = await client.tts.retrieve('<mediaId from enqueue>');\n * console.log(metadata.contentType); // 'audio/mpeg'\n * for await (const chunk of stream) fs.appendFileSync('out.mp3', chunk);\n */\n async retrieve(mediaId: string): Promise<StreamResponse> {\n const { body, headers } = await this.http.getStream(`/v1/synthesis/stream-audio/${mediaId}`);\n return {\n stream: readableFromWeb(body),\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Open a persistent WebSocket connection for low-latency streaming TTS.\n *\n * Supports multiple concurrent streams on one connection, multiplexed by\n * requestId. Use for real-time conversational AI, live agents, and\n * interactive use cases. Resolves once the connection is ready.\n *\n * Open one connection per conversation or user session — don't share across\n * unrelated contexts.\n *\n * @example\n * const ws = await client.tts.connect();\n * // Stream sentence-by-sentence as your LLM generates\n * for await (const sentence of llm.streamSentences(prompt)) {\n * const stream = ws.stream({ text: sentence, voiceId: 'v_meklc281' });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n * }\n * ws.close();\n */\n private buildTemporaryUrl(mediaId: string, token: string): string {\n return `${this.baseUrl}/v1/synthesis/stream-audio/${mediaId}?token=${encodeURIComponent(token)}`;\n }\n\n async connect(): Promise<TTSWebSocket> {\n const wsUrl = `${this.wsBaseUrl}/v1/text-to-speech/multi-stream`;\n const ws = new TTSWebSocketImpl(wsUrl, this.apiKey);\n await ws.waitForReady();\n return ws;\n }\n}\n","import { HttpClient } from './http';\nimport type { PhraseReplacement, PhraseReplacementConfig } from './types';\n\nexport class PhraseReplacements {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n async create(replacements: PhraseReplacement[]): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.postJSON<PhraseReplacementConfig>(\n '/v1/synthesis/phrase-replacement-config',\n { phraseReplacements: replacements },\n );\n return data;\n }\n\n async get(configId: string): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.get<PhraseReplacementConfig>(\n `/v1/synthesis/phrase-replacement-config/${configId}`,\n );\n return data;\n }\n\n async list(): Promise<PhraseReplacementConfig[]> {\n const { data } = await this.http.get<PhraseReplacementConfig[]>(\n '/v1/synthesis/phrase-replacement-config',\n );\n return data;\n }\n\n async update(configId: string, replacements: PhraseReplacement[]): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.postJSON<PhraseReplacementConfig>(\n `/v1/synthesis/phrase-replacement-config/${configId}`,\n { phraseReplacements: replacements },\n );\n return data;\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport WebSocket from 'ws';\nimport type {\n TTSRequest,\n TTSStream,\n TTSStreamEvent,\n TTSWebSocket,\n WSReadyState,\n} from './types';\nimport { UpliftAIError } from './errors';\n\ninterface PendingStream {\n push(event: TTSStreamEvent): void;\n end(): void;\n error(err: Error): void;\n}\n\n/**\n * WebSocket-based TTS client. Supports multiple concurrent streams on a\n * single connection, multiplexed by requestId.\n *\n * Scope one connection per conversation or user session. Don't share a\n * single connection across unrelated contexts — we may leverage\n * connection-level state for prosody continuity in the future.\n *\n * Created via `client.tts.connect()` — do not instantiate directly.\n */\nexport class TTSWebSocketImpl implements TTSWebSocket {\n private ws: WebSocket;\n private _sessionId = '';\n private streams = new Map<string, PendingStream>();\n private readyPromise: Promise<void>;\n private readyResolve!: () => void;\n private readyReject!: (err: Error) => void;\n private listeners: { error: ((error: Error) => void)[]; close: ((code: number, reason: string) => void)[] } = {\n error: [],\n close: [],\n };\n\n constructor(url: string, apiKey: string) {\n this.readyPromise = new Promise<void>((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n\n this.ws = new WebSocket(url, {\n headers: { Authorization: `Bearer ${apiKey}` },\n });\n\n this.ws.on('message', (raw: WebSocket.Data) => {\n this.handleMessage(raw);\n });\n\n this.ws.on('error', (err: Error) => {\n this.readyReject(err);\n for (const listener of this.listeners.error) {\n try { listener(err); } catch (e) { process.emitWarning(`Error in listener callback: ${e}`, 'UpliftAI'); }\n }\n for (const stream of this.streams.values()) stream.error(err);\n });\n\n this.ws.on('close', (code: number, reason: Buffer) => {\n const reasonStr = reason.toString();\n for (const listener of this.listeners.close) {\n try { listener(code, reasonStr); } catch (e) { process.emitWarning(`Error in listener callback: ${e}`, 'UpliftAI'); }\n }\n for (const stream of this.streams.values()) {\n stream.error(new UpliftAIError(`WebSocket closed: ${code} ${reasonStr}`));\n }\n this.streams.clear();\n });\n }\n\n /** @internal Wait for the server `ready` message. Called by `tts.connect()`. */\n async waitForReady(): Promise<void> {\n return this.readyPromise;\n }\n\n /** Current connection state. */\n get readyState(): WSReadyState {\n switch (this.ws.readyState) {\n case WebSocket.CONNECTING: return 'connecting';\n case WebSocket.OPEN: return 'open';\n case WebSocket.CLOSING: return 'closing';\n case WebSocket.CLOSED: return 'closed';\n default: return 'closed';\n }\n }\n\n /** Server-assigned session ID, available after connection is ready. */\n get sessionId(): string {\n return this._sessionId;\n }\n\n /** Register a listener for connection-level events. */\n on(event: 'error', listener: (error: Error) => void): this;\n on(event: 'close', listener: (code: number, reason: string) => void): this;\n on(event: 'error' | 'close', listener: ((error: Error) => void) | ((code: number, reason: string) => void)): this {\n if (event === 'error') {\n this.listeners.error.push(listener as (error: Error) => void);\n } else {\n this.listeners.close.push(listener as (code: number, reason: string) => void);\n }\n return this;\n }\n\n /**\n * Start a TTS stream. Sends text to the server and returns an async iterable\n * of audio events (`audio_start`, `audio`, `audio_end`, `error`).\n *\n * Multiple streams can run concurrently on the same connection — each is\n * demuxed by its `requestId`. For real-time conversational AI, break your\n * LLM output into sentence-sized chunks and stream each one as it arrives.\n * This gives the lowest time-to-first-audio since synthesis starts before\n * the LLM finishes generating. If you use LiveKit, the UpliftAI plugin\n * handles this sentence segmentation automatically.\n *\n * **Connection scope:** Use one WebSocket per conversation / user session.\n * Don't multiplex unrelated use cases on a single connection — we may use\n * connection-level context for prosody and other improvements in the future.\n *\n * @example // Simple usage\n * const stream = ws.stream({ text: 'سلام', voiceId: 'v_meklc281' });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n *\n * @example // Real-time: stream sentence-by-sentence as LLM generates\n * for await (const sentence of llm.streamSentences(prompt)) {\n * const stream = ws.stream({ text: sentence, voiceId });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n * }\n *\n * @example // Overlap: fire next sentence before previous finishes\n * const sentences = ['پہلا جملہ۔', 'دوسرا جملہ۔', 'تیسرا جملہ۔'];\n * for (const sentence of sentences) {\n * const stream = ws.stream({ text: sentence, voiceId });\n * consume(stream); // don't await — let them overlap\n * }\n */\n stream(request: TTSRequest & { requestId?: string }): TTSStream {\n const requestId = request.requestId ?? randomUUID();\n\n const buffer: TTSStreamEvent[] = [];\n let resolve: ((value: IteratorResult<TTSStreamEvent>) => void) | null = null;\n let done = false;\n let error: Error | null = null;\n\n const cleanup = () => {\n this.streams.delete(requestId);\n buffer.length = 0;\n resolve = null;\n };\n\n const pending: PendingStream = {\n push(event: TTSStreamEvent) {\n if (done) return;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: event, done: false });\n } else {\n buffer.push(event);\n }\n },\n end() {\n if (done) return;\n done = true;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n },\n error(err: Error) {\n if (done) return;\n error = err;\n done = true;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n },\n };\n\n this.streams.set(requestId, pending);\n\n this.safeSend({\n type: 'synthesize',\n requestId,\n text: request.text,\n voiceId: request.voiceId,\n outputFormat: request.outputFormat ?? 'PCM_22050_16',\n });\n\n const iterator: AsyncIterableIterator<TTSStreamEvent> = {\n next(): Promise<IteratorResult<TTSStreamEvent>> {\n if (error || done) {\n if (buffer.length > 0) {\n return Promise.resolve({ value: buffer.shift()!, done: false });\n }\n cleanup();\n return Promise.resolve({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n if (buffer.length > 0) {\n return Promise.resolve({ value: buffer.shift()!, done: false });\n }\n return new Promise<IteratorResult<TTSStreamEvent>>((r) => {\n resolve = r;\n });\n },\n return(): Promise<IteratorResult<TTSStreamEvent>> {\n done = true;\n cleanup();\n return Promise.resolve({ value: undefined as unknown as TTSStreamEvent, done: true });\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n\n const stream: TTSStream = {\n requestId,\n /** Cancel this stream. Tells the server to stop generating and ends the iterator. */\n cancel: async () => {\n this.safeSend({ type: 'cancel', requestId });\n cleanup();\n pending.end();\n },\n [Symbol.asyncIterator]() {\n return iterator;\n },\n };\n\n return stream;\n }\n\n /**\n * Cancel all in-flight streams. Use for barge-in / interruption — when the\n * user starts speaking and you need to immediately stop all TTS playback.\n *\n * Sends a cancel message to the server for each active stream and ends\n * all iterators synchronously.\n *\n * @example\n * ws.stream({ text: 'sentence 1...', voiceId });\n * ws.stream({ text: 'sentence 2...', voiceId });\n * // User interrupts!\n * ws.cancelAll(); // both streams end immediately\n */\n cancelAll(): void {\n for (const [requestId, stream] of this.streams) {\n this.safeSend({ type: 'cancel', requestId });\n stream.end();\n }\n this.streams.clear();\n }\n\n /** Number of streams currently in-flight on this connection. */\n get activeStreams(): number {\n return this.streams.size;\n }\n\n /** Close the WebSocket connection. */\n close(): void {\n this.ws.close();\n }\n\n private safeSend(msg: Record<string, unknown>): void {\n try {\n this.ws.send(JSON.stringify(msg));\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n for (const stream of this.streams.values()) {\n stream.error(new UpliftAIError(`WebSocket send failed: ${error.message}`));\n }\n }\n }\n\n private handleMessage(raw: WebSocket.Data): void {\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n const type = msg.type as string;\n\n if (type === 'ready') {\n this._sessionId = msg.sessionId as string;\n this.readyResolve();\n return;\n }\n\n const requestId = msg.requestId as string;\n if (!requestId) return;\n\n const stream = this.streams.get(requestId);\n if (!stream) return;\n\n switch (type) {\n case 'audio_start':\n stream.push({\n type: 'audio_start',\n requestId,\n timestamp: msg.timestamp as number,\n });\n break;\n\n case 'audio': {\n let audio: Buffer;\n try {\n audio = Buffer.from(msg.audio as string, 'base64');\n } catch {\n stream.push({\n type: 'error',\n requestId,\n code: 'decode_error',\n message: 'Failed to decode base64 audio data',\n });\n stream.end();\n this.streams.delete(requestId);\n return;\n }\n stream.push({\n type: 'audio',\n requestId,\n sequence: msg.sequence as number,\n audio,\n });\n break;\n }\n\n case 'audio_end':\n stream.push({\n type: 'audio_end',\n requestId,\n timestamp: msg.timestamp as number,\n });\n stream.end();\n this.streams.delete(requestId);\n break;\n\n case 'error':\n stream.push({\n type: 'error',\n requestId,\n code: msg.code as string,\n message: msg.message as string,\n });\n stream.end();\n this.streams.delete(requestId);\n break;\n }\n }\n}\n","import { Readable } from 'node:stream';\nimport { createReadStream } from 'node:fs';\nimport { basename } from 'node:path';\nimport { HttpClient } from './http';\nimport { UpliftAIError } from './errors';\nimport type { TranscriptionRequest, TranscriptionResponse } from './types';\n\nasync function streamToBuffer(stream: NodeJS.ReadableStream | Readable): Promise<Buffer> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (Buffer.isBuffer(chunk)) {\n chunks.push(chunk);\n } else if (chunk instanceof Uint8Array) {\n chunks.push(Buffer.from(chunk));\n } else if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n throw new UpliftAIError('Unexpected chunk type in audio stream');\n }\n }\n return Buffer.concat(chunks);\n}\n\n/** Speech-to-text resource. Access via `client.stt`. */\nexport class STT {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n /**\n * Transcribe audio to text.\n *\n * Accepts a file path, Buffer, or readable stream as input.\n *\n * @example\n * // From file path (extension used for content-type detection)\n * const { transcript } = await client.stt.transcribe({ file: './call.mp3', model: 'scribe' });\n *\n * // From Buffer (pass fileName so the server knows the format)\n * const { transcript } = await client.stt.transcribe({ file: audioBuffer, fileName: 'call.mp3', language: 'ur' });\n */\n async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {\n const formData = new FormData();\n\n if (typeof request.file === 'string') {\n const stream = createReadStream(request.file);\n const buffer = await streamToBuffer(stream);\n formData.append('file', new Blob([buffer]), basename(request.file));\n } else if (Buffer.isBuffer(request.file)) {\n formData.append('file', new Blob([request.file]), request.fileName);\n } else {\n const buffer = await streamToBuffer(request.file as Readable);\n formData.append('file', new Blob([buffer]), request.fileName);\n }\n\n if (request.model) formData.append('model', request.model);\n if (request.language) formData.append('language', request.language);\n if (request.domain) formData.append('domain', request.domain);\n\n const { data } = await this.http.postMultipart<TranscriptionResponse>(\n '/v1/transcribe/speech-to-text',\n formData,\n );\n\n return data;\n }\n}\n","import { HttpClient } from './http';\nimport { TTS } from './tts';\nimport { STT } from './stt';\nimport { UpliftAIError } from './errors';\nimport type { UpliftAIOptions } from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.upliftai.org';\n\nexport class UpliftAI {\n readonly tts: TTS;\n readonly stt: STT;\n\n constructor(options: UpliftAIOptions = {}) {\n const apiKey = options.apiKey ?? process.env.UPLIFTAI_API_KEY;\n if (!apiKey) {\n throw new UpliftAIError(\n 'apiKey is required. Pass it in options or set the UPLIFTAI_API_KEY environment variable.',\n undefined,\n 'invalid_config',\n );\n }\n\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n const http = new HttpClient({\n baseUrl,\n apiKey,\n timeout: options.timeout,\n maxRetries: options.maxRetries,\n });\n\n const wsBaseUrl = baseUrl.replace(/^http/, 'ws').replace(/^https/, 'wss');\n\n this.tts = new TTS(http, apiKey, baseUrl, wsBaseUrl);\n this.stt = new STT(http);\n }\n}\n"],"mappings":"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","names":["WebSocket"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/tts.ts","../src/phrase-replacements.ts","../src/ws.ts","../src/stt.ts","../src/client.ts"],"sourcesContent":["import { UpliftAI } from './client';\n\nexport { UpliftAI } from './client';\nexport { UpliftAIError, UpliftAIAuthError, UpliftAIInsufficientBalanceError, UpliftAIRateLimitError } from './errors';\nexport type {\n UpliftAIOptions,\n OutputFormat,\n TTSRequest,\n AudioMetadata,\n AudioResponse,\n StreamResponse,\n EnqueueResponse,\n WSAudioStart,\n WSAudio,\n WSAudioEnd,\n WSError,\n TTSStreamEvent,\n TranscriptionRequest,\n TranscriptionRequestFromPath,\n TranscriptionRequestFromBuffer,\n TranscriptionResponse,\n PhraseReplacement,\n PhraseReplacementConfig,\n TTSStream,\n TTSWebSocket,\n WSReadyState,\n} from './types';\n\nexport default UpliftAI;\n","export class UpliftAIError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly code?: string,\n public readonly requestId?: string,\n ) {\n super(message);\n this.name = 'UpliftAIError';\n }\n}\n\nexport class UpliftAIAuthError extends UpliftAIError {\n constructor(message = 'Authentication failed. Check your API key.', requestId?: string) {\n super(message, 401, 'auth_error', requestId);\n this.name = 'UpliftAIAuthError';\n }\n}\n\nexport class UpliftAIInsufficientBalanceError extends UpliftAIError {\n constructor(message = 'Insufficient balance. Please add credits to your account.', requestId?: string) {\n super(message, 402, 'insufficient_balance', requestId);\n this.name = 'UpliftAIInsufficientBalanceError';\n }\n}\n\nexport class UpliftAIRateLimitError extends UpliftAIError {\n constructor(message = 'Rate limit exceeded.', requestId?: string) {\n super(message, 429, 'rate_limited', requestId);\n this.name = 'UpliftAIRateLimitError';\n }\n}\n","import { UpliftAIAuthError, UpliftAIError, UpliftAIInsufficientBalanceError, UpliftAIRateLimitError } from './errors';\n\nconst SDK_VERSION = '0.1.1';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n\nexport interface HttpClientOptions {\n baseUrl: string;\n apiKey: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class HttpClient {\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n private maxRetries: number;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\n this.apiKey = options.apiKey;\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n }\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n Authorization: `Bearer ${this.apiKey}`,\n 'User-Agent': `upliftai-js/${SDK_VERSION}`,\n Connection: 'keep-alive',\n ...extra,\n };\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, retriesLeft = this.maxRetries): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, { ...init, signal: controller.signal });\n\n if (!res.ok && retriesLeft > 0 && RETRYABLE_STATUS_CODES.has(res.status)) {\n const delay = this.retryDelay(this.maxRetries - retriesLeft);\n await sleep(delay);\n return this.fetchWithRetry(url, init, retriesLeft - 1);\n }\n\n return res;\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw new UpliftAIError('Request timed out', undefined, 'timeout');\n }\n if (retriesLeft > 0) {\n const delay = this.retryDelay(this.maxRetries - retriesLeft);\n await sleep(delay);\n return this.fetchWithRetry(url, init, retriesLeft - 1);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private retryDelay(attempt: number): number {\n const base = Math.min(500 * Math.pow(2, attempt), 5000);\n const jitter = base * 0.25 * Math.random();\n return base + jitter;\n }\n\n async postJSON<T>(path: string, body: Record<string, unknown>): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async postJSONForBuffer(path: string, body: Record<string, unknown>): Promise<{ buffer: Buffer; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const buffer = Buffer.from(await res.arrayBuffer());\n return { buffer, headers: res.headers };\n }\n\n async postJSONForStream(path: string, body: Record<string, unknown>): Promise<{ body: ReadableStream<Uint8Array>; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n if (!res.body) {\n throw new UpliftAIError('Response body is null');\n }\n\n return { body: res.body, headers: res.headers };\n }\n\n async postMultipart<T>(path: string, formData: FormData): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers(),\n body: formData,\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async get<T>(path: string): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'GET',\n headers: this.headers(),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async getStream(path: string, query?: Record<string, string>): Promise<{ body: ReadableStream<Uint8Array>; headers: Headers }> {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n url.searchParams.set(k, v);\n }\n }\n\n const res = await this.fetchWithRetry(url.toString(), {\n method: 'GET',\n headers: this.headers(),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n if (!res.body) {\n throw new UpliftAIError('Response body is null');\n }\n\n return { body: res.body, headers: res.headers };\n }\n\n private async throwForStatus(res: Response): Promise<never> {\n const requestId = res.headers.get('x-uplift-ai-request-id') ?? undefined;\n const body = await this.safeText(res);\n if (res.status === 401) throw new UpliftAIAuthError(undefined, requestId);\n if (res.status === 402) throw new UpliftAIInsufficientBalanceError(undefined, requestId);\n if (res.status === 429) throw new UpliftAIRateLimitError(undefined, requestId);\n throw new UpliftAIError(`HTTP ${res.status}: ${body}`, res.status, undefined, requestId);\n }\n\n private async safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return '';\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { Readable } from 'node:stream';\nimport { HttpClient } from './http';\nimport { PhraseReplacements } from './phrase-replacements';\nimport { TTSWebSocketImpl } from './ws';\nimport type {\n TTSRequest,\n AudioResponse,\n AudioMetadata,\n EnqueueResponse,\n StreamResponse,\n TTSWebSocket,\n} from './types';\n\nconst DEFAULT_OUTPUT_FORMAT = 'WAV_22050_32';\n\nfunction buildTTSBody(request: TTSRequest): Record<string, unknown> {\n const body: Record<string, unknown> = {\n text: request.text,\n voiceId: request.voiceId,\n outputFormat: request.outputFormat ?? DEFAULT_OUTPUT_FORMAT,\n };\n if (request.phraseReplacementConfigId) body.phraseReplacementConfigId = request.phraseReplacementConfigId;\n return body;\n}\n\nfunction parseAudioMetadata(headers: Headers): AudioMetadata {\n return {\n requestId: headers.get('x-uplift-ai-request-id') ?? '',\n duration: Number(headers.get('x-uplift-ai-audio-duration') ?? 0),\n contentType: headers.get('content-type') ?? 'application/octet-stream',\n sampleRate: Number(headers.get('x-uplift-ai-sample-rate') ?? 0),\n bitRate: Number(headers.get('x-uplift-ai-bit-rate') ?? 0),\n };\n}\n\nfunction readableFromWeb(webStream: ReadableStream<Uint8Array>): Readable {\n const reader = webStream.getReader();\n return new Readable({\n async read() {\n const { done, value } = await reader.read();\n if (done) {\n this.push(null);\n } else {\n this.push(Buffer.from(value));\n }\n },\n destroy(_err, callback) {\n reader.cancel().then(() => callback(null), callback);\n },\n });\n}\n\n/** Text-to-speech resource. Access via `client.tts`. */\nexport class TTS {\n private http: HttpClient;\n private apiKey: string;\n private baseUrl: string;\n private wsBaseUrl: string;\n\n /** Manage phrase replacement configs for pronunciation control. */\n readonly phraseReplacements: PhraseReplacements;\n\n constructor(http: HttpClient, apiKey: string, baseUrl: string, wsBaseUrl: string) {\n this.http = http;\n this.apiKey = apiKey;\n this.baseUrl = baseUrl;\n this.wsBaseUrl = wsBaseUrl;\n this.phraseReplacements = new PhraseReplacements(http);\n }\n\n /**\n * Synthesize text and return the full audio buffer.\n *\n * Generates the complete audio before returning. Faster end-to-end than\n * streaming, but the caller must wait for the entire file. Best for\n * batch/offline use cases where latency to first byte doesn't matter.\n *\n * @example\n * const { audio, metadata } = await client.tts.create({ text: 'سلام', voiceId: 'v_meklc281' });\n * fs.writeFileSync('output.mp3', audio);\n */\n async create(request: TTSRequest): Promise<AudioResponse> {\n const { buffer, headers } = await this.http.postJSONForBuffer(\n '/v1/synthesis/text-to-speech',\n buildTTSBody(request),\n );\n return {\n audio: buffer,\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Synthesize text and return a readable stream of audio chunks.\n *\n * The first chunk arrives quickly, but total generation is slower than\n * `create()`. Use this in latency-sensitive environments like live agents,\n * phone calls, or real-time playback where you want audio to start playing\n * immediately rather than waiting for the full file.\n *\n * @example\n * const { stream, metadata } = await client.tts.createStream({ text: 'سلام', voiceId: 'v_meklc281' });\n * for await (const chunk of stream) speaker.write(chunk);\n */\n async createStream(request: TTSRequest): Promise<StreamResponse> {\n const { body, headers } = await this.http.postJSONForStream(\n '/v1/synthesis/text-to-speech/stream',\n buildTTSBody(request),\n );\n return {\n stream: readableFromWeb(body),\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Enqueue an async TTS job. Returns a `mediaId` to retrieve the audio later.\n *\n * Use for batch processing or when you don't need audio immediately.\n * Poll or call `retrieve(mediaId)` when the audio is ready.\n *\n * @example\n * const { mediaId, temporaryUrl } = await client.tts.enqueue({ text: 'سلام', voiceId: 'v_meklc281' });\n * // retrieve server-side\n * const audio = await client.tts.retrieve(mediaId);\n * // or pass URL directly to a client/browser\n * console.log(temporaryUrl);\n */\n async enqueue(request: TTSRequest): Promise<EnqueueResponse> {\n const { data } = await this.http.postJSON<{ mediaId: string; token: string }>(\n '/v1/synthesis/text-to-speech-async',\n buildTTSBody(request),\n );\n return {\n ...data,\n temporaryUrl: this.buildTemporaryUrl(data.mediaId, data.token),\n };\n }\n\n /**\n * Enqueue an async TTS job with streaming retrieval.\n *\n * Same as `enqueue()`, but when retrieved via `retrieve(mediaId)` the audio\n * streams in chunks instead of arriving as a single buffer.\n *\n * @example\n * const { mediaId, temporaryUrl } = await client.tts.enqueueStream({ text: 'سلام', voiceId: 'v_meklc281' });\n * const stream = await client.tts.retrieve(mediaId);\n * for await (const chunk of stream) speaker.write(chunk);\n */\n async enqueueStream(request: TTSRequest): Promise<EnqueueResponse> {\n const { data } = await this.http.postJSON<{ mediaId: string; token: string }>(\n '/v1/synthesis/text-to-speech/stream-async',\n buildTTSBody(request),\n );\n return {\n ...data,\n temporaryUrl: this.buildTemporaryUrl(data.mediaId, data.token),\n };\n }\n\n /**\n * Retrieve audio from a previously enqueued job.\n *\n * Returns the audio stream along with metadata (encoding, sample rate, etc.)\n * from response headers.\n *\n * @example\n * const { stream, metadata } = await client.tts.retrieve('<mediaId from enqueue>');\n * console.log(metadata.contentType); // 'audio/mpeg'\n * for await (const chunk of stream) fs.appendFileSync('out.mp3', chunk);\n */\n async retrieve(mediaId: string): Promise<StreamResponse> {\n const { body, headers } = await this.http.getStream(`/v1/synthesis/stream-audio/${mediaId}`);\n return {\n stream: readableFromWeb(body),\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Open a persistent WebSocket connection for low-latency streaming TTS.\n *\n * Supports multiple concurrent streams on one connection, multiplexed by\n * requestId. Use for real-time conversational AI, live agents, and\n * interactive use cases. Resolves once the connection is ready.\n *\n * Open one connection per conversation or user session — don't share across\n * unrelated contexts.\n *\n * @example\n * const ws = await client.tts.connect();\n * // Stream sentence-by-sentence as your LLM generates\n * for await (const sentence of llm.streamSentences(prompt)) {\n * const stream = ws.stream({ text: sentence, voiceId: 'v_meklc281' });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n * }\n * ws.close();\n */\n private buildTemporaryUrl(mediaId: string, token: string): string {\n return `${this.baseUrl}/v1/synthesis/stream-audio/${mediaId}?token=${encodeURIComponent(token)}`;\n }\n\n async connect(): Promise<TTSWebSocket> {\n const wsUrl = `${this.wsBaseUrl}/v1/text-to-speech/multi-stream`;\n const ws = new TTSWebSocketImpl(wsUrl, this.apiKey);\n await ws.waitForReady();\n return ws;\n }\n}\n","import { HttpClient } from './http';\nimport type { PhraseReplacement, PhraseReplacementConfig } from './types';\n\nexport class PhraseReplacements {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n async create(replacements: PhraseReplacement[]): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.postJSON<PhraseReplacementConfig>(\n '/v1/synthesis/phrase-replacement-config',\n { phraseReplacements: replacements },\n );\n return data;\n }\n\n async get(configId: string): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.get<PhraseReplacementConfig>(\n `/v1/synthesis/phrase-replacement-config/${configId}`,\n );\n return data;\n }\n\n async list(): Promise<PhraseReplacementConfig[]> {\n const { data } = await this.http.get<PhraseReplacementConfig[]>(\n '/v1/synthesis/phrase-replacement-config',\n );\n return data;\n }\n\n async update(configId: string, replacements: PhraseReplacement[]): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.postJSON<PhraseReplacementConfig>(\n `/v1/synthesis/phrase-replacement-config/${configId}`,\n { phraseReplacements: replacements },\n );\n return data;\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport WebSocket from 'ws';\nimport type {\n TTSRequest,\n TTSStream,\n TTSStreamEvent,\n TTSWebSocket,\n WSReadyState,\n} from './types';\nimport { UpliftAIError } from './errors';\n\ninterface PendingStream {\n push(event: TTSStreamEvent): void;\n end(): void;\n error(err: Error): void;\n}\n\n/**\n * WebSocket-based TTS client. Supports multiple concurrent streams on a\n * single connection, multiplexed by requestId.\n *\n * Scope one connection per conversation or user session. Don't share a\n * single connection across unrelated contexts — we may leverage\n * connection-level state for prosody continuity in the future.\n *\n * Created via `client.tts.connect()` — do not instantiate directly.\n */\nexport class TTSWebSocketImpl implements TTSWebSocket {\n private ws: WebSocket;\n private _sessionId = '';\n private streams = new Map<string, PendingStream>();\n private readyPromise: Promise<void>;\n private readyResolve!: () => void;\n private readyReject!: (err: Error) => void;\n private listeners: { error: ((error: Error) => void)[]; close: ((code: number, reason: string) => void)[] } = {\n error: [],\n close: [],\n };\n\n constructor(url: string, apiKey: string) {\n this.readyPromise = new Promise<void>((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n\n this.ws = new WebSocket(url, {\n headers: { Authorization: `Bearer ${apiKey}` },\n });\n\n this.ws.on('message', (raw: WebSocket.Data) => {\n this.handleMessage(raw);\n });\n\n this.ws.on('error', (err: Error) => {\n this.readyReject(err);\n for (const listener of this.listeners.error) {\n try { listener(err); } catch (e) { process.emitWarning(`Error in listener callback: ${e}`, 'UpliftAI'); }\n }\n for (const stream of this.streams.values()) stream.error(err);\n });\n\n this.ws.on('close', (code: number, reason: Buffer) => {\n const reasonStr = reason.toString();\n for (const listener of this.listeners.close) {\n try { listener(code, reasonStr); } catch (e) { process.emitWarning(`Error in listener callback: ${e}`, 'UpliftAI'); }\n }\n for (const stream of this.streams.values()) {\n stream.error(new UpliftAIError(`WebSocket closed: ${code} ${reasonStr}`));\n }\n this.streams.clear();\n });\n }\n\n /** @internal Wait for the server `ready` message. Called by `tts.connect()`. */\n async waitForReady(): Promise<void> {\n return this.readyPromise;\n }\n\n /** Current connection state. */\n get readyState(): WSReadyState {\n switch (this.ws.readyState) {\n case WebSocket.CONNECTING: return 'connecting';\n case WebSocket.OPEN: return 'open';\n case WebSocket.CLOSING: return 'closing';\n case WebSocket.CLOSED: return 'closed';\n default: return 'closed';\n }\n }\n\n /** Server-assigned session ID, available after connection is ready. */\n get sessionId(): string {\n return this._sessionId;\n }\n\n /** Register a listener for connection-level events. */\n on(event: 'error', listener: (error: Error) => void): this;\n on(event: 'close', listener: (code: number, reason: string) => void): this;\n on(event: 'error' | 'close', listener: ((error: Error) => void) | ((code: number, reason: string) => void)): this {\n if (event === 'error') {\n this.listeners.error.push(listener as (error: Error) => void);\n } else {\n this.listeners.close.push(listener as (code: number, reason: string) => void);\n }\n return this;\n }\n\n /**\n * Start a TTS stream. Sends text to the server and returns an async iterable\n * of audio events (`audio_start`, `audio`, `audio_end`, `error`).\n *\n * Multiple streams can run concurrently on the same connection — each is\n * demuxed by its `requestId`. For real-time conversational AI, break your\n * LLM output into sentence-sized chunks and stream each one as it arrives.\n * This gives the lowest time-to-first-audio since synthesis starts before\n * the LLM finishes generating. If you use LiveKit, the UpliftAI plugin\n * handles this sentence segmentation automatically.\n *\n * **Connection scope:** Use one WebSocket per conversation / user session.\n * Don't multiplex unrelated use cases on a single connection — we may use\n * connection-level context for prosody and other improvements in the future.\n *\n * @example // Simple usage\n * const stream = ws.stream({ text: 'سلام', voiceId: 'v_meklc281' });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n *\n * @example // Real-time: stream sentence-by-sentence as LLM generates\n * for await (const sentence of llm.streamSentences(prompt)) {\n * const stream = ws.stream({ text: sentence, voiceId });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n * }\n *\n * @example // Overlap: fire next sentence before previous finishes\n * const sentences = ['پہلا جملہ۔', 'دوسرا جملہ۔', 'تیسرا جملہ۔'];\n * for (const sentence of sentences) {\n * const stream = ws.stream({ text: sentence, voiceId });\n * consume(stream); // don't await — let them overlap\n * }\n */\n stream(request: TTSRequest & { requestId?: string }): TTSStream {\n const requestId = request.requestId ?? randomUUID();\n\n const buffer: TTSStreamEvent[] = [];\n let resolve: ((value: IteratorResult<TTSStreamEvent>) => void) | null = null;\n let done = false;\n let error: Error | null = null;\n\n const cleanup = () => {\n this.streams.delete(requestId);\n buffer.length = 0;\n resolve = null;\n };\n\n const pending: PendingStream = {\n push(event: TTSStreamEvent) {\n if (done) return;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: event, done: false });\n } else {\n buffer.push(event);\n }\n },\n end() {\n if (done) return;\n done = true;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n },\n error(err: Error) {\n if (done) return;\n error = err;\n done = true;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n },\n };\n\n this.streams.set(requestId, pending);\n\n this.safeSend({\n type: 'synthesize',\n requestId,\n text: request.text,\n voiceId: request.voiceId,\n outputFormat: request.outputFormat ?? 'PCM_22050_16',\n });\n\n const iterator: AsyncIterableIterator<TTSStreamEvent> = {\n next(): Promise<IteratorResult<TTSStreamEvent>> {\n if (error || done) {\n if (buffer.length > 0) {\n return Promise.resolve({ value: buffer.shift()!, done: false });\n }\n cleanup();\n return Promise.resolve({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n if (buffer.length > 0) {\n return Promise.resolve({ value: buffer.shift()!, done: false });\n }\n return new Promise<IteratorResult<TTSStreamEvent>>((r) => {\n resolve = r;\n });\n },\n return(): Promise<IteratorResult<TTSStreamEvent>> {\n done = true;\n cleanup();\n return Promise.resolve({ value: undefined as unknown as TTSStreamEvent, done: true });\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n\n const stream: TTSStream = {\n requestId,\n /** Cancel this stream. Tells the server to stop generating and ends the iterator. */\n cancel: async () => {\n this.safeSend({ type: 'cancel', requestId });\n cleanup();\n pending.end();\n },\n [Symbol.asyncIterator]() {\n return iterator;\n },\n };\n\n return stream;\n }\n\n /**\n * Cancel all in-flight streams. Use for barge-in / interruption — when the\n * user starts speaking and you need to immediately stop all TTS playback.\n *\n * Sends a cancel message to the server for each active stream and ends\n * all iterators synchronously.\n *\n * @example\n * ws.stream({ text: 'sentence 1...', voiceId });\n * ws.stream({ text: 'sentence 2...', voiceId });\n * // User interrupts!\n * ws.cancelAll(); // both streams end immediately\n */\n cancelAll(): void {\n for (const [requestId, stream] of this.streams) {\n this.safeSend({ type: 'cancel', requestId });\n stream.end();\n }\n this.streams.clear();\n }\n\n /** Number of streams currently in-flight on this connection. */\n get activeStreams(): number {\n return this.streams.size;\n }\n\n /** Close the WebSocket connection. */\n close(): void {\n this.ws.close();\n }\n\n private safeSend(msg: Record<string, unknown>): void {\n try {\n this.ws.send(JSON.stringify(msg));\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n for (const stream of this.streams.values()) {\n stream.error(new UpliftAIError(`WebSocket send failed: ${error.message}`));\n }\n }\n }\n\n private handleMessage(raw: WebSocket.Data): void {\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n const type = msg.type as string;\n\n if (type === 'ready') {\n this._sessionId = msg.sessionId as string;\n this.readyResolve();\n return;\n }\n\n const requestId = msg.requestId as string;\n if (!requestId) return;\n\n const stream = this.streams.get(requestId);\n if (!stream) return;\n\n switch (type) {\n case 'audio_start':\n stream.push({\n type: 'audio_start',\n requestId,\n timestamp: msg.timestamp as number,\n });\n break;\n\n case 'audio': {\n let audio: Buffer;\n try {\n audio = Buffer.from(msg.audio as string, 'base64');\n } catch {\n stream.push({\n type: 'error',\n requestId,\n code: 'decode_error',\n message: 'Failed to decode base64 audio data',\n });\n stream.end();\n this.streams.delete(requestId);\n return;\n }\n stream.push({\n type: 'audio',\n requestId,\n sequence: msg.sequence as number,\n audio,\n });\n break;\n }\n\n case 'audio_end':\n stream.push({\n type: 'audio_end',\n requestId,\n timestamp: msg.timestamp as number,\n });\n stream.end();\n this.streams.delete(requestId);\n break;\n\n case 'error':\n stream.push({\n type: 'error',\n requestId,\n code: msg.code as string,\n message: msg.message as string,\n });\n stream.end();\n this.streams.delete(requestId);\n break;\n }\n }\n}\n","import { Readable } from 'node:stream';\nimport { createReadStream } from 'node:fs';\nimport { basename } from 'node:path';\nimport { HttpClient } from './http';\nimport { UpliftAIError } from './errors';\nimport type { TranscriptionRequest, TranscriptionResponse } from './types';\n\nasync function streamToBuffer(stream: NodeJS.ReadableStream | Readable): Promise<Buffer> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (Buffer.isBuffer(chunk)) {\n chunks.push(chunk);\n } else if (chunk instanceof Uint8Array) {\n chunks.push(Buffer.from(chunk));\n } else if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n throw new UpliftAIError('Unexpected chunk type in audio stream');\n }\n }\n return Buffer.concat(chunks);\n}\n\n/** Speech-to-text resource. Access via `client.stt`. */\nexport class STT {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n /**\n * Transcribe audio to text.\n *\n * Accepts a file path, Buffer, or readable stream as input.\n *\n * @example\n * // From file path (extension used for content-type detection)\n * const { transcript } = await client.stt.transcribe({ file: './call.mp3', model: 'scribe' });\n *\n * // From Buffer (pass fileName so the server knows the format)\n * const { transcript } = await client.stt.transcribe({ file: audioBuffer, fileName: 'call.mp3', language: 'ur' });\n */\n async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {\n const formData = new FormData();\n\n if (typeof request.file === 'string') {\n const stream = createReadStream(request.file);\n const buffer = await streamToBuffer(stream);\n formData.append('file', new Blob([buffer]), basename(request.file));\n } else if (Buffer.isBuffer(request.file)) {\n formData.append('file', new Blob([request.file]), request.fileName);\n } else {\n const buffer = await streamToBuffer(request.file as Readable);\n formData.append('file', new Blob([buffer]), request.fileName);\n }\n\n if (request.model) formData.append('model', request.model);\n if (request.language) formData.append('language', request.language);\n if (request.domain) formData.append('domain', request.domain);\n\n const { data } = await this.http.postMultipart<TranscriptionResponse>(\n '/v1/transcribe/speech-to-text',\n formData,\n );\n\n return data;\n }\n}\n","import { HttpClient } from './http';\nimport { TTS } from './tts';\nimport { STT } from './stt';\nimport { UpliftAIError } from './errors';\nimport type { UpliftAIOptions } from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.upliftai.org';\n\nexport class UpliftAI {\n readonly tts: TTS;\n readonly stt: STT;\n\n constructor(options: UpliftAIOptions = {}) {\n const apiKey = options.apiKey ?? process.env.UPLIFTAI_API_KEY;\n if (!apiKey) {\n throw new UpliftAIError(\n 'apiKey is required. Pass it in options or set the UPLIFTAI_API_KEY environment variable.',\n undefined,\n 'invalid_config',\n );\n }\n\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n const http = new HttpClient({\n baseUrl,\n apiKey,\n timeout: options.timeout,\n maxRetries: options.maxRetries,\n });\n\n const wsBaseUrl = baseUrl.replace(/^http/, 'ws').replace(/^https/, 'wss');\n\n this.tts = new TTS(http, apiKey, baseUrl, wsBaseUrl);\n this.stt = new STT(http);\n }\n}\n"],"mappings":"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","names":["WebSocket"]}
package/dist/index.mjs CHANGED
@@ -28,7 +28,7 @@ var UpliftAIRateLimitError = class extends UpliftAIError {
28
28
  };
29
29
 
30
30
  // src/http.ts
31
- var SDK_VERSION = "0.1.0";
31
+ var SDK_VERSION = "0.1.1";
32
32
  var DEFAULT_TIMEOUT = 3e4;
33
33
  var DEFAULT_MAX_RETRIES = 2;
34
34
  var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/tts.ts","../src/phrase-replacements.ts","../src/ws.ts","../src/stt.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["export class UpliftAIError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly code?: string,\n public readonly requestId?: string,\n ) {\n super(message);\n this.name = 'UpliftAIError';\n }\n}\n\nexport class UpliftAIAuthError extends UpliftAIError {\n constructor(message = 'Authentication failed. Check your API key.', requestId?: string) {\n super(message, 401, 'auth_error', requestId);\n this.name = 'UpliftAIAuthError';\n }\n}\n\nexport class UpliftAIInsufficientBalanceError extends UpliftAIError {\n constructor(message = 'Insufficient balance. Please add credits to your account.', requestId?: string) {\n super(message, 402, 'insufficient_balance', requestId);\n this.name = 'UpliftAIInsufficientBalanceError';\n }\n}\n\nexport class UpliftAIRateLimitError extends UpliftAIError {\n constructor(message = 'Rate limit exceeded.', requestId?: string) {\n super(message, 429, 'rate_limited', requestId);\n this.name = 'UpliftAIRateLimitError';\n }\n}\n","import { UpliftAIAuthError, UpliftAIError, UpliftAIInsufficientBalanceError, UpliftAIRateLimitError } from './errors';\n\nconst SDK_VERSION = '0.1.0';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n\nexport interface HttpClientOptions {\n baseUrl: string;\n apiKey: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class HttpClient {\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n private maxRetries: number;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\n this.apiKey = options.apiKey;\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n }\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n Authorization: `Bearer ${this.apiKey}`,\n 'User-Agent': `upliftai-js/${SDK_VERSION}`,\n Connection: 'keep-alive',\n ...extra,\n };\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, retriesLeft = this.maxRetries): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, { ...init, signal: controller.signal });\n\n if (!res.ok && retriesLeft > 0 && RETRYABLE_STATUS_CODES.has(res.status)) {\n const delay = this.retryDelay(this.maxRetries - retriesLeft);\n await sleep(delay);\n return this.fetchWithRetry(url, init, retriesLeft - 1);\n }\n\n return res;\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw new UpliftAIError('Request timed out', undefined, 'timeout');\n }\n if (retriesLeft > 0) {\n const delay = this.retryDelay(this.maxRetries - retriesLeft);\n await sleep(delay);\n return this.fetchWithRetry(url, init, retriesLeft - 1);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private retryDelay(attempt: number): number {\n const base = Math.min(500 * Math.pow(2, attempt), 5000);\n const jitter = base * 0.25 * Math.random();\n return base + jitter;\n }\n\n async postJSON<T>(path: string, body: Record<string, unknown>): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async postJSONForBuffer(path: string, body: Record<string, unknown>): Promise<{ buffer: Buffer; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const buffer = Buffer.from(await res.arrayBuffer());\n return { buffer, headers: res.headers };\n }\n\n async postJSONForStream(path: string, body: Record<string, unknown>): Promise<{ body: ReadableStream<Uint8Array>; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n if (!res.body) {\n throw new UpliftAIError('Response body is null');\n }\n\n return { body: res.body, headers: res.headers };\n }\n\n async postMultipart<T>(path: string, formData: FormData): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers(),\n body: formData,\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async get<T>(path: string): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'GET',\n headers: this.headers(),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async getStream(path: string, query?: Record<string, string>): Promise<{ body: ReadableStream<Uint8Array>; headers: Headers }> {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n url.searchParams.set(k, v);\n }\n }\n\n const res = await this.fetchWithRetry(url.toString(), {\n method: 'GET',\n headers: this.headers(),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n if (!res.body) {\n throw new UpliftAIError('Response body is null');\n }\n\n return { body: res.body, headers: res.headers };\n }\n\n private async throwForStatus(res: Response): Promise<never> {\n const requestId = res.headers.get('x-uplift-ai-request-id') ?? undefined;\n const body = await this.safeText(res);\n if (res.status === 401) throw new UpliftAIAuthError(undefined, requestId);\n if (res.status === 402) throw new UpliftAIInsufficientBalanceError(undefined, requestId);\n if (res.status === 429) throw new UpliftAIRateLimitError(undefined, requestId);\n throw new UpliftAIError(`HTTP ${res.status}: ${body}`, res.status, undefined, requestId);\n }\n\n private async safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return '';\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { Readable } from 'node:stream';\nimport { HttpClient } from './http';\nimport { PhraseReplacements } from './phrase-replacements';\nimport { TTSWebSocketImpl } from './ws';\nimport type {\n TTSRequest,\n AudioResponse,\n AudioMetadata,\n EnqueueResponse,\n StreamResponse,\n TTSWebSocket,\n} from './types';\n\nconst DEFAULT_OUTPUT_FORMAT = 'WAV_22050_32';\n\nfunction buildTTSBody(request: TTSRequest): Record<string, unknown> {\n const body: Record<string, unknown> = {\n text: request.text,\n voiceId: request.voiceId,\n outputFormat: request.outputFormat ?? DEFAULT_OUTPUT_FORMAT,\n };\n if (request.phraseReplacementConfigId) body.phraseReplacementConfigId = request.phraseReplacementConfigId;\n return body;\n}\n\nfunction parseAudioMetadata(headers: Headers): AudioMetadata {\n return {\n requestId: headers.get('x-uplift-ai-request-id') ?? '',\n duration: Number(headers.get('x-uplift-ai-audio-duration') ?? 0),\n contentType: headers.get('content-type') ?? 'application/octet-stream',\n sampleRate: Number(headers.get('x-uplift-ai-sample-rate') ?? 0),\n bitRate: Number(headers.get('x-uplift-ai-bit-rate') ?? 0),\n };\n}\n\nfunction readableFromWeb(webStream: ReadableStream<Uint8Array>): Readable {\n const reader = webStream.getReader();\n return new Readable({\n async read() {\n const { done, value } = await reader.read();\n if (done) {\n this.push(null);\n } else {\n this.push(Buffer.from(value));\n }\n },\n destroy(_err, callback) {\n reader.cancel().then(() => callback(null), callback);\n },\n });\n}\n\n/** Text-to-speech resource. Access via `client.tts`. */\nexport class TTS {\n private http: HttpClient;\n private apiKey: string;\n private baseUrl: string;\n private wsBaseUrl: string;\n\n /** Manage phrase replacement configs for pronunciation control. */\n readonly phraseReplacements: PhraseReplacements;\n\n constructor(http: HttpClient, apiKey: string, baseUrl: string, wsBaseUrl: string) {\n this.http = http;\n this.apiKey = apiKey;\n this.baseUrl = baseUrl;\n this.wsBaseUrl = wsBaseUrl;\n this.phraseReplacements = new PhraseReplacements(http);\n }\n\n /**\n * Synthesize text and return the full audio buffer.\n *\n * Generates the complete audio before returning. Faster end-to-end than\n * streaming, but the caller must wait for the entire file. Best for\n * batch/offline use cases where latency to first byte doesn't matter.\n *\n * @example\n * const { audio, metadata } = await client.tts.create({ text: 'سلام', voiceId: 'v_meklc281' });\n * fs.writeFileSync('output.mp3', audio);\n */\n async create(request: TTSRequest): Promise<AudioResponse> {\n const { buffer, headers } = await this.http.postJSONForBuffer(\n '/v1/synthesis/text-to-speech',\n buildTTSBody(request),\n );\n return {\n audio: buffer,\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Synthesize text and return a readable stream of audio chunks.\n *\n * The first chunk arrives quickly, but total generation is slower than\n * `create()`. Use this in latency-sensitive environments like live agents,\n * phone calls, or real-time playback where you want audio to start playing\n * immediately rather than waiting for the full file.\n *\n * @example\n * const { stream, metadata } = await client.tts.createStream({ text: 'سلام', voiceId: 'v_meklc281' });\n * for await (const chunk of stream) speaker.write(chunk);\n */\n async createStream(request: TTSRequest): Promise<StreamResponse> {\n const { body, headers } = await this.http.postJSONForStream(\n '/v1/synthesis/text-to-speech/stream',\n buildTTSBody(request),\n );\n return {\n stream: readableFromWeb(body),\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Enqueue an async TTS job. Returns a `mediaId` to retrieve the audio later.\n *\n * Use for batch processing or when you don't need audio immediately.\n * Poll or call `retrieve(mediaId)` when the audio is ready.\n *\n * @example\n * const { mediaId, temporaryUrl } = await client.tts.enqueue({ text: 'سلام', voiceId: 'v_meklc281' });\n * // retrieve server-side\n * const audio = await client.tts.retrieve(mediaId);\n * // or pass URL directly to a client/browser\n * console.log(temporaryUrl);\n */\n async enqueue(request: TTSRequest): Promise<EnqueueResponse> {\n const { data } = await this.http.postJSON<{ mediaId: string; token: string }>(\n '/v1/synthesis/text-to-speech-async',\n buildTTSBody(request),\n );\n return {\n ...data,\n temporaryUrl: this.buildTemporaryUrl(data.mediaId, data.token),\n };\n }\n\n /**\n * Enqueue an async TTS job with streaming retrieval.\n *\n * Same as `enqueue()`, but when retrieved via `retrieve(mediaId)` the audio\n * streams in chunks instead of arriving as a single buffer.\n *\n * @example\n * const { mediaId, temporaryUrl } = await client.tts.enqueueStream({ text: 'سلام', voiceId: 'v_meklc281' });\n * const stream = await client.tts.retrieve(mediaId);\n * for await (const chunk of stream) speaker.write(chunk);\n */\n async enqueueStream(request: TTSRequest): Promise<EnqueueResponse> {\n const { data } = await this.http.postJSON<{ mediaId: string; token: string }>(\n '/v1/synthesis/text-to-speech/stream-async',\n buildTTSBody(request),\n );\n return {\n ...data,\n temporaryUrl: this.buildTemporaryUrl(data.mediaId, data.token),\n };\n }\n\n /**\n * Retrieve audio from a previously enqueued job.\n *\n * Returns the audio stream along with metadata (encoding, sample rate, etc.)\n * from response headers.\n *\n * @example\n * const { stream, metadata } = await client.tts.retrieve('<mediaId from enqueue>');\n * console.log(metadata.contentType); // 'audio/mpeg'\n * for await (const chunk of stream) fs.appendFileSync('out.mp3', chunk);\n */\n async retrieve(mediaId: string): Promise<StreamResponse> {\n const { body, headers } = await this.http.getStream(`/v1/synthesis/stream-audio/${mediaId}`);\n return {\n stream: readableFromWeb(body),\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Open a persistent WebSocket connection for low-latency streaming TTS.\n *\n * Supports multiple concurrent streams on one connection, multiplexed by\n * requestId. Use for real-time conversational AI, live agents, and\n * interactive use cases. Resolves once the connection is ready.\n *\n * Open one connection per conversation or user session — don't share across\n * unrelated contexts.\n *\n * @example\n * const ws = await client.tts.connect();\n * // Stream sentence-by-sentence as your LLM generates\n * for await (const sentence of llm.streamSentences(prompt)) {\n * const stream = ws.stream({ text: sentence, voiceId: 'v_meklc281' });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n * }\n * ws.close();\n */\n private buildTemporaryUrl(mediaId: string, token: string): string {\n return `${this.baseUrl}/v1/synthesis/stream-audio/${mediaId}?token=${encodeURIComponent(token)}`;\n }\n\n async connect(): Promise<TTSWebSocket> {\n const wsUrl = `${this.wsBaseUrl}/v1/text-to-speech/multi-stream`;\n const ws = new TTSWebSocketImpl(wsUrl, this.apiKey);\n await ws.waitForReady();\n return ws;\n }\n}\n","import { HttpClient } from './http';\nimport type { PhraseReplacement, PhraseReplacementConfig } from './types';\n\nexport class PhraseReplacements {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n async create(replacements: PhraseReplacement[]): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.postJSON<PhraseReplacementConfig>(\n '/v1/synthesis/phrase-replacement-config',\n { phraseReplacements: replacements },\n );\n return data;\n }\n\n async get(configId: string): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.get<PhraseReplacementConfig>(\n `/v1/synthesis/phrase-replacement-config/${configId}`,\n );\n return data;\n }\n\n async list(): Promise<PhraseReplacementConfig[]> {\n const { data } = await this.http.get<PhraseReplacementConfig[]>(\n '/v1/synthesis/phrase-replacement-config',\n );\n return data;\n }\n\n async update(configId: string, replacements: PhraseReplacement[]): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.postJSON<PhraseReplacementConfig>(\n `/v1/synthesis/phrase-replacement-config/${configId}`,\n { phraseReplacements: replacements },\n );\n return data;\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport WebSocket from 'ws';\nimport type {\n TTSRequest,\n TTSStream,\n TTSStreamEvent,\n TTSWebSocket,\n WSReadyState,\n} from './types';\nimport { UpliftAIError } from './errors';\n\ninterface PendingStream {\n push(event: TTSStreamEvent): void;\n end(): void;\n error(err: Error): void;\n}\n\n/**\n * WebSocket-based TTS client. Supports multiple concurrent streams on a\n * single connection, multiplexed by requestId.\n *\n * Scope one connection per conversation or user session. Don't share a\n * single connection across unrelated contexts — we may leverage\n * connection-level state for prosody continuity in the future.\n *\n * Created via `client.tts.connect()` — do not instantiate directly.\n */\nexport class TTSWebSocketImpl implements TTSWebSocket {\n private ws: WebSocket;\n private _sessionId = '';\n private streams = new Map<string, PendingStream>();\n private readyPromise: Promise<void>;\n private readyResolve!: () => void;\n private readyReject!: (err: Error) => void;\n private listeners: { error: ((error: Error) => void)[]; close: ((code: number, reason: string) => void)[] } = {\n error: [],\n close: [],\n };\n\n constructor(url: string, apiKey: string) {\n this.readyPromise = new Promise<void>((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n\n this.ws = new WebSocket(url, {\n headers: { Authorization: `Bearer ${apiKey}` },\n });\n\n this.ws.on('message', (raw: WebSocket.Data) => {\n this.handleMessage(raw);\n });\n\n this.ws.on('error', (err: Error) => {\n this.readyReject(err);\n for (const listener of this.listeners.error) {\n try { listener(err); } catch (e) { process.emitWarning(`Error in listener callback: ${e}`, 'UpliftAI'); }\n }\n for (const stream of this.streams.values()) stream.error(err);\n });\n\n this.ws.on('close', (code: number, reason: Buffer) => {\n const reasonStr = reason.toString();\n for (const listener of this.listeners.close) {\n try { listener(code, reasonStr); } catch (e) { process.emitWarning(`Error in listener callback: ${e}`, 'UpliftAI'); }\n }\n for (const stream of this.streams.values()) {\n stream.error(new UpliftAIError(`WebSocket closed: ${code} ${reasonStr}`));\n }\n this.streams.clear();\n });\n }\n\n /** @internal Wait for the server `ready` message. Called by `tts.connect()`. */\n async waitForReady(): Promise<void> {\n return this.readyPromise;\n }\n\n /** Current connection state. */\n get readyState(): WSReadyState {\n switch (this.ws.readyState) {\n case WebSocket.CONNECTING: return 'connecting';\n case WebSocket.OPEN: return 'open';\n case WebSocket.CLOSING: return 'closing';\n case WebSocket.CLOSED: return 'closed';\n default: return 'closed';\n }\n }\n\n /** Server-assigned session ID, available after connection is ready. */\n get sessionId(): string {\n return this._sessionId;\n }\n\n /** Register a listener for connection-level events. */\n on(event: 'error', listener: (error: Error) => void): this;\n on(event: 'close', listener: (code: number, reason: string) => void): this;\n on(event: 'error' | 'close', listener: ((error: Error) => void) | ((code: number, reason: string) => void)): this {\n if (event === 'error') {\n this.listeners.error.push(listener as (error: Error) => void);\n } else {\n this.listeners.close.push(listener as (code: number, reason: string) => void);\n }\n return this;\n }\n\n /**\n * Start a TTS stream. Sends text to the server and returns an async iterable\n * of audio events (`audio_start`, `audio`, `audio_end`, `error`).\n *\n * Multiple streams can run concurrently on the same connection — each is\n * demuxed by its `requestId`. For real-time conversational AI, break your\n * LLM output into sentence-sized chunks and stream each one as it arrives.\n * This gives the lowest time-to-first-audio since synthesis starts before\n * the LLM finishes generating. If you use LiveKit, the UpliftAI plugin\n * handles this sentence segmentation automatically.\n *\n * **Connection scope:** Use one WebSocket per conversation / user session.\n * Don't multiplex unrelated use cases on a single connection — we may use\n * connection-level context for prosody and other improvements in the future.\n *\n * @example // Simple usage\n * const stream = ws.stream({ text: 'سلام', voiceId: 'v_meklc281' });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n *\n * @example // Real-time: stream sentence-by-sentence as LLM generates\n * for await (const sentence of llm.streamSentences(prompt)) {\n * const stream = ws.stream({ text: sentence, voiceId });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n * }\n *\n * @example // Overlap: fire next sentence before previous finishes\n * const sentences = ['پہلا جملہ۔', 'دوسرا جملہ۔', 'تیسرا جملہ۔'];\n * for (const sentence of sentences) {\n * const stream = ws.stream({ text: sentence, voiceId });\n * consume(stream); // don't await — let them overlap\n * }\n */\n stream(request: TTSRequest & { requestId?: string }): TTSStream {\n const requestId = request.requestId ?? randomUUID();\n\n const buffer: TTSStreamEvent[] = [];\n let resolve: ((value: IteratorResult<TTSStreamEvent>) => void) | null = null;\n let done = false;\n let error: Error | null = null;\n\n const cleanup = () => {\n this.streams.delete(requestId);\n buffer.length = 0;\n resolve = null;\n };\n\n const pending: PendingStream = {\n push(event: TTSStreamEvent) {\n if (done) return;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: event, done: false });\n } else {\n buffer.push(event);\n }\n },\n end() {\n if (done) return;\n done = true;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n },\n error(err: Error) {\n if (done) return;\n error = err;\n done = true;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n },\n };\n\n this.streams.set(requestId, pending);\n\n this.safeSend({\n type: 'synthesize',\n requestId,\n text: request.text,\n voiceId: request.voiceId,\n outputFormat: request.outputFormat ?? 'PCM_22050_16',\n });\n\n const iterator: AsyncIterableIterator<TTSStreamEvent> = {\n next(): Promise<IteratorResult<TTSStreamEvent>> {\n if (error || done) {\n if (buffer.length > 0) {\n return Promise.resolve({ value: buffer.shift()!, done: false });\n }\n cleanup();\n return Promise.resolve({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n if (buffer.length > 0) {\n return Promise.resolve({ value: buffer.shift()!, done: false });\n }\n return new Promise<IteratorResult<TTSStreamEvent>>((r) => {\n resolve = r;\n });\n },\n return(): Promise<IteratorResult<TTSStreamEvent>> {\n done = true;\n cleanup();\n return Promise.resolve({ value: undefined as unknown as TTSStreamEvent, done: true });\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n\n const stream: TTSStream = {\n requestId,\n /** Cancel this stream. Tells the server to stop generating and ends the iterator. */\n cancel: async () => {\n this.safeSend({ type: 'cancel', requestId });\n cleanup();\n pending.end();\n },\n [Symbol.asyncIterator]() {\n return iterator;\n },\n };\n\n return stream;\n }\n\n /**\n * Cancel all in-flight streams. Use for barge-in / interruption — when the\n * user starts speaking and you need to immediately stop all TTS playback.\n *\n * Sends a cancel message to the server for each active stream and ends\n * all iterators synchronously.\n *\n * @example\n * ws.stream({ text: 'sentence 1...', voiceId });\n * ws.stream({ text: 'sentence 2...', voiceId });\n * // User interrupts!\n * ws.cancelAll(); // both streams end immediately\n */\n cancelAll(): void {\n for (const [requestId, stream] of this.streams) {\n this.safeSend({ type: 'cancel', requestId });\n stream.end();\n }\n this.streams.clear();\n }\n\n /** Number of streams currently in-flight on this connection. */\n get activeStreams(): number {\n return this.streams.size;\n }\n\n /** Close the WebSocket connection. */\n close(): void {\n this.ws.close();\n }\n\n private safeSend(msg: Record<string, unknown>): void {\n try {\n this.ws.send(JSON.stringify(msg));\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n for (const stream of this.streams.values()) {\n stream.error(new UpliftAIError(`WebSocket send failed: ${error.message}`));\n }\n }\n }\n\n private handleMessage(raw: WebSocket.Data): void {\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n const type = msg.type as string;\n\n if (type === 'ready') {\n this._sessionId = msg.sessionId as string;\n this.readyResolve();\n return;\n }\n\n const requestId = msg.requestId as string;\n if (!requestId) return;\n\n const stream = this.streams.get(requestId);\n if (!stream) return;\n\n switch (type) {\n case 'audio_start':\n stream.push({\n type: 'audio_start',\n requestId,\n timestamp: msg.timestamp as number,\n });\n break;\n\n case 'audio': {\n let audio: Buffer;\n try {\n audio = Buffer.from(msg.audio as string, 'base64');\n } catch {\n stream.push({\n type: 'error',\n requestId,\n code: 'decode_error',\n message: 'Failed to decode base64 audio data',\n });\n stream.end();\n this.streams.delete(requestId);\n return;\n }\n stream.push({\n type: 'audio',\n requestId,\n sequence: msg.sequence as number,\n audio,\n });\n break;\n }\n\n case 'audio_end':\n stream.push({\n type: 'audio_end',\n requestId,\n timestamp: msg.timestamp as number,\n });\n stream.end();\n this.streams.delete(requestId);\n break;\n\n case 'error':\n stream.push({\n type: 'error',\n requestId,\n code: msg.code as string,\n message: msg.message as string,\n });\n stream.end();\n this.streams.delete(requestId);\n break;\n }\n }\n}\n","import { Readable } from 'node:stream';\nimport { createReadStream } from 'node:fs';\nimport { basename } from 'node:path';\nimport { HttpClient } from './http';\nimport { UpliftAIError } from './errors';\nimport type { TranscriptionRequest, TranscriptionResponse } from './types';\n\nasync function streamToBuffer(stream: NodeJS.ReadableStream | Readable): Promise<Buffer> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (Buffer.isBuffer(chunk)) {\n chunks.push(chunk);\n } else if (chunk instanceof Uint8Array) {\n chunks.push(Buffer.from(chunk));\n } else if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n throw new UpliftAIError('Unexpected chunk type in audio stream');\n }\n }\n return Buffer.concat(chunks);\n}\n\n/** Speech-to-text resource. Access via `client.stt`. */\nexport class STT {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n /**\n * Transcribe audio to text.\n *\n * Accepts a file path, Buffer, or readable stream as input.\n *\n * @example\n * // From file path (extension used for content-type detection)\n * const { transcript } = await client.stt.transcribe({ file: './call.mp3', model: 'scribe' });\n *\n * // From Buffer (pass fileName so the server knows the format)\n * const { transcript } = await client.stt.transcribe({ file: audioBuffer, fileName: 'call.mp3', language: 'ur' });\n */\n async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {\n const formData = new FormData();\n\n if (typeof request.file === 'string') {\n const stream = createReadStream(request.file);\n const buffer = await streamToBuffer(stream);\n formData.append('file', new Blob([buffer]), basename(request.file));\n } else if (Buffer.isBuffer(request.file)) {\n formData.append('file', new Blob([request.file]), request.fileName);\n } else {\n const buffer = await streamToBuffer(request.file as Readable);\n formData.append('file', new Blob([buffer]), request.fileName);\n }\n\n if (request.model) formData.append('model', request.model);\n if (request.language) formData.append('language', request.language);\n if (request.domain) formData.append('domain', request.domain);\n\n const { data } = await this.http.postMultipart<TranscriptionResponse>(\n '/v1/transcribe/speech-to-text',\n formData,\n );\n\n return data;\n }\n}\n","import { HttpClient } from './http';\nimport { TTS } from './tts';\nimport { STT } from './stt';\nimport { UpliftAIError } from './errors';\nimport type { UpliftAIOptions } from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.upliftai.org';\n\nexport class UpliftAI {\n readonly tts: TTS;\n readonly stt: STT;\n\n constructor(options: UpliftAIOptions = {}) {\n const apiKey = options.apiKey ?? process.env.UPLIFTAI_API_KEY;\n if (!apiKey) {\n throw new UpliftAIError(\n 'apiKey is required. Pass it in options or set the UPLIFTAI_API_KEY environment variable.',\n undefined,\n 'invalid_config',\n );\n }\n\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n const http = new HttpClient({\n baseUrl,\n apiKey,\n timeout: options.timeout,\n maxRetries: options.maxRetries,\n });\n\n const wsBaseUrl = baseUrl.replace(/^http/, 'ws').replace(/^https/, 'wss');\n\n this.tts = new TTS(http, apiKey, baseUrl, wsBaseUrl);\n this.stt = new STT(http);\n }\n}\n","import { UpliftAI } from './client';\n\nexport { UpliftAI } from './client';\nexport { UpliftAIError, UpliftAIAuthError, UpliftAIInsufficientBalanceError, UpliftAIRateLimitError } from './errors';\nexport type {\n UpliftAIOptions,\n OutputFormat,\n TTSRequest,\n AudioMetadata,\n AudioResponse,\n StreamResponse,\n EnqueueResponse,\n WSAudioStart,\n WSAudio,\n WSAudioEnd,\n WSError,\n TTSStreamEvent,\n TranscriptionRequest,\n TranscriptionRequestFromPath,\n TranscriptionRequestFromBuffer,\n TranscriptionResponse,\n PhraseReplacement,\n PhraseReplacementConfig,\n TTSStream,\n TTSWebSocket,\n WSReadyState,\n} from './types';\n\nexport default UpliftAI;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/tts.ts","../src/phrase-replacements.ts","../src/ws.ts","../src/stt.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["export class UpliftAIError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly code?: string,\n public readonly requestId?: string,\n ) {\n super(message);\n this.name = 'UpliftAIError';\n }\n}\n\nexport class UpliftAIAuthError extends UpliftAIError {\n constructor(message = 'Authentication failed. Check your API key.', requestId?: string) {\n super(message, 401, 'auth_error', requestId);\n this.name = 'UpliftAIAuthError';\n }\n}\n\nexport class UpliftAIInsufficientBalanceError extends UpliftAIError {\n constructor(message = 'Insufficient balance. Please add credits to your account.', requestId?: string) {\n super(message, 402, 'insufficient_balance', requestId);\n this.name = 'UpliftAIInsufficientBalanceError';\n }\n}\n\nexport class UpliftAIRateLimitError extends UpliftAIError {\n constructor(message = 'Rate limit exceeded.', requestId?: string) {\n super(message, 429, 'rate_limited', requestId);\n this.name = 'UpliftAIRateLimitError';\n }\n}\n","import { UpliftAIAuthError, UpliftAIError, UpliftAIInsufficientBalanceError, UpliftAIRateLimitError } from './errors';\n\nconst SDK_VERSION = '0.1.1';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n\nexport interface HttpClientOptions {\n baseUrl: string;\n apiKey: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class HttpClient {\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n private maxRetries: number;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\n this.apiKey = options.apiKey;\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n }\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n Authorization: `Bearer ${this.apiKey}`,\n 'User-Agent': `upliftai-js/${SDK_VERSION}`,\n Connection: 'keep-alive',\n ...extra,\n };\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, retriesLeft = this.maxRetries): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, { ...init, signal: controller.signal });\n\n if (!res.ok && retriesLeft > 0 && RETRYABLE_STATUS_CODES.has(res.status)) {\n const delay = this.retryDelay(this.maxRetries - retriesLeft);\n await sleep(delay);\n return this.fetchWithRetry(url, init, retriesLeft - 1);\n }\n\n return res;\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw new UpliftAIError('Request timed out', undefined, 'timeout');\n }\n if (retriesLeft > 0) {\n const delay = this.retryDelay(this.maxRetries - retriesLeft);\n await sleep(delay);\n return this.fetchWithRetry(url, init, retriesLeft - 1);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private retryDelay(attempt: number): number {\n const base = Math.min(500 * Math.pow(2, attempt), 5000);\n const jitter = base * 0.25 * Math.random();\n return base + jitter;\n }\n\n async postJSON<T>(path: string, body: Record<string, unknown>): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async postJSONForBuffer(path: string, body: Record<string, unknown>): Promise<{ buffer: Buffer; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const buffer = Buffer.from(await res.arrayBuffer());\n return { buffer, headers: res.headers };\n }\n\n async postJSONForStream(path: string, body: Record<string, unknown>): Promise<{ body: ReadableStream<Uint8Array>; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n if (!res.body) {\n throw new UpliftAIError('Response body is null');\n }\n\n return { body: res.body, headers: res.headers };\n }\n\n async postMultipart<T>(path: string, formData: FormData): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'POST',\n headers: this.headers(),\n body: formData,\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async get<T>(path: string): Promise<{ data: T; headers: Headers }> {\n const url = `${this.baseUrl}${path}`;\n const res = await this.fetchWithRetry(url, {\n method: 'GET',\n headers: this.headers(),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n const data = (await res.json()) as T;\n return { data, headers: res.headers };\n }\n\n async getStream(path: string, query?: Record<string, string>): Promise<{ body: ReadableStream<Uint8Array>; headers: Headers }> {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n url.searchParams.set(k, v);\n }\n }\n\n const res = await this.fetchWithRetry(url.toString(), {\n method: 'GET',\n headers: this.headers(),\n });\n\n if (!res.ok) {\n await this.throwForStatus(res);\n }\n\n if (!res.body) {\n throw new UpliftAIError('Response body is null');\n }\n\n return { body: res.body, headers: res.headers };\n }\n\n private async throwForStatus(res: Response): Promise<never> {\n const requestId = res.headers.get('x-uplift-ai-request-id') ?? undefined;\n const body = await this.safeText(res);\n if (res.status === 401) throw new UpliftAIAuthError(undefined, requestId);\n if (res.status === 402) throw new UpliftAIInsufficientBalanceError(undefined, requestId);\n if (res.status === 429) throw new UpliftAIRateLimitError(undefined, requestId);\n throw new UpliftAIError(`HTTP ${res.status}: ${body}`, res.status, undefined, requestId);\n }\n\n private async safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return '';\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { Readable } from 'node:stream';\nimport { HttpClient } from './http';\nimport { PhraseReplacements } from './phrase-replacements';\nimport { TTSWebSocketImpl } from './ws';\nimport type {\n TTSRequest,\n AudioResponse,\n AudioMetadata,\n EnqueueResponse,\n StreamResponse,\n TTSWebSocket,\n} from './types';\n\nconst DEFAULT_OUTPUT_FORMAT = 'WAV_22050_32';\n\nfunction buildTTSBody(request: TTSRequest): Record<string, unknown> {\n const body: Record<string, unknown> = {\n text: request.text,\n voiceId: request.voiceId,\n outputFormat: request.outputFormat ?? DEFAULT_OUTPUT_FORMAT,\n };\n if (request.phraseReplacementConfigId) body.phraseReplacementConfigId = request.phraseReplacementConfigId;\n return body;\n}\n\nfunction parseAudioMetadata(headers: Headers): AudioMetadata {\n return {\n requestId: headers.get('x-uplift-ai-request-id') ?? '',\n duration: Number(headers.get('x-uplift-ai-audio-duration') ?? 0),\n contentType: headers.get('content-type') ?? 'application/octet-stream',\n sampleRate: Number(headers.get('x-uplift-ai-sample-rate') ?? 0),\n bitRate: Number(headers.get('x-uplift-ai-bit-rate') ?? 0),\n };\n}\n\nfunction readableFromWeb(webStream: ReadableStream<Uint8Array>): Readable {\n const reader = webStream.getReader();\n return new Readable({\n async read() {\n const { done, value } = await reader.read();\n if (done) {\n this.push(null);\n } else {\n this.push(Buffer.from(value));\n }\n },\n destroy(_err, callback) {\n reader.cancel().then(() => callback(null), callback);\n },\n });\n}\n\n/** Text-to-speech resource. Access via `client.tts`. */\nexport class TTS {\n private http: HttpClient;\n private apiKey: string;\n private baseUrl: string;\n private wsBaseUrl: string;\n\n /** Manage phrase replacement configs for pronunciation control. */\n readonly phraseReplacements: PhraseReplacements;\n\n constructor(http: HttpClient, apiKey: string, baseUrl: string, wsBaseUrl: string) {\n this.http = http;\n this.apiKey = apiKey;\n this.baseUrl = baseUrl;\n this.wsBaseUrl = wsBaseUrl;\n this.phraseReplacements = new PhraseReplacements(http);\n }\n\n /**\n * Synthesize text and return the full audio buffer.\n *\n * Generates the complete audio before returning. Faster end-to-end than\n * streaming, but the caller must wait for the entire file. Best for\n * batch/offline use cases where latency to first byte doesn't matter.\n *\n * @example\n * const { audio, metadata } = await client.tts.create({ text: 'سلام', voiceId: 'v_meklc281' });\n * fs.writeFileSync('output.mp3', audio);\n */\n async create(request: TTSRequest): Promise<AudioResponse> {\n const { buffer, headers } = await this.http.postJSONForBuffer(\n '/v1/synthesis/text-to-speech',\n buildTTSBody(request),\n );\n return {\n audio: buffer,\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Synthesize text and return a readable stream of audio chunks.\n *\n * The first chunk arrives quickly, but total generation is slower than\n * `create()`. Use this in latency-sensitive environments like live agents,\n * phone calls, or real-time playback where you want audio to start playing\n * immediately rather than waiting for the full file.\n *\n * @example\n * const { stream, metadata } = await client.tts.createStream({ text: 'سلام', voiceId: 'v_meklc281' });\n * for await (const chunk of stream) speaker.write(chunk);\n */\n async createStream(request: TTSRequest): Promise<StreamResponse> {\n const { body, headers } = await this.http.postJSONForStream(\n '/v1/synthesis/text-to-speech/stream',\n buildTTSBody(request),\n );\n return {\n stream: readableFromWeb(body),\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Enqueue an async TTS job. Returns a `mediaId` to retrieve the audio later.\n *\n * Use for batch processing or when you don't need audio immediately.\n * Poll or call `retrieve(mediaId)` when the audio is ready.\n *\n * @example\n * const { mediaId, temporaryUrl } = await client.tts.enqueue({ text: 'سلام', voiceId: 'v_meklc281' });\n * // retrieve server-side\n * const audio = await client.tts.retrieve(mediaId);\n * // or pass URL directly to a client/browser\n * console.log(temporaryUrl);\n */\n async enqueue(request: TTSRequest): Promise<EnqueueResponse> {\n const { data } = await this.http.postJSON<{ mediaId: string; token: string }>(\n '/v1/synthesis/text-to-speech-async',\n buildTTSBody(request),\n );\n return {\n ...data,\n temporaryUrl: this.buildTemporaryUrl(data.mediaId, data.token),\n };\n }\n\n /**\n * Enqueue an async TTS job with streaming retrieval.\n *\n * Same as `enqueue()`, but when retrieved via `retrieve(mediaId)` the audio\n * streams in chunks instead of arriving as a single buffer.\n *\n * @example\n * const { mediaId, temporaryUrl } = await client.tts.enqueueStream({ text: 'سلام', voiceId: 'v_meklc281' });\n * const stream = await client.tts.retrieve(mediaId);\n * for await (const chunk of stream) speaker.write(chunk);\n */\n async enqueueStream(request: TTSRequest): Promise<EnqueueResponse> {\n const { data } = await this.http.postJSON<{ mediaId: string; token: string }>(\n '/v1/synthesis/text-to-speech/stream-async',\n buildTTSBody(request),\n );\n return {\n ...data,\n temporaryUrl: this.buildTemporaryUrl(data.mediaId, data.token),\n };\n }\n\n /**\n * Retrieve audio from a previously enqueued job.\n *\n * Returns the audio stream along with metadata (encoding, sample rate, etc.)\n * from response headers.\n *\n * @example\n * const { stream, metadata } = await client.tts.retrieve('<mediaId from enqueue>');\n * console.log(metadata.contentType); // 'audio/mpeg'\n * for await (const chunk of stream) fs.appendFileSync('out.mp3', chunk);\n */\n async retrieve(mediaId: string): Promise<StreamResponse> {\n const { body, headers } = await this.http.getStream(`/v1/synthesis/stream-audio/${mediaId}`);\n return {\n stream: readableFromWeb(body),\n metadata: parseAudioMetadata(headers),\n };\n }\n\n /**\n * Open a persistent WebSocket connection for low-latency streaming TTS.\n *\n * Supports multiple concurrent streams on one connection, multiplexed by\n * requestId. Use for real-time conversational AI, live agents, and\n * interactive use cases. Resolves once the connection is ready.\n *\n * Open one connection per conversation or user session — don't share across\n * unrelated contexts.\n *\n * @example\n * const ws = await client.tts.connect();\n * // Stream sentence-by-sentence as your LLM generates\n * for await (const sentence of llm.streamSentences(prompt)) {\n * const stream = ws.stream({ text: sentence, voiceId: 'v_meklc281' });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n * }\n * ws.close();\n */\n private buildTemporaryUrl(mediaId: string, token: string): string {\n return `${this.baseUrl}/v1/synthesis/stream-audio/${mediaId}?token=${encodeURIComponent(token)}`;\n }\n\n async connect(): Promise<TTSWebSocket> {\n const wsUrl = `${this.wsBaseUrl}/v1/text-to-speech/multi-stream`;\n const ws = new TTSWebSocketImpl(wsUrl, this.apiKey);\n await ws.waitForReady();\n return ws;\n }\n}\n","import { HttpClient } from './http';\nimport type { PhraseReplacement, PhraseReplacementConfig } from './types';\n\nexport class PhraseReplacements {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n async create(replacements: PhraseReplacement[]): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.postJSON<PhraseReplacementConfig>(\n '/v1/synthesis/phrase-replacement-config',\n { phraseReplacements: replacements },\n );\n return data;\n }\n\n async get(configId: string): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.get<PhraseReplacementConfig>(\n `/v1/synthesis/phrase-replacement-config/${configId}`,\n );\n return data;\n }\n\n async list(): Promise<PhraseReplacementConfig[]> {\n const { data } = await this.http.get<PhraseReplacementConfig[]>(\n '/v1/synthesis/phrase-replacement-config',\n );\n return data;\n }\n\n async update(configId: string, replacements: PhraseReplacement[]): Promise<PhraseReplacementConfig> {\n const { data } = await this.http.postJSON<PhraseReplacementConfig>(\n `/v1/synthesis/phrase-replacement-config/${configId}`,\n { phraseReplacements: replacements },\n );\n return data;\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport WebSocket from 'ws';\nimport type {\n TTSRequest,\n TTSStream,\n TTSStreamEvent,\n TTSWebSocket,\n WSReadyState,\n} from './types';\nimport { UpliftAIError } from './errors';\n\ninterface PendingStream {\n push(event: TTSStreamEvent): void;\n end(): void;\n error(err: Error): void;\n}\n\n/**\n * WebSocket-based TTS client. Supports multiple concurrent streams on a\n * single connection, multiplexed by requestId.\n *\n * Scope one connection per conversation or user session. Don't share a\n * single connection across unrelated contexts — we may leverage\n * connection-level state for prosody continuity in the future.\n *\n * Created via `client.tts.connect()` — do not instantiate directly.\n */\nexport class TTSWebSocketImpl implements TTSWebSocket {\n private ws: WebSocket;\n private _sessionId = '';\n private streams = new Map<string, PendingStream>();\n private readyPromise: Promise<void>;\n private readyResolve!: () => void;\n private readyReject!: (err: Error) => void;\n private listeners: { error: ((error: Error) => void)[]; close: ((code: number, reason: string) => void)[] } = {\n error: [],\n close: [],\n };\n\n constructor(url: string, apiKey: string) {\n this.readyPromise = new Promise<void>((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n\n this.ws = new WebSocket(url, {\n headers: { Authorization: `Bearer ${apiKey}` },\n });\n\n this.ws.on('message', (raw: WebSocket.Data) => {\n this.handleMessage(raw);\n });\n\n this.ws.on('error', (err: Error) => {\n this.readyReject(err);\n for (const listener of this.listeners.error) {\n try { listener(err); } catch (e) { process.emitWarning(`Error in listener callback: ${e}`, 'UpliftAI'); }\n }\n for (const stream of this.streams.values()) stream.error(err);\n });\n\n this.ws.on('close', (code: number, reason: Buffer) => {\n const reasonStr = reason.toString();\n for (const listener of this.listeners.close) {\n try { listener(code, reasonStr); } catch (e) { process.emitWarning(`Error in listener callback: ${e}`, 'UpliftAI'); }\n }\n for (const stream of this.streams.values()) {\n stream.error(new UpliftAIError(`WebSocket closed: ${code} ${reasonStr}`));\n }\n this.streams.clear();\n });\n }\n\n /** @internal Wait for the server `ready` message. Called by `tts.connect()`. */\n async waitForReady(): Promise<void> {\n return this.readyPromise;\n }\n\n /** Current connection state. */\n get readyState(): WSReadyState {\n switch (this.ws.readyState) {\n case WebSocket.CONNECTING: return 'connecting';\n case WebSocket.OPEN: return 'open';\n case WebSocket.CLOSING: return 'closing';\n case WebSocket.CLOSED: return 'closed';\n default: return 'closed';\n }\n }\n\n /** Server-assigned session ID, available after connection is ready. */\n get sessionId(): string {\n return this._sessionId;\n }\n\n /** Register a listener for connection-level events. */\n on(event: 'error', listener: (error: Error) => void): this;\n on(event: 'close', listener: (code: number, reason: string) => void): this;\n on(event: 'error' | 'close', listener: ((error: Error) => void) | ((code: number, reason: string) => void)): this {\n if (event === 'error') {\n this.listeners.error.push(listener as (error: Error) => void);\n } else {\n this.listeners.close.push(listener as (code: number, reason: string) => void);\n }\n return this;\n }\n\n /**\n * Start a TTS stream. Sends text to the server and returns an async iterable\n * of audio events (`audio_start`, `audio`, `audio_end`, `error`).\n *\n * Multiple streams can run concurrently on the same connection — each is\n * demuxed by its `requestId`. For real-time conversational AI, break your\n * LLM output into sentence-sized chunks and stream each one as it arrives.\n * This gives the lowest time-to-first-audio since synthesis starts before\n * the LLM finishes generating. If you use LiveKit, the UpliftAI plugin\n * handles this sentence segmentation automatically.\n *\n * **Connection scope:** Use one WebSocket per conversation / user session.\n * Don't multiplex unrelated use cases on a single connection — we may use\n * connection-level context for prosody and other improvements in the future.\n *\n * @example // Simple usage\n * const stream = ws.stream({ text: 'سلام', voiceId: 'v_meklc281' });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n *\n * @example // Real-time: stream sentence-by-sentence as LLM generates\n * for await (const sentence of llm.streamSentences(prompt)) {\n * const stream = ws.stream({ text: sentence, voiceId });\n * for await (const event of stream) {\n * if (event.type === 'audio') speaker.write(event.audio);\n * }\n * }\n *\n * @example // Overlap: fire next sentence before previous finishes\n * const sentences = ['پہلا جملہ۔', 'دوسرا جملہ۔', 'تیسرا جملہ۔'];\n * for (const sentence of sentences) {\n * const stream = ws.stream({ text: sentence, voiceId });\n * consume(stream); // don't await — let them overlap\n * }\n */\n stream(request: TTSRequest & { requestId?: string }): TTSStream {\n const requestId = request.requestId ?? randomUUID();\n\n const buffer: TTSStreamEvent[] = [];\n let resolve: ((value: IteratorResult<TTSStreamEvent>) => void) | null = null;\n let done = false;\n let error: Error | null = null;\n\n const cleanup = () => {\n this.streams.delete(requestId);\n buffer.length = 0;\n resolve = null;\n };\n\n const pending: PendingStream = {\n push(event: TTSStreamEvent) {\n if (done) return;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: event, done: false });\n } else {\n buffer.push(event);\n }\n },\n end() {\n if (done) return;\n done = true;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n },\n error(err: Error) {\n if (done) return;\n error = err;\n done = true;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n },\n };\n\n this.streams.set(requestId, pending);\n\n this.safeSend({\n type: 'synthesize',\n requestId,\n text: request.text,\n voiceId: request.voiceId,\n outputFormat: request.outputFormat ?? 'PCM_22050_16',\n });\n\n const iterator: AsyncIterableIterator<TTSStreamEvent> = {\n next(): Promise<IteratorResult<TTSStreamEvent>> {\n if (error || done) {\n if (buffer.length > 0) {\n return Promise.resolve({ value: buffer.shift()!, done: false });\n }\n cleanup();\n return Promise.resolve({ value: undefined as unknown as TTSStreamEvent, done: true });\n }\n if (buffer.length > 0) {\n return Promise.resolve({ value: buffer.shift()!, done: false });\n }\n return new Promise<IteratorResult<TTSStreamEvent>>((r) => {\n resolve = r;\n });\n },\n return(): Promise<IteratorResult<TTSStreamEvent>> {\n done = true;\n cleanup();\n return Promise.resolve({ value: undefined as unknown as TTSStreamEvent, done: true });\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n\n const stream: TTSStream = {\n requestId,\n /** Cancel this stream. Tells the server to stop generating and ends the iterator. */\n cancel: async () => {\n this.safeSend({ type: 'cancel', requestId });\n cleanup();\n pending.end();\n },\n [Symbol.asyncIterator]() {\n return iterator;\n },\n };\n\n return stream;\n }\n\n /**\n * Cancel all in-flight streams. Use for barge-in / interruption — when the\n * user starts speaking and you need to immediately stop all TTS playback.\n *\n * Sends a cancel message to the server for each active stream and ends\n * all iterators synchronously.\n *\n * @example\n * ws.stream({ text: 'sentence 1...', voiceId });\n * ws.stream({ text: 'sentence 2...', voiceId });\n * // User interrupts!\n * ws.cancelAll(); // both streams end immediately\n */\n cancelAll(): void {\n for (const [requestId, stream] of this.streams) {\n this.safeSend({ type: 'cancel', requestId });\n stream.end();\n }\n this.streams.clear();\n }\n\n /** Number of streams currently in-flight on this connection. */\n get activeStreams(): number {\n return this.streams.size;\n }\n\n /** Close the WebSocket connection. */\n close(): void {\n this.ws.close();\n }\n\n private safeSend(msg: Record<string, unknown>): void {\n try {\n this.ws.send(JSON.stringify(msg));\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n for (const stream of this.streams.values()) {\n stream.error(new UpliftAIError(`WebSocket send failed: ${error.message}`));\n }\n }\n }\n\n private handleMessage(raw: WebSocket.Data): void {\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n const type = msg.type as string;\n\n if (type === 'ready') {\n this._sessionId = msg.sessionId as string;\n this.readyResolve();\n return;\n }\n\n const requestId = msg.requestId as string;\n if (!requestId) return;\n\n const stream = this.streams.get(requestId);\n if (!stream) return;\n\n switch (type) {\n case 'audio_start':\n stream.push({\n type: 'audio_start',\n requestId,\n timestamp: msg.timestamp as number,\n });\n break;\n\n case 'audio': {\n let audio: Buffer;\n try {\n audio = Buffer.from(msg.audio as string, 'base64');\n } catch {\n stream.push({\n type: 'error',\n requestId,\n code: 'decode_error',\n message: 'Failed to decode base64 audio data',\n });\n stream.end();\n this.streams.delete(requestId);\n return;\n }\n stream.push({\n type: 'audio',\n requestId,\n sequence: msg.sequence as number,\n audio,\n });\n break;\n }\n\n case 'audio_end':\n stream.push({\n type: 'audio_end',\n requestId,\n timestamp: msg.timestamp as number,\n });\n stream.end();\n this.streams.delete(requestId);\n break;\n\n case 'error':\n stream.push({\n type: 'error',\n requestId,\n code: msg.code as string,\n message: msg.message as string,\n });\n stream.end();\n this.streams.delete(requestId);\n break;\n }\n }\n}\n","import { Readable } from 'node:stream';\nimport { createReadStream } from 'node:fs';\nimport { basename } from 'node:path';\nimport { HttpClient } from './http';\nimport { UpliftAIError } from './errors';\nimport type { TranscriptionRequest, TranscriptionResponse } from './types';\n\nasync function streamToBuffer(stream: NodeJS.ReadableStream | Readable): Promise<Buffer> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (Buffer.isBuffer(chunk)) {\n chunks.push(chunk);\n } else if (chunk instanceof Uint8Array) {\n chunks.push(Buffer.from(chunk));\n } else if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n throw new UpliftAIError('Unexpected chunk type in audio stream');\n }\n }\n return Buffer.concat(chunks);\n}\n\n/** Speech-to-text resource. Access via `client.stt`. */\nexport class STT {\n private http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n /**\n * Transcribe audio to text.\n *\n * Accepts a file path, Buffer, or readable stream as input.\n *\n * @example\n * // From file path (extension used for content-type detection)\n * const { transcript } = await client.stt.transcribe({ file: './call.mp3', model: 'scribe' });\n *\n * // From Buffer (pass fileName so the server knows the format)\n * const { transcript } = await client.stt.transcribe({ file: audioBuffer, fileName: 'call.mp3', language: 'ur' });\n */\n async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {\n const formData = new FormData();\n\n if (typeof request.file === 'string') {\n const stream = createReadStream(request.file);\n const buffer = await streamToBuffer(stream);\n formData.append('file', new Blob([buffer]), basename(request.file));\n } else if (Buffer.isBuffer(request.file)) {\n formData.append('file', new Blob([request.file]), request.fileName);\n } else {\n const buffer = await streamToBuffer(request.file as Readable);\n formData.append('file', new Blob([buffer]), request.fileName);\n }\n\n if (request.model) formData.append('model', request.model);\n if (request.language) formData.append('language', request.language);\n if (request.domain) formData.append('domain', request.domain);\n\n const { data } = await this.http.postMultipart<TranscriptionResponse>(\n '/v1/transcribe/speech-to-text',\n formData,\n );\n\n return data;\n }\n}\n","import { HttpClient } from './http';\nimport { TTS } from './tts';\nimport { STT } from './stt';\nimport { UpliftAIError } from './errors';\nimport type { UpliftAIOptions } from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.upliftai.org';\n\nexport class UpliftAI {\n readonly tts: TTS;\n readonly stt: STT;\n\n constructor(options: UpliftAIOptions = {}) {\n const apiKey = options.apiKey ?? process.env.UPLIFTAI_API_KEY;\n if (!apiKey) {\n throw new UpliftAIError(\n 'apiKey is required. Pass it in options or set the UPLIFTAI_API_KEY environment variable.',\n undefined,\n 'invalid_config',\n );\n }\n\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n const http = new HttpClient({\n baseUrl,\n apiKey,\n timeout: options.timeout,\n maxRetries: options.maxRetries,\n });\n\n const wsBaseUrl = baseUrl.replace(/^http/, 'ws').replace(/^https/, 'wss');\n\n this.tts = new TTS(http, apiKey, baseUrl, wsBaseUrl);\n this.stt = new STT(http);\n }\n}\n","import { UpliftAI } from './client';\n\nexport { UpliftAI } from './client';\nexport { UpliftAIError, UpliftAIAuthError, UpliftAIInsufficientBalanceError, UpliftAIRateLimitError } from './errors';\nexport type {\n UpliftAIOptions,\n OutputFormat,\n TTSRequest,\n AudioMetadata,\n AudioResponse,\n StreamResponse,\n EnqueueResponse,\n WSAudioStart,\n WSAudio,\n WSAudioEnd,\n WSError,\n TTSStreamEvent,\n TranscriptionRequest,\n TranscriptionRequestFromPath,\n TranscriptionRequestFromBuffer,\n TranscriptionResponse,\n PhraseReplacement,\n PhraseReplacementConfig,\n TTSStream,\n TTSWebSocket,\n WSReadyState,\n} from './types';\n\nexport default UpliftAI;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upliftai/sdk-js",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Official UpliftAI SDK for Node.js — TTS, STT, and real-time audio streaming",
5
5
  "author": "UpliftAI",
6
6
  "license": "MIT",