UNPKG

phonic

Version:
311 lines (303 loc) 7.74 kB
// package.json var version = "0.19.1"; // src/conversations/index.ts var Conversations = class { constructor(phonic) { this.phonic = phonic; } async get(id) { const response = await this.phonic.get( `/conversations/${id}` ); return response; } async getByExternalId({ project, externalId }) { const queryString = new URLSearchParams({ ...project !== void 0 && { project }, external_id: externalId }).toString(); const response = await this.phonic.get( `/conversations?${queryString}` ); return response; } async list({ project, durationMin, durationMax, startedAtMin, startedAtMax }) { const queryString = new URLSearchParams({ ...project !== void 0 && { project }, ...durationMin !== void 0 && { duration_min: String(durationMin) }, ...durationMax !== void 0 && { duration_max: String(durationMax) }, ...startedAtMin !== void 0 && { started_at_min: startedAtMin }, ...startedAtMax !== void 0 && { started_at_max: startedAtMax } }).toString(); const response = await this.phonic.get( `/conversations?${queryString}` ); return response; } }; // src/sts/index.ts import WebSocket from "ws"; // src/sts/twilio/index.ts var Twilio = class { constructor(phonic) { this.phonic = phonic; } async outboundCall(params, config) { const response = await this.phonic.post( "/sts/twilio/outbound_call", { from_phone_number: params.from_phone_number, to_phone_number: params.to_phone_number, config }, { "X-Twilio-Account-Sid": params.account_sid, "X-Twilio-Api-Key-Sid": params.api_key_sid, "X-Twilio-Api-Key-Secret": params.api_key_secret } ); return response; } }; // src/sts/websocket.ts var PhonicSTSWebSocket = class { constructor(ws, config) { this.ws = ws; this.config = config; this.buffer.push( JSON.stringify({ type: "config", ...this.config }) ); this.ws.onopen = () => { for (const message of this.buffer) { this.ws.send(message); } this.isOpen = true; }; this.ws.onmessage = (event) => { if (this.onMessageCallback === null) { return; } if (typeof event.data !== "string") { throw new Error("Received non-string message"); } const dataObj = JSON.parse( event.data ); this.onMessageCallback(dataObj); }; this.ws.onclose = (event) => { if (this.onCloseCallback === null) { return; } this.onCloseCallback(event); }; this.ws.onerror = (event) => { if (this.onErrorCallback === null) { return; } this.onErrorCallback(event); }; this.onMessage = this.onMessage.bind(this); this.onClose = this.onClose.bind(this); this.onError = this.onError.bind(this); this.audioChunk = this.audioChunk.bind(this); this.close = this.close.bind(this); } onMessageCallback = null; onCloseCallback = null; onErrorCallback = null; buffer = []; isOpen = false; onMessage(callback) { this.onMessageCallback = callback; } onClose(callback) { this.onCloseCallback = callback; } onError(callback) { this.onErrorCallback = callback; } audioChunk({ audio }) { const audiochunkMessage = JSON.stringify({ type: "audio_chunk", audio }); if (this.isOpen) { this.ws.send(audiochunkMessage); } else { this.buffer.push(audiochunkMessage); } } updateSystemPrompt({ systemPrompt }) { const updateSystemPromptMessage = JSON.stringify({ type: "update_system_prompt", system_prompt: systemPrompt }); if (this.isOpen) { this.ws.send(updateSystemPromptMessage); } else { this.buffer.push(updateSystemPromptMessage); } } setExternalId({ externalId }) { const setExternalIdMessage = JSON.stringify({ type: "set_external_id", external_id: externalId }); if (this.isOpen) { this.ws.send(setExternalIdMessage); } else { this.buffer.push(setExternalIdMessage); } } close(code) { this.ws.close(code ?? 1e3); } }; // src/sts/index.ts var SpeechToSpeech = class { constructor(phonic) { this.phonic = phonic; this.twilio = new Twilio(phonic); } twilio; websocket(config) { const wsBaseUrl = this.phonic.baseUrl.replace(/^http/, "ws"); const queryString = new URLSearchParams({ ...this.phonic.__downstreamWebSocketUrl !== null && { downstream_websocket_url: this.phonic.__downstreamWebSocketUrl } }).toString(); const phonicApiWsUrl = `${wsBaseUrl}/v1/sts/ws?${queryString}`; const ws = new WebSocket(phonicApiWsUrl, { headers: this.phonic.headers }); return new PhonicSTSWebSocket(ws, config); } async outboundCall(toPhoneNumber, config) { const response = await this.phonic.post( "/sts/outbound_call", { to_phone_number: toPhoneNumber, config } ); return response; } }; // src/voices/index.ts var Voices = class { constructor(phonic) { this.phonic = phonic; } async list({ model }) { const response = await this.phonic.get( `/voices?model=${encodeURIComponent(model)}` ); return response; } async get(id) { const response = await this.phonic.get( `/voices/${id}` ); return response; } }; // src/phonic.ts var defaultBaseUrl = "https://api.phonic.co"; var defaultUserAgent = `phonic-node:${version}`; var Phonic = class { constructor(apiKey, config) { this.apiKey = apiKey; if (typeof process === "undefined") { throw new Error( "Phonic SDK is intended to be used in Node.js environment." ); } if (!this.apiKey) { throw new Error( 'API key is missing. Pass it to the constructor: `new Phonic("ph_...")`' ); } this.baseUrl = (config?.baseUrl ?? defaultBaseUrl).replace(/\/$/, ""); this.__downstreamWebSocketUrl = config?.__downstreamWebSocketUrl || null; this.headers = { Authorization: `Bearer ${this.apiKey}`, "User-Agent": process.env.PHONIC_USER_AGENT || defaultUserAgent, "Content-Type": "application/json", ...config?.headers }; } baseUrl; __downstreamWebSocketUrl; headers; conversations = new Conversations(this); voices = new Voices(this); sts = new SpeechToSpeech(this); async fetchRequest(path, options) { try { const { headers, ...restOptions } = options; const response = await fetch(`${this.baseUrl}/v1${path}`, { headers: { ...this.headers, ...headers }, ...restOptions }); if (response.ok) { const data = await response.json(); return { data, error: null }; } try { const data = await response.json(); const errorMessage = data.error.message || response.statusText; return { data: null, error: { message: errorMessage } }; } catch (error) { return { data: null, error: { message: response.statusText } }; } } catch (error) { console.error(error); return { data: null, error: { message: "Fetch request failed" } }; } } async get(path) { return this.fetchRequest(path, { method: "GET" }); } async post(path, body, headers) { return this.fetchRequest(path, { method: "POST", body: JSON.stringify(body), headers }); } }; export { Phonic };