UNPKG

@mastra/voice-cloudflare

Version:

Mastra Cloudflare AI voice integration

332 lines (328 loc) • 10.1 kB
import Cloudflare from 'cloudflare'; // ../../packages/_internal-core/dist/chunk-HDURQPU2.js var RegisteredLogger = { LLM: "LLM"}; var LogLevel = { DEBUG: "debug", INFO: "info", WARN: "warn", ERROR: "error"}; var MastraLogger = class { name; level; transports; constructor(options = {}) { this.name = options.name || "Mastra"; this.level = options.level || LogLevel.ERROR; this.transports = new Map(Object.entries(options.transports || {})); } getTransports() { return this.transports; } trackException(_error, _metadata) { } async listLogs(transportId, params) { if (!transportId || !this.transports.has(transportId)) { return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false }; } return this.transports.get(transportId).listLogs?.(params) ?? { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false }; } async listLogsByRunId({ transportId, runId, fromDate, toDate, logLevel, filters, page, perPage }) { if (!transportId || !this.transports.has(transportId) || !runId) { return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false }; } return this.transports.get(transportId).listLogsByRunId?.({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false }; } }; var ConsoleLogger = class _ConsoleLogger extends MastraLogger { component; filter; constructor(options = {}) { super(options); this.component = options.component; this.filter = options.filter; } child(componentOrBindings) { const component = typeof componentOrBindings === "string" ? componentOrBindings : componentOrBindings?.component ?? this.component; return new _ConsoleLogger({ name: this.name, level: this.level, component, filter: this.filter }); } shouldLog(level, message, args) { if (!this.filter) return true; try { return this.filter({ component: this.component, level, message, args }); } catch (e) { console.error(`[Logger] Filter error for component=${this.component} level=${level}:`, e); return true; } } prefix() { return this.component ? `[${this.component}] ` : ""; } debug(message, ...args) { if (this.level === LogLevel.DEBUG && this.shouldLog(LogLevel.DEBUG, message, args)) { console.info(`${this.prefix()}${message}`, ...args); } } info(message, ...args) { if ((this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.INFO, message, args)) { console.info(`${this.prefix()}${message}`, ...args); } } warn(message, ...args) { if ((this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.WARN, message, args)) { console.info(`${this.prefix()}${message}`, ...args); } } error(message, ...args) { if ((this.level === LogLevel.ERROR || this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.ERROR, message, args)) { console.error(`${this.prefix()}${message}`, ...args); } } async listLogs(_transportId, _params) { return { logs: [], total: 0, page: _params?.page ?? 1, perPage: _params?.perPage ?? 100, hasMore: false }; } async listLogsByRunId(_args) { return { logs: [], total: 0, page: _args.page ?? 1, perPage: _args.perPage ?? 100, hasMore: false }; } }; // ../../packages/_internal-core/dist/base/index.js var MastraBase = class { component = RegisteredLogger.LLM; logger; name; #rawConfig; constructor({ component, name, rawConfig }) { this.component = component || RegisteredLogger.LLM; this.name = name; this.#rawConfig = rawConfig; this.logger = new ConsoleLogger({ name: `${this.component} - ${this.name}` }); } /** * Returns the raw storage configuration this primitive was created from, * or undefined if it was created from code. */ toRawConfig() { return this.#rawConfig; } /** * Sets the raw storage configuration for this primitive. * @internal */ __setRawConfig(rawConfig) { this.#rawConfig = rawConfig; } /** * Set the logger for the agent * @param logger */ __setLogger(logger) { this.logger = "child" in logger && typeof logger.child === "function" ? logger.child({ component: this.component }) : logger; } }; // ../../packages/_internals/voice/dist/chunk-NWNKSBZV.js var MastraVoice = class extends MastraBase { listeningModel; speechModel; speaker; realtimeConfig; constructor({ listeningModel, speechModel, speaker, realtimeConfig, name } = {}) { super({ component: "VOICE", name }); this.listeningModel = listeningModel; this.speechModel = speechModel; this.speaker = speaker; this.realtimeConfig = realtimeConfig; } /** * Custom serialization for tracing/observability spans. * Excludes `apiKey` from listeningModel / speechModel / realtimeConfig * and any provider-specific state held by subclasses. Subclasses that * need to expose additional non-sensitive fields can override. */ serializeForSpan() { return { component: "VOICE", name: this.name, speaker: this.speaker, listeningModel: this.listeningModel ? { name: this.listeningModel.name } : void 0, speechModel: this.speechModel ? { name: this.speechModel.name } : void 0, realtimeModel: this.realtimeConfig?.model }; } updateConfig(_options) { this.logger.debug("updateConfig not implemented by this voice provider"); } /** * Initializes a WebSocket or WebRTC connection for real-time communication * @returns Promise that resolves when the connection is established */ async connect(_options) { this.logger.debug("connect not implemented by this voice provider"); } /** * Relay audio data to the voice provider for real-time processing * @param audioData Audio data to relay */ async send(_audioData) { this.logger.debug("relay not implemented by this voice provider"); } /** * Trigger voice providers to respond */ async answer(_options) { this.logger.debug("answer not implemented by this voice provider"); } /** * Equip the voice provider with instructions * @param instructions Instructions to add */ addInstructions(_instructions) { } /** * Equip the voice provider with tools * @param tools Array of tools to add */ addTools(_tools) { } /** * Disconnect from the WebSocket or WebRTC connection */ close() { this.logger.debug("close not implemented by this voice provider"); } /** * Register an event listener * @param event Event name (e.g., 'speaking', 'writing', 'error') * @param callback Callback function that receives event data */ on(_event, _callback) { this.logger.debug("on not implemented by this voice provider"); } /** * Remove an event listener * @param event Event name (e.g., 'speaking', 'writing', 'error') * @param callback Callback function to remove */ off(_event, _callback) { this.logger.debug("off not implemented by this voice provider"); } /** * Get available speakers/voices * @returns Array of available voice IDs and their metadata */ getSpeakers() { this.logger.debug("getSpeakers not implemented by this voice provider"); return Promise.resolve([]); } /** * Get available speakers/voices * @returns Array of available voice IDs and their metadata */ getListener() { this.logger.debug("getListener not implemented by this voice provider"); return Promise.resolve({ enabled: false }); } }; var defaultListeningModel = { model: "@cf/openai/whisper-large-v3-turbo", apiKey: process.env.CLOUDFLARE_AI_API_KEY, account_id: process.env.CLOUDFLARE_ACCOUNT_ID }; var CloudflareVoice = class extends MastraVoice { apiToken; client = null; binding; constructor({ listeningModel, binding } = {}) { super({ listeningModel: { name: listeningModel?.model ?? defaultListeningModel.model, apiKey: listeningModel?.apiKey ?? defaultListeningModel.apiKey } }); this.binding = binding; if (!binding) { this.apiToken = listeningModel?.apiKey || defaultListeningModel.apiKey; if (!this.apiToken) { throw new Error("CLOUDFLARE_AI_API_KEY must be set when not using bindings"); } this.client = new Cloudflare({ apiToken: this.apiToken }); } } /** * Checks if listening capabilities are enabled. * * @returns {Promise<{ enabled: boolean }>} */ async getListener() { return { enabled: true }; } async listen(audioStream, options) { const chunks = []; for await (const chunk of audioStream) { if (typeof chunk === "string") { chunks.push(Buffer.from(chunk)); } else { chunks.push(chunk); } } const audioBuffer = Buffer.concat(chunks); const base64Audio = audioBuffer.toString("base64"); const model = options?.model || defaultListeningModel.model; if (this.binding) { const response = await this.binding.run(model, { audio: base64Audio }); return response.text; } else if (this.client) { const payload = { audio: base64Audio, account_id: options?.account_id || defaultListeningModel.account_id }; const response = await this.client.ai.run(model, payload); return response.text; } else { throw new Error("Neither binding nor REST client is configured"); } } async speak() { throw new Error("This feature is not yet implemented."); } async getSpeakers() { throw new Error("This feature is not yet implemented."); } }; export { CloudflareVoice }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map