{"version":3,"file":"openai.cjs","sources":["../../src/providers/OpenAIProvider.ts"],"sourcesContent":["import type { TTSProvider, SpeakOptions, VoiceInfo, SpeechError, OpenAIConfig } from './types.js'\nimport { playBlobAudio, throwIfNotOk } from './audioUtils.js'\n\nconst OPENAI_VOICES: VoiceInfo[] = [\n  { id: 'alloy',   name: 'Alloy',   lang: 'en', label: 'Alloy',   default: true  },\n  { id: 'echo',    name: 'Echo',    lang: 'en', label: 'Echo',    default: false },\n  { id: 'fable',   name: 'Fable',   lang: 'en', label: 'Fable',   default: false },\n  { id: 'onyx',    name: 'Onyx',    lang: 'en', label: 'Onyx',    default: false },\n  { id: 'nova',    name: 'Nova',    lang: 'en', label: 'Nova',    default: false },\n  { id: 'shimmer', name: 'Shimmer', lang: 'en', label: 'Shimmer', default: false },\n]\n\nexport class OpenAIProvider implements TTSProvider {\n  readonly isSupported: boolean = typeof window !== 'undefined'\n\n  private _config: OpenAIConfig\n  private _abortController: AbortController | null = null\n\n  private _startCbs: Array<() => void> = []\n  private _endCbs: Array<() => void> = []\n  private _errorCbs: Array<(err: SpeechError) => void> = []\n\n  constructor(config: OpenAIConfig) {\n    if (config.baseURL && !/^https:\\/\\//i.test(config.baseURL)) {\n      throw new Error('[vue-text-to-speech] OpenAI baseURL must use HTTPS')\n    }\n    this._config = config\n  }\n\n  onStart(cb: () => void): void { this._startCbs.push(cb) }\n  onEnd(cb: () => void): void   { this._endCbs.push(cb) }\n  onError(cb: (err: SpeechError) => void): void { this._errorCbs.push(cb) }\n\n  async speak(options: SpeakOptions): Promise<void> {\n    if (!options.text) {\n      const err: SpeechError = { code: 'API_ERROR', message: 'Text must not be empty' }\n      this._errorCbs.forEach((cb) => cb(err))\n      throw err\n    }\n    if (options.text.length > 10_000) {\n      const err: SpeechError = { code: 'API_ERROR', message: 'Text exceeds maximum length of 10,000 characters' }\n      this._errorCbs.forEach((cb) => cb(err))\n      throw err\n    }\n\n    this.stop()\n\n    const controller = new AbortController()\n    this._abortController = controller\n\n    const baseURL = this._config.baseURL?.replace(/\\/$/, '') ?? 'https://api.openai.com'\n\n    let response: Response\n    try {\n      response = await fetch(`${baseURL}/v1/audio/speech`, {\n        method: 'POST',\n        signal: controller.signal,\n        headers: {\n          'Content-Type': 'application/json',\n          Authorization: `Bearer ${this._config.apiKey}`,\n        },\n        body: JSON.stringify({\n          model: this._config.model ?? 'tts-1',\n          input: options.text,\n          voice: options.voice?.id ?? this._config.voice ?? 'alloy',\n          speed: options.rate ?? this._config.speed ?? 1,\n        }),\n      })\n    } catch (e: unknown) {\n      if ((e as Error)?.name === 'AbortError') return\n      const err: SpeechError = { code: 'NETWORK', message: 'OpenAI TTS fetch failed', cause: e }\n      this._errorCbs.forEach((cb) => cb(err))\n      throw err\n    }\n\n    await throwIfNotOk(response)\n\n    const blob = await response.blob()\n\n    this._startCbs.forEach((cb) => cb())\n    try {\n      await playBlobAudio(blob, controller.signal)\n    } catch (e: unknown) {\n      const err = e as SpeechError\n      this._errorCbs.forEach((cb) => cb(err))\n      throw err\n    } finally {\n      this._abortController = null\n      this._endCbs.forEach((cb) => cb())\n    }\n  }\n\n  stop(): void {\n    this._abortController?.abort()\n    this._abortController = null\n  }\n\n  pause(): void { /* no-op — no pause API for remote audio */ }\n  resume(): void { /* no-op */ }\n\n  getVoices(): Promise<VoiceInfo[]> {\n    return Promise.resolve(OPENAI_VOICES)\n  }\n}\n"],"names":["throwIfNotOk","playBlobAudio"],"mappings":"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"}