@ai-sdk/fish-audio 2.0.0 → 3.0.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/CHANGELOG.md CHANGED
@@ -1,7 +1,15 @@
1
1
  # @ai-sdk/fish-audio
2
2
 
3
- ## 2.0.0
3
+ ## 3.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [3469d0c]
8
+ - @ai-sdk/provider@4.0.6
9
+ - @ai-sdk/provider-utils@5.0.23
10
+
11
+ ## 3.0.0
4
12
 
5
13
  ### Major Changes
6
14
 
7
- - db05205: feat(fish-audio): add Fish Audio provider with speech and transcription models
15
+ - e1f9b02: feat(fish-audio): add Fish Audio provider with speech and transcription models
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { SpeechModelV3, ProviderV3, TranscriptionModelV3 } from '@ai-sdk/provider';
2
- import { FetchFunction } from '@ai-sdk/provider-utils';
1
+ import * as _ai_sdk_provider from '@ai-sdk/provider';
2
+ import { SpeechModelV4, ProviderV4, TranscriptionModelV4 } from '@ai-sdk/provider';
3
+ import { FetchFunction, WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from '@ai-sdk/provider-utils';
3
4
  import { z } from 'zod/v4';
4
5
 
5
6
  type FishAudioConfig = {
@@ -33,14 +34,22 @@ interface FishAudioSpeechModelConfig extends FishAudioConfig {
33
34
  currentDate?: () => Date;
34
35
  };
35
36
  }
36
- declare class FishAudioSpeechModel implements SpeechModelV3 {
37
+ declare class FishAudioSpeechModel implements SpeechModelV4 {
37
38
  readonly modelId: FishAudioSpeechModelId;
38
39
  private readonly config;
39
- readonly specificationVersion = "v3";
40
+ readonly specificationVersion = "v4";
40
41
  get provider(): string;
42
+ static [WORKFLOW_SERIALIZE](model: FishAudioSpeechModel): {
43
+ modelId: string;
44
+ config: _ai_sdk_provider.JSONObject;
45
+ };
46
+ static [WORKFLOW_DESERIALIZE](options: {
47
+ modelId: FishAudioSpeechModelId;
48
+ config: FishAudioSpeechModelConfig;
49
+ }): FishAudioSpeechModel;
41
50
  constructor(modelId: FishAudioSpeechModelId, config: FishAudioSpeechModelConfig);
42
51
  private getArgs;
43
- doGenerate(options: Parameters<SpeechModelV3['doGenerate']>[0]): Promise<Awaited<ReturnType<SpeechModelV3['doGenerate']>>>;
52
+ doGenerate(options: Parameters<SpeechModelV4['doGenerate']>[0]): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>>;
44
53
  }
45
54
 
46
55
  /**
@@ -55,30 +64,30 @@ declare class FishAudioSpeechModel implements SpeechModelV3 {
55
64
  */
56
65
  type FishAudioTranscriptionModelId = 'transcribe-1' | (string & {});
57
66
 
58
- interface FishAudioProvider extends ProviderV3 {
67
+ interface FishAudioProvider extends ProviderV4 {
59
68
  (modelId: FishAudioSpeechModelId, settings?: {}): {
60
69
  speech: FishAudioSpeechModel;
61
70
  };
62
71
  /**
63
72
  * Creates a model for speech generation.
64
73
  */
65
- speech(modelId: FishAudioSpeechModelId): SpeechModelV3;
74
+ speech(modelId: FishAudioSpeechModelId): SpeechModelV4;
66
75
  /**
67
76
  * Creates a model for speech generation.
68
77
  *
69
78
  * Narrowed to required: Fish Audio always provides speech models.
70
79
  */
71
- speechModel(modelId: FishAudioSpeechModelId): SpeechModelV3;
80
+ speechModel(modelId: FishAudioSpeechModelId): SpeechModelV4;
72
81
  /**
73
82
  * Creates a model for transcription.
74
83
  */
75
- transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV3;
84
+ transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV4;
76
85
  /**
77
86
  * Creates a model for transcription.
78
87
  *
79
88
  * Narrowed to required: Fish Audio always provides a transcription model.
80
89
  */
81
- transcriptionModel(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV3;
90
+ transcriptionModel(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV4;
82
91
  }
83
92
  interface FishAudioProviderSettings {
84
93
  /**
@@ -113,14 +122,22 @@ interface FishAudioTranscriptionModelConfig extends FishAudioConfig {
113
122
  currentDate?: () => Date;
114
123
  };
115
124
  }
116
- declare class FishAudioTranscriptionModel implements TranscriptionModelV3 {
125
+ declare class FishAudioTranscriptionModel implements TranscriptionModelV4 {
117
126
  readonly modelId: FishAudioTranscriptionModelId;
118
127
  private readonly config;
119
- readonly specificationVersion = "v3";
128
+ readonly specificationVersion = "v4";
120
129
  get provider(): string;
130
+ static [WORKFLOW_SERIALIZE](model: FishAudioTranscriptionModel): {
131
+ modelId: string;
132
+ config: _ai_sdk_provider.JSONObject;
133
+ };
134
+ static [WORKFLOW_DESERIALIZE](options: {
135
+ modelId: FishAudioTranscriptionModelId;
136
+ config: FishAudioTranscriptionModelConfig;
137
+ }): FishAudioTranscriptionModel;
121
138
  constructor(modelId: FishAudioTranscriptionModelId, config: FishAudioTranscriptionModelConfig);
122
139
  private getArgs;
123
- doGenerate(options: Parameters<TranscriptionModelV3['doGenerate']>[0]): Promise<Awaited<ReturnType<TranscriptionModelV3['doGenerate']>>>;
140
+ doGenerate(options: Parameters<TranscriptionModelV4['doGenerate']>[0]): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>>;
124
141
  }
125
142
 
126
143
  declare const fishAudioSpeechModelOptionsSchema: z.ZodObject<{
package/dist/index.js CHANGED
@@ -12,7 +12,10 @@ import {
12
12
  combineHeaders,
13
13
  createBinaryResponseHandler,
14
14
  parseProviderOptions,
15
- postJsonToApi
15
+ postJsonToApi,
16
+ serializeModelOptions,
17
+ WORKFLOW_DESERIALIZE,
18
+ WORKFLOW_SERIALIZE
16
19
  } from "@ai-sdk/provider-utils";
17
20
 
18
21
  // src/fish-audio-error.ts
@@ -150,15 +153,24 @@ function resolveFormat({
150
153
  }
151
154
  return matched;
152
155
  }
153
- var FishAudioSpeechModel = class {
156
+ var FishAudioSpeechModel = class _FishAudioSpeechModel {
154
157
  constructor(modelId, config) {
155
158
  this.modelId = modelId;
156
159
  this.config = config;
157
- this.specificationVersion = "v3";
160
+ this.specificationVersion = "v4";
158
161
  }
159
162
  get provider() {
160
163
  return this.config.provider;
161
164
  }
165
+ static [WORKFLOW_SERIALIZE](model) {
166
+ return serializeModelOptions({
167
+ modelId: model.modelId,
168
+ config: model.config
169
+ });
170
+ }
171
+ static [WORKFLOW_DESERIALIZE](options) {
172
+ return new _FishAudioSpeechModel(options.modelId, options.config);
173
+ }
162
174
  async getArgs({
163
175
  text,
164
176
  voice,
@@ -335,7 +347,10 @@ import {
335
347
  createJsonResponseHandler,
336
348
  mediaTypeToExtension,
337
349
  parseProviderOptions as parseProviderOptions2,
338
- postFormDataToApi
350
+ postFormDataToApi,
351
+ serializeModelOptions as serializeModelOptions2,
352
+ WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE2,
353
+ WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE2
339
354
  } from "@ai-sdk/provider-utils";
340
355
  import { z as z4 } from "zod/v4";
341
356
 
@@ -363,15 +378,24 @@ var fishAudioTranscriptionModelOptionsSchema = z3.object({
363
378
  });
364
379
 
365
380
  // src/fish-audio-transcription-model.ts
366
- var FishAudioTranscriptionModel = class {
381
+ var FishAudioTranscriptionModel = class _FishAudioTranscriptionModel {
367
382
  constructor(modelId, config) {
368
383
  this.modelId = modelId;
369
384
  this.config = config;
370
- this.specificationVersion = "v3";
385
+ this.specificationVersion = "v4";
371
386
  }
372
387
  get provider() {
373
388
  return this.config.provider;
374
389
  }
390
+ static [WORKFLOW_SERIALIZE2](model) {
391
+ return serializeModelOptions2({
392
+ modelId: model.modelId,
393
+ config: model.config
394
+ });
395
+ }
396
+ static [WORKFLOW_DESERIALIZE2](options) {
397
+ return new _FishAudioTranscriptionModel(options.modelId, options.config);
398
+ }
375
399
  async getArgs({
376
400
  audio,
377
401
  mediaType,
@@ -470,7 +494,7 @@ var fishAudioTranscriptionResponseSchema = z4.object({
470
494
  });
471
495
 
472
496
  // src/version.ts
473
- var VERSION = true ? "2.0.0" : "0.0.0-test";
497
+ var VERSION = true ? "3.0.1" : "0.0.0-test";
474
498
 
475
499
  // src/fish-audio-provider.ts
476
500
  var DEFAULT_BASE_URL = "https://api.fish.audio";
@@ -505,7 +529,7 @@ function createFishAudio(options = {}) {
505
529
  speech: createSpeechModel(modelId)
506
530
  };
507
531
  };
508
- provider.specificationVersion = "v3";
532
+ provider.specificationVersion = "v4";
509
533
  provider.speech = createSpeechModel;
510
534
  provider.speechModel = createSpeechModel;
511
535
  provider.transcription = createTranscriptionModel;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/fish-audio-provider.ts","../src/fish-audio-speech-model.ts","../src/fish-audio-error.ts","../src/fish-audio-speech-model-options.ts","../src/fish-audio-transcription-model.ts","../src/fish-audio-transcription-model-options.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type ProviderV3,\n type SpeechModelV3,\n type TranscriptionModelV3,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { FishAudioSpeechModel } from './fish-audio-speech-model';\nimport type { FishAudioSpeechModelId } from './fish-audio-speech-options';\nimport { FishAudioTranscriptionModel } from './fish-audio-transcription-model';\nimport type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';\nimport { VERSION } from './version';\n\nexport interface FishAudioProvider extends ProviderV3 {\n (\n modelId: FishAudioSpeechModelId,\n settings?: {},\n ): {\n speech: FishAudioSpeechModel;\n };\n\n /**\n * Creates a model for speech generation.\n */\n speech(modelId: FishAudioSpeechModelId): SpeechModelV3;\n\n /**\n * Creates a model for speech generation.\n *\n * Narrowed to required: Fish Audio always provides speech models.\n */\n speechModel(modelId: FishAudioSpeechModelId): SpeechModelV3;\n\n /**\n * Creates a model for transcription.\n */\n transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV3;\n\n /**\n * Creates a model for transcription.\n *\n * Narrowed to required: Fish Audio always provides a transcription model.\n */\n transcriptionModel(\n modelId?: FishAudioTranscriptionModelId,\n ): TranscriptionModelV3;\n}\n\nexport interface FishAudioProviderSettings {\n /**\n * API key for authenticating requests.\n */\n apiKey?: string;\n\n /**\n * Base URL for the API calls.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept requests,\n * or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.fish.audio';\n\n/**\n * Create a Fish Audio provider instance.\n */\nexport function createFishAudio(\n options: FishAudioProviderSettings = {},\n): FishAudioProvider {\n const baseURL = options.baseURL?.replace(/\\/$/, '') ?? DEFAULT_BASE_URL;\n\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'FISH_AUDIO_API_KEY',\n description: 'Fish Audio',\n })}`,\n ...options.headers,\n },\n `ai-sdk/fish-audio/${VERSION}`,\n );\n\n const createSpeechModel = (modelId: FishAudioSpeechModelId) =>\n new FishAudioSpeechModel(modelId, {\n provider: 'fish-audio.speech',\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n // `/v1/asr` has no model selector, so the model ID is a routing label and\n // defaults to `transcribe-1`.\n const createTranscriptionModel = (\n modelId: FishAudioTranscriptionModelId = 'transcribe-1',\n ) =>\n new FishAudioTranscriptionModel(modelId, {\n provider: 'fish-audio.transcription',\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const provider = function (modelId: FishAudioSpeechModelId) {\n return {\n speech: createSpeechModel(modelId),\n };\n };\n\n provider.specificationVersion = 'v3' as const;\n provider.speech = createSpeechModel;\n provider.speechModel = createSpeechModel;\n provider.transcription = createTranscriptionModel;\n provider.transcriptionModel = createTranscriptionModel;\n\n // Required ProviderV3 methods that are not supported\n provider.languageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n message: 'Fish Audio does not provide language models',\n });\n };\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n message: 'Fish Audio does not provide embedding models',\n });\n };\n provider.textEmbeddingModel = provider.embeddingModel;\n\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'imageModel',\n message: 'Fish Audio does not provide image models',\n });\n };\n\n return provider as FishAudioProvider;\n}\n\n/**\n * Default Fish Audio provider instance.\n */\nexport const fishAudio = createFishAudio();\n","import type { SharedV3Warning, SpeechModelV3 } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n createBinaryResponseHandler,\n parseProviderOptions,\n postJsonToApi,\n} from '@ai-sdk/provider-utils';\nimport type { FishAudioConfig } from './fish-audio-config';\nimport { fishAudioFailedResponseHandler } from './fish-audio-error';\nimport type {\n FishAudioSpeechAPITypes,\n FishAudioSpeechFormat,\n FishAudioProsodyControl,\n} from './fish-audio-speech-api-types';\nimport { fishAudioSpeechModelOptionsSchema } from './fish-audio-speech-model-options';\nimport type { FishAudioSpeechModelId } from './fish-audio-speech-options';\n\ninterface FishAudioSpeechModelConfig extends FishAudioConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nconst SUPPORTED_FORMATS: FishAudioSpeechFormat[] = [\n 'wav',\n 'pcm',\n 'mp3',\n 'opus',\n];\n\nconst DEFAULT_FORMAT: FishAudioSpeechFormat = 'mp3';\n\n// Fish Audio accepts `prosody.speed` between 0.5 and 2.0.\nconst MIN_SPEED = 0.5;\nconst MAX_SPEED = 2;\n\nfunction resolveFormat({\n outputFormat,\n warnings,\n}: {\n outputFormat: string | undefined;\n warnings: SharedV3Warning[];\n}): FishAudioSpeechFormat {\n if (outputFormat == null) {\n return DEFAULT_FORMAT;\n }\n\n const normalized = outputFormat.toLowerCase();\n const matched = SUPPORTED_FORMATS.find(format => format === normalized);\n\n if (matched == null) {\n warnings.push({\n type: 'unsupported',\n feature: 'outputFormat',\n details: `Fish Audio does not support the output format \"${outputFormat}\". Falling back to ${DEFAULT_FORMAT}. Supported formats are ${SUPPORTED_FORMATS.join(', ')}.`,\n });\n return DEFAULT_FORMAT;\n }\n\n return matched;\n}\n\nexport class FishAudioSpeechModel implements SpeechModelV3 {\n readonly specificationVersion = 'v3';\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: FishAudioSpeechModelId,\n private readonly config: FishAudioSpeechModelConfig,\n ) {}\n\n private async getArgs({\n text,\n voice,\n outputFormat,\n instructions,\n language,\n speed,\n providerOptions,\n }: Parameters<SpeechModelV3['doGenerate']>[0]) {\n const warnings: SharedV3Warning[] = [];\n\n const fishAudioOptions = await parseProviderOptions({\n provider: 'fishAudio',\n providerOptions,\n schema: fishAudioSpeechModelOptionsSchema,\n });\n\n const format = resolveFormat({ outputFormat, warnings });\n\n const requestBody: FishAudioSpeechAPITypes = {\n text,\n format,\n };\n\n // `providerOptions.fishAudio.referenceId` wins over the generic `voice` so\n // that multi-speaker arrays are expressible.\n const referenceId = fishAudioOptions?.referenceId ?? voice;\n if (referenceId != null) {\n requestBody.reference_id = referenceId;\n }\n\n const prosody: FishAudioProsodyControl = {};\n\n if (speed != null) {\n if (speed >= MIN_SPEED && speed <= MAX_SPEED) {\n prosody.speed = speed;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'speed',\n details: `Fish Audio speed must be between ${MIN_SPEED} and ${MAX_SPEED}. The speed option was ignored.`,\n });\n }\n }\n\n if (fishAudioOptions?.volume != null) {\n prosody.volume = fishAudioOptions.volume;\n }\n\n if (fishAudioOptions?.normalizeLoudness != null) {\n // Fish Audio accepts `normalize_loudness` on s1 but ignores it, so warn\n // rather than let it silently do nothing. Only s1 is known to ignore it;\n // unrecognized model IDs are left alone.\n if (this.modelId === 's1') {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.normalizeLoudness',\n details:\n 'Fish Audio ignores normalizeLoudness on s1. It is supported by the S2 family (s2-pro, s2.1-pro).',\n });\n } else {\n prosody.normalize_loudness = fishAudioOptions.normalizeLoudness;\n }\n }\n\n if (Object.keys(prosody).length > 0) {\n requestBody.prosody = prosody;\n }\n\n if (language != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'language',\n details:\n 'Fish Audio infers the language from the input text and the selected voice, and has no language parameter. The language option was ignored.',\n });\n }\n\n if (instructions != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'instructions',\n details:\n 'Fish Audio does not support instructions. The instructions option was ignored.',\n });\n }\n\n if (fishAudioOptions != null) {\n if (fishAudioOptions.sampleRate != null) {\n requestBody.sample_rate = fishAudioOptions.sampleRate;\n }\n\n if (fishAudioOptions.mp3Bitrate != null) {\n if (format === 'mp3') {\n requestBody.mp3_bitrate = fishAudioOptions.mp3Bitrate;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.mp3Bitrate',\n details: `mp3Bitrate only applies to mp3 output. The option was ignored for ${format} output.`,\n });\n }\n }\n\n if (fishAudioOptions.opusBitrate != null) {\n if (format === 'opus') {\n requestBody.opus_bitrate = fishAudioOptions.opusBitrate;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.opusBitrate',\n details: `opusBitrate only applies to opus output. The option was ignored for ${format} output.`,\n });\n }\n }\n\n if (fishAudioOptions.latency != null) {\n requestBody.latency = fishAudioOptions.latency;\n }\n\n if (fishAudioOptions.temperature != null) {\n requestBody.temperature = fishAudioOptions.temperature;\n }\n\n if (fishAudioOptions.topP != null) {\n requestBody.top_p = fishAudioOptions.topP;\n }\n\n if (fishAudioOptions.chunkLength != null) {\n requestBody.chunk_length = fishAudioOptions.chunkLength;\n }\n\n if (fishAudioOptions.minChunkLength != null) {\n requestBody.min_chunk_length = fishAudioOptions.minChunkLength;\n }\n\n if (fishAudioOptions.normalize != null) {\n requestBody.normalize = fishAudioOptions.normalize;\n }\n\n if (fishAudioOptions.maxNewTokens != null) {\n requestBody.max_new_tokens = fishAudioOptions.maxNewTokens;\n }\n\n if (fishAudioOptions.repetitionPenalty != null) {\n requestBody.repetition_penalty = fishAudioOptions.repetitionPenalty;\n }\n\n if (fishAudioOptions.conditionOnPreviousChunks != null) {\n requestBody.condition_on_previous_chunks =\n fishAudioOptions.conditionOnPreviousChunks;\n }\n\n if (fishAudioOptions.earlyStopThreshold != null) {\n requestBody.early_stop_threshold = fishAudioOptions.earlyStopThreshold;\n }\n\n if (fishAudioOptions.features != null) {\n requestBody.features = fishAudioOptions.features;\n }\n }\n\n return { requestBody, warnings };\n }\n\n async doGenerate(\n options: Parameters<SpeechModelV3['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<SpeechModelV3['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { requestBody, warnings } = await this.getArgs(options);\n\n const {\n value: audio,\n responseHeaders,\n rawValue: rawResponse,\n } = await postJsonToApi({\n url: this.config.url({ path: '/v1/tts', modelId: this.modelId }),\n // Fish Audio selects the TTS model with a `model` HTTP header rather\n // than a request body field.\n headers: combineHeaders(\n this.config.headers?.(),\n { model: this.modelId },\n options.headers,\n ),\n body: requestBody,\n failedResponseHandler: fishAudioFailedResponseHandler,\n successfulResponseHandler: createBinaryResponseHandler(),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n return {\n audio,\n warnings,\n request: {\n body: JSON.stringify(requestBody),\n },\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n };\n }\n}\n","import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\n// Fish Audio returns `{ status, message }` for documented error responses\n// (401 no permission, 402 no payment).\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\nexport const fishAudioErrorDataSchema = z.object({\n status: z.number().nullish(),\n message: z.string().nullish(),\n});\n\nexport type FishAudioErrorData = z.infer<typeof fishAudioErrorDataSchema>;\n\nexport const fishAudioFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: fishAudioErrorDataSchema,\n errorToMessage: data => data.message ?? 'Unknown Fish Audio error',\n});\n","import { z } from 'zod/v4';\n\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\nexport const fishAudioSpeechModelOptionsSchema = z.object({\n /**\n * Voice model ID(s). A single ID selects one speaker; an array enables\n * multi-speaker dialogue (S2-Pro models), in which case the text must mark\n * turns with speaker tokens such as `<|speaker:0|>`. The speaker index maps\n * to the position in this array.\n *\n * Takes precedence over the top-level `voice` option.\n */\n referenceId: z.union([z.string(), z.array(z.string())]).optional(),\n\n /**\n * Output sample rate in Hz. Falls back to the format default when unset\n * (44100 Hz for wav/pcm/mp3, 48000 Hz for opus).\n */\n sampleRate: z.number().int().positive().optional(),\n\n /**\n * Bitrate in kbps for mp3 output. Ignored for other formats.\n */\n mp3Bitrate: z\n .union([z.literal(64), z.literal(128), z.literal(192)])\n .optional(),\n\n /**\n * Bitrate in bps for opus output, where `-1000` selects automatic. Ignored\n * for other formats.\n */\n opusBitrate: z\n .union([\n z.literal(-1000),\n z.literal(24_000),\n z.literal(32_000),\n z.literal(48_000),\n z.literal(64_000),\n ])\n .optional(),\n\n /**\n * Latency/quality tradeoff. `normal` gives the best quality, `balanced`\n * reduces latency, and `low` is the fastest.\n */\n latency: z.enum(['low', 'normal', 'balanced']).optional(),\n\n /**\n * Volume offset in dB. Negative values are quieter.\n */\n volume: z.number().optional(),\n\n /**\n * Loudness normalization. Supported by the S2 family (`s2-pro` and\n * `s2.1-pro`). Fish Audio accepts it on `s1` but ignores it, so the provider\n * emits a warning in that case.\n */\n normalizeLoudness: z.boolean().optional(),\n\n /**\n * Governs expressiveness. Higher values are more varied, lower values more\n * consistent.\n */\n temperature: z.number().min(0).max(1).optional(),\n\n /**\n * Controls diversity via nucleus sampling.\n */\n topP: z.number().min(0).max(1).optional(),\n\n /**\n * Text segment size for processing.\n */\n chunkLength: z.number().int().min(100).max(300).optional(),\n\n /**\n * Minimum characters before splitting into a new chunk.\n */\n minChunkLength: z.number().int().min(0).max(100).optional(),\n\n /**\n * Text normalization for English and Chinese. Helps stability with numbers.\n */\n normalize: z.boolean().optional(),\n\n /**\n * Maximum audio tokens to generate per text chunk.\n */\n maxNewTokens: z.number().int().positive().optional(),\n\n /**\n * Values above 1.0 discourage repeated audio patterns.\n */\n repetitionPenalty: z.number().optional(),\n\n /**\n * Reuse prior audio as context for voice consistency across chunks.\n */\n conditionOnPreviousChunks: z.boolean().optional(),\n\n /**\n * Early-stop threshold used in batch processing.\n */\n earlyStopThreshold: z.number().min(0).max(1).optional(),\n\n /**\n * Request-scoped flags passed through to the inference backend, e.g.\n * `['quality-guard']`.\n */\n features: z.array(z.string()).optional(),\n});\n\nexport type FishAudioSpeechModelOptions = z.infer<\n typeof fishAudioSpeechModelOptionsSchema\n>;\n","import type { SharedV3Warning, TranscriptionModelV3 } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n convertBase64ToUint8Array,\n createJsonResponseHandler,\n mediaTypeToExtension,\n parseProviderOptions,\n postFormDataToApi,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport type { FishAudioConfig } from './fish-audio-config';\nimport { fishAudioFailedResponseHandler } from './fish-audio-error';\nimport { fishAudioTranscriptionModelOptionsSchema } from './fish-audio-transcription-model-options';\nimport type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';\n\ninterface FishAudioTranscriptionModelConfig extends FishAudioConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class FishAudioTranscriptionModel implements TranscriptionModelV3 {\n readonly specificationVersion = 'v3';\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: FishAudioTranscriptionModelId,\n private readonly config: FishAudioTranscriptionModelConfig,\n ) {}\n\n private async getArgs({\n audio,\n mediaType,\n providerOptions,\n }: Parameters<TranscriptionModelV3['doGenerate']>[0]) {\n const warnings: SharedV3Warning[] = [];\n\n const fishAudioOptions = await parseProviderOptions({\n provider: 'fishAudio',\n providerOptions,\n schema: fishAudioTranscriptionModelOptionsSchema,\n });\n\n const formData = new FormData();\n const blob =\n audio instanceof Uint8Array\n ? new Blob([audio])\n : new Blob([convertBase64ToUint8Array(audio)]);\n\n formData.append(\n 'audio',\n new File([blob], 'audio', { type: mediaType }),\n `audio.${mediaTypeToExtension(mediaType)}`,\n );\n\n if (fishAudioOptions?.language != null) {\n formData.append('language', fishAudioOptions.language);\n }\n\n // Fish Audio defaults `ignore_timestamps` to true, which leaves the\n // transcription result without segments. Request timestamps by default and\n // let callers opt back out.\n formData.append(\n 'ignore_timestamps',\n String(fishAudioOptions?.ignoreTimestamps ?? false),\n );\n\n return { formData, warnings };\n }\n\n async doGenerate(\n options: Parameters<TranscriptionModelV3['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<TranscriptionModelV3['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { formData, warnings } = await this.getArgs(options);\n\n const {\n value: response,\n responseHeaders,\n rawValue: rawResponse,\n } = await postFormDataToApi({\n url: this.config.url({ path: '/v1/asr', modelId: this.modelId }),\n headers: combineHeaders(this.config.headers?.(), options.headers),\n formData,\n failedResponseHandler: fishAudioFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n fishAudioTranscriptionResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n const segments =\n response.segments?.map(segment => ({\n text: segment.text,\n startSecond: segment.start,\n endSecond: segment.end,\n })) ?? [];\n\n return {\n text: response.text,\n segments,\n // `language_code` is absent from the documented response schema but is\n // returned in practice, and reflects the detected language rather than\n // the requested one.\n language: response.language_code ?? undefined,\n durationInSeconds: response.duration ?? undefined,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n ...(response.language != null && {\n providerMetadata: {\n fishAudio: {\n // Human-readable display name, e.g. `English`. Its exact form is\n // not guaranteed, so `language` above (the ISO-639-1 code) is the\n // value to branch on.\n language: response.language,\n },\n },\n }),\n };\n }\n}\n\nconst fishAudioTranscriptionResponseSchema = z.object({\n text: z.string(),\n // `language` and `language_code` are undocumented but returned in practice.\n // Human-readable name, e.g. `English`.\n language: z.string().nullish(),\n // ISO-639-1 code, e.g. `en`.\n language_code: z.string().nullish(),\n duration: z.number().nullish(),\n segments: z\n .array(\n z.object({\n text: z.string(),\n start: z.number(),\n end: z.number(),\n }),\n )\n .nullish(),\n});\n","import { z } from 'zod/v4';\n\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/speech-to-text\nexport const fishAudioTranscriptionModelOptionsSchema = z.object({\n /**\n * Language of the audio.\n *\n * A hint only. Fish Audio passes it to the model, but auto-detection is\n * authoritative and overrides it, so this changes neither the transcript nor\n * the reported language. The detected language is reported as\n * `result.language`.\n */\n language: z.string().optional(),\n\n /**\n * Whether to skip precise timestamps. Mirrors the Fish Audio\n * `ignore_timestamps` parameter, whose API default is `true`.\n *\n * This provider defaults it to `false` so that `result.segments` is\n * populated. Fish Audio documents an added latency cost for audio shorter\n * than 30 seconds; set this to `true` to trade segments for that latency.\n */\n ignoreTimestamps: z.boolean().optional(),\n});\n\nexport type FishAudioTranscriptionModelOptions = z.infer<\n typeof fishAudioTranscriptionModelOptionsSchema\n>;\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":"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","names":["z","combineHeaders","parseProviderOptions","z","z","parseProviderOptions","combineHeaders","z"]}
1
+ {"version":3,"sources":["../src/fish-audio-provider.ts","../src/fish-audio-speech-model.ts","../src/fish-audio-error.ts","../src/fish-audio-speech-model-options.ts","../src/fish-audio-transcription-model.ts","../src/fish-audio-transcription-model-options.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type ProviderV4,\n type SpeechModelV4,\n type TranscriptionModelV4,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { FishAudioSpeechModel } from './fish-audio-speech-model';\nimport type { FishAudioSpeechModelId } from './fish-audio-speech-options';\nimport { FishAudioTranscriptionModel } from './fish-audio-transcription-model';\nimport type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';\nimport { VERSION } from './version';\n\nexport interface FishAudioProvider extends ProviderV4 {\n (\n modelId: FishAudioSpeechModelId,\n settings?: {},\n ): {\n speech: FishAudioSpeechModel;\n };\n\n /**\n * Creates a model for speech generation.\n */\n speech(modelId: FishAudioSpeechModelId): SpeechModelV4;\n\n /**\n * Creates a model for speech generation.\n *\n * Narrowed to required: Fish Audio always provides speech models.\n */\n speechModel(modelId: FishAudioSpeechModelId): SpeechModelV4;\n\n /**\n * Creates a model for transcription.\n */\n transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV4;\n\n /**\n * Creates a model for transcription.\n *\n * Narrowed to required: Fish Audio always provides a transcription model.\n */\n transcriptionModel(\n modelId?: FishAudioTranscriptionModelId,\n ): TranscriptionModelV4;\n}\n\nexport interface FishAudioProviderSettings {\n /**\n * API key for authenticating requests.\n */\n apiKey?: string;\n\n /**\n * Base URL for the API calls.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept requests,\n * or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.fish.audio';\n\n/**\n * Create a Fish Audio provider instance.\n */\nexport function createFishAudio(\n options: FishAudioProviderSettings = {},\n): FishAudioProvider {\n const baseURL = options.baseURL?.replace(/\\/$/, '') ?? DEFAULT_BASE_URL;\n\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'FISH_AUDIO_API_KEY',\n description: 'Fish Audio',\n })}`,\n ...options.headers,\n },\n `ai-sdk/fish-audio/${VERSION}`,\n );\n\n const createSpeechModel = (modelId: FishAudioSpeechModelId) =>\n new FishAudioSpeechModel(modelId, {\n provider: 'fish-audio.speech',\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n // `/v1/asr` has no model selector, so the model ID is a routing label and\n // defaults to `transcribe-1`.\n const createTranscriptionModel = (\n modelId: FishAudioTranscriptionModelId = 'transcribe-1',\n ) =>\n new FishAudioTranscriptionModel(modelId, {\n provider: 'fish-audio.transcription',\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const provider = function (modelId: FishAudioSpeechModelId) {\n return {\n speech: createSpeechModel(modelId),\n };\n };\n\n provider.specificationVersion = 'v4' as const;\n provider.speech = createSpeechModel;\n provider.speechModel = createSpeechModel;\n provider.transcription = createTranscriptionModel;\n provider.transcriptionModel = createTranscriptionModel;\n\n // Required ProviderV4 methods that are not supported\n provider.languageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n message: 'Fish Audio does not provide language models',\n });\n };\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n message: 'Fish Audio does not provide embedding models',\n });\n };\n provider.textEmbeddingModel = provider.embeddingModel;\n\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'imageModel',\n message: 'Fish Audio does not provide image models',\n });\n };\n\n return provider as FishAudioProvider;\n}\n\n/**\n * Default Fish Audio provider instance.\n */\nexport const fishAudio = createFishAudio();\n","import type { SharedV4Warning, SpeechModelV4 } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n createBinaryResponseHandler,\n parseProviderOptions,\n postJsonToApi,\n serializeModelOptions,\n WORKFLOW_DESERIALIZE,\n WORKFLOW_SERIALIZE,\n} from '@ai-sdk/provider-utils';\nimport type { FishAudioConfig } from './fish-audio-config';\nimport { fishAudioFailedResponseHandler } from './fish-audio-error';\nimport type {\n FishAudioSpeechAPITypes,\n FishAudioSpeechFormat,\n FishAudioProsodyControl,\n} from './fish-audio-speech-api-types';\nimport { fishAudioSpeechModelOptionsSchema } from './fish-audio-speech-model-options';\nimport type { FishAudioSpeechModelId } from './fish-audio-speech-options';\n\ninterface FishAudioSpeechModelConfig extends FishAudioConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nconst SUPPORTED_FORMATS: FishAudioSpeechFormat[] = [\n 'wav',\n 'pcm',\n 'mp3',\n 'opus',\n];\n\nconst DEFAULT_FORMAT: FishAudioSpeechFormat = 'mp3';\n\n// Fish Audio accepts `prosody.speed` between 0.5 and 2.0.\nconst MIN_SPEED = 0.5;\nconst MAX_SPEED = 2;\n\nfunction resolveFormat({\n outputFormat,\n warnings,\n}: {\n outputFormat: string | undefined;\n warnings: SharedV4Warning[];\n}): FishAudioSpeechFormat {\n if (outputFormat == null) {\n return DEFAULT_FORMAT;\n }\n\n const normalized = outputFormat.toLowerCase();\n const matched = SUPPORTED_FORMATS.find(format => format === normalized);\n\n if (matched == null) {\n warnings.push({\n type: 'unsupported',\n feature: 'outputFormat',\n details: `Fish Audio does not support the output format \"${outputFormat}\". Falling back to ${DEFAULT_FORMAT}. Supported formats are ${SUPPORTED_FORMATS.join(', ')}.`,\n });\n return DEFAULT_FORMAT;\n }\n\n return matched;\n}\n\nexport class FishAudioSpeechModel implements SpeechModelV4 {\n readonly specificationVersion = 'v4';\n\n get provider(): string {\n return this.config.provider;\n }\n\n static [WORKFLOW_SERIALIZE](model: FishAudioSpeechModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: FishAudioSpeechModelId;\n config: FishAudioSpeechModelConfig;\n }) {\n return new FishAudioSpeechModel(options.modelId, options.config);\n }\n\n constructor(\n readonly modelId: FishAudioSpeechModelId,\n private readonly config: FishAudioSpeechModelConfig,\n ) {}\n\n private async getArgs({\n text,\n voice,\n outputFormat,\n instructions,\n language,\n speed,\n providerOptions,\n }: Parameters<SpeechModelV4['doGenerate']>[0]) {\n const warnings: SharedV4Warning[] = [];\n\n const fishAudioOptions = await parseProviderOptions({\n provider: 'fishAudio',\n providerOptions,\n schema: fishAudioSpeechModelOptionsSchema,\n });\n\n const format = resolveFormat({ outputFormat, warnings });\n\n const requestBody: FishAudioSpeechAPITypes = {\n text,\n format,\n };\n\n // `providerOptions.fishAudio.referenceId` wins over the generic `voice` so\n // that multi-speaker arrays are expressible.\n const referenceId = fishAudioOptions?.referenceId ?? voice;\n if (referenceId != null) {\n requestBody.reference_id = referenceId;\n }\n\n const prosody: FishAudioProsodyControl = {};\n\n if (speed != null) {\n if (speed >= MIN_SPEED && speed <= MAX_SPEED) {\n prosody.speed = speed;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'speed',\n details: `Fish Audio speed must be between ${MIN_SPEED} and ${MAX_SPEED}. The speed option was ignored.`,\n });\n }\n }\n\n if (fishAudioOptions?.volume != null) {\n prosody.volume = fishAudioOptions.volume;\n }\n\n if (fishAudioOptions?.normalizeLoudness != null) {\n // Fish Audio accepts `normalize_loudness` on s1 but ignores it, so warn\n // rather than let it silently do nothing. Only s1 is known to ignore it;\n // unrecognized model IDs are left alone.\n if (this.modelId === 's1') {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.normalizeLoudness',\n details:\n 'Fish Audio ignores normalizeLoudness on s1. It is supported by the S2 family (s2-pro, s2.1-pro).',\n });\n } else {\n prosody.normalize_loudness = fishAudioOptions.normalizeLoudness;\n }\n }\n\n if (Object.keys(prosody).length > 0) {\n requestBody.prosody = prosody;\n }\n\n if (language != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'language',\n details:\n 'Fish Audio infers the language from the input text and the selected voice, and has no language parameter. The language option was ignored.',\n });\n }\n\n if (instructions != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'instructions',\n details:\n 'Fish Audio does not support instructions. The instructions option was ignored.',\n });\n }\n\n if (fishAudioOptions != null) {\n if (fishAudioOptions.sampleRate != null) {\n requestBody.sample_rate = fishAudioOptions.sampleRate;\n }\n\n if (fishAudioOptions.mp3Bitrate != null) {\n if (format === 'mp3') {\n requestBody.mp3_bitrate = fishAudioOptions.mp3Bitrate;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.mp3Bitrate',\n details: `mp3Bitrate only applies to mp3 output. The option was ignored for ${format} output.`,\n });\n }\n }\n\n if (fishAudioOptions.opusBitrate != null) {\n if (format === 'opus') {\n requestBody.opus_bitrate = fishAudioOptions.opusBitrate;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.opusBitrate',\n details: `opusBitrate only applies to opus output. The option was ignored for ${format} output.`,\n });\n }\n }\n\n if (fishAudioOptions.latency != null) {\n requestBody.latency = fishAudioOptions.latency;\n }\n\n if (fishAudioOptions.temperature != null) {\n requestBody.temperature = fishAudioOptions.temperature;\n }\n\n if (fishAudioOptions.topP != null) {\n requestBody.top_p = fishAudioOptions.topP;\n }\n\n if (fishAudioOptions.chunkLength != null) {\n requestBody.chunk_length = fishAudioOptions.chunkLength;\n }\n\n if (fishAudioOptions.minChunkLength != null) {\n requestBody.min_chunk_length = fishAudioOptions.minChunkLength;\n }\n\n if (fishAudioOptions.normalize != null) {\n requestBody.normalize = fishAudioOptions.normalize;\n }\n\n if (fishAudioOptions.maxNewTokens != null) {\n requestBody.max_new_tokens = fishAudioOptions.maxNewTokens;\n }\n\n if (fishAudioOptions.repetitionPenalty != null) {\n requestBody.repetition_penalty = fishAudioOptions.repetitionPenalty;\n }\n\n if (fishAudioOptions.conditionOnPreviousChunks != null) {\n requestBody.condition_on_previous_chunks =\n fishAudioOptions.conditionOnPreviousChunks;\n }\n\n if (fishAudioOptions.earlyStopThreshold != null) {\n requestBody.early_stop_threshold = fishAudioOptions.earlyStopThreshold;\n }\n\n if (fishAudioOptions.features != null) {\n requestBody.features = fishAudioOptions.features;\n }\n }\n\n return { requestBody, warnings };\n }\n\n async doGenerate(\n options: Parameters<SpeechModelV4['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { requestBody, warnings } = await this.getArgs(options);\n\n const {\n value: audio,\n responseHeaders,\n rawValue: rawResponse,\n } = await postJsonToApi({\n url: this.config.url({ path: '/v1/tts', modelId: this.modelId }),\n // Fish Audio selects the TTS model with a `model` HTTP header rather\n // than a request body field.\n headers: combineHeaders(\n this.config.headers?.(),\n { model: this.modelId },\n options.headers,\n ),\n body: requestBody,\n failedResponseHandler: fishAudioFailedResponseHandler,\n successfulResponseHandler: createBinaryResponseHandler(),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n return {\n audio,\n warnings,\n request: {\n body: JSON.stringify(requestBody),\n },\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n };\n }\n}\n","import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\n// Fish Audio returns `{ status, message }` for documented error responses\n// (401 no permission, 402 no payment).\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\nexport const fishAudioErrorDataSchema = z.object({\n status: z.number().nullish(),\n message: z.string().nullish(),\n});\n\nexport type FishAudioErrorData = z.infer<typeof fishAudioErrorDataSchema>;\n\nexport const fishAudioFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: fishAudioErrorDataSchema,\n errorToMessage: data => data.message ?? 'Unknown Fish Audio error',\n});\n","import { z } from 'zod/v4';\n\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\nexport const fishAudioSpeechModelOptionsSchema = z.object({\n /**\n * Voice model ID(s). A single ID selects one speaker; an array enables\n * multi-speaker dialogue (S2-Pro models), in which case the text must mark\n * turns with speaker tokens such as `<|speaker:0|>`. The speaker index maps\n * to the position in this array.\n *\n * Takes precedence over the top-level `voice` option.\n */\n referenceId: z.union([z.string(), z.array(z.string())]).optional(),\n\n /**\n * Output sample rate in Hz. Falls back to the format default when unset\n * (44100 Hz for wav/pcm/mp3, 48000 Hz for opus).\n */\n sampleRate: z.number().int().positive().optional(),\n\n /**\n * Bitrate in kbps for mp3 output. Ignored for other formats.\n */\n mp3Bitrate: z\n .union([z.literal(64), z.literal(128), z.literal(192)])\n .optional(),\n\n /**\n * Bitrate in bps for opus output, where `-1000` selects automatic. Ignored\n * for other formats.\n */\n opusBitrate: z\n .union([\n z.literal(-1000),\n z.literal(24_000),\n z.literal(32_000),\n z.literal(48_000),\n z.literal(64_000),\n ])\n .optional(),\n\n /**\n * Latency/quality tradeoff. `normal` gives the best quality, `balanced`\n * reduces latency, and `low` is the fastest.\n */\n latency: z.enum(['low', 'normal', 'balanced']).optional(),\n\n /**\n * Volume offset in dB. Negative values are quieter.\n */\n volume: z.number().optional(),\n\n /**\n * Loudness normalization. Supported by the S2 family (`s2-pro` and\n * `s2.1-pro`). Fish Audio accepts it on `s1` but ignores it, so the provider\n * emits a warning in that case.\n */\n normalizeLoudness: z.boolean().optional(),\n\n /**\n * Governs expressiveness. Higher values are more varied, lower values more\n * consistent.\n */\n temperature: z.number().min(0).max(1).optional(),\n\n /**\n * Controls diversity via nucleus sampling.\n */\n topP: z.number().min(0).max(1).optional(),\n\n /**\n * Text segment size for processing.\n */\n chunkLength: z.number().int().min(100).max(300).optional(),\n\n /**\n * Minimum characters before splitting into a new chunk.\n */\n minChunkLength: z.number().int().min(0).max(100).optional(),\n\n /**\n * Text normalization for English and Chinese. Helps stability with numbers.\n */\n normalize: z.boolean().optional(),\n\n /**\n * Maximum audio tokens to generate per text chunk.\n */\n maxNewTokens: z.number().int().positive().optional(),\n\n /**\n * Values above 1.0 discourage repeated audio patterns.\n */\n repetitionPenalty: z.number().optional(),\n\n /**\n * Reuse prior audio as context for voice consistency across chunks.\n */\n conditionOnPreviousChunks: z.boolean().optional(),\n\n /**\n * Early-stop threshold used in batch processing.\n */\n earlyStopThreshold: z.number().min(0).max(1).optional(),\n\n /**\n * Request-scoped flags passed through to the inference backend, e.g.\n * `['quality-guard']`.\n */\n features: z.array(z.string()).optional(),\n});\n\nexport type FishAudioSpeechModelOptions = z.infer<\n typeof fishAudioSpeechModelOptionsSchema\n>;\n","import type { SharedV4Warning, TranscriptionModelV4 } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n convertBase64ToUint8Array,\n createJsonResponseHandler,\n mediaTypeToExtension,\n parseProviderOptions,\n postFormDataToApi,\n serializeModelOptions,\n WORKFLOW_DESERIALIZE,\n WORKFLOW_SERIALIZE,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport type { FishAudioConfig } from './fish-audio-config';\nimport { fishAudioFailedResponseHandler } from './fish-audio-error';\nimport { fishAudioTranscriptionModelOptionsSchema } from './fish-audio-transcription-model-options';\nimport type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';\n\ninterface FishAudioTranscriptionModelConfig extends FishAudioConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class FishAudioTranscriptionModel implements TranscriptionModelV4 {\n readonly specificationVersion = 'v4';\n\n get provider(): string {\n return this.config.provider;\n }\n\n static [WORKFLOW_SERIALIZE](model: FishAudioTranscriptionModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: FishAudioTranscriptionModelId;\n config: FishAudioTranscriptionModelConfig;\n }) {\n return new FishAudioTranscriptionModel(options.modelId, options.config);\n }\n\n constructor(\n readonly modelId: FishAudioTranscriptionModelId,\n private readonly config: FishAudioTranscriptionModelConfig,\n ) {}\n\n private async getArgs({\n audio,\n mediaType,\n providerOptions,\n }: Parameters<TranscriptionModelV4['doGenerate']>[0]) {\n const warnings: SharedV4Warning[] = [];\n\n const fishAudioOptions = await parseProviderOptions({\n provider: 'fishAudio',\n providerOptions,\n schema: fishAudioTranscriptionModelOptionsSchema,\n });\n\n const formData = new FormData();\n const blob =\n audio instanceof Uint8Array\n ? new Blob([audio])\n : new Blob([convertBase64ToUint8Array(audio)]);\n\n formData.append(\n 'audio',\n new File([blob], 'audio', { type: mediaType }),\n `audio.${mediaTypeToExtension(mediaType)}`,\n );\n\n if (fishAudioOptions?.language != null) {\n formData.append('language', fishAudioOptions.language);\n }\n\n // Fish Audio defaults `ignore_timestamps` to true, which leaves the\n // transcription result without segments. Request timestamps by default and\n // let callers opt back out.\n formData.append(\n 'ignore_timestamps',\n String(fishAudioOptions?.ignoreTimestamps ?? false),\n );\n\n return { formData, warnings };\n }\n\n async doGenerate(\n options: Parameters<TranscriptionModelV4['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { formData, warnings } = await this.getArgs(options);\n\n const {\n value: response,\n responseHeaders,\n rawValue: rawResponse,\n } = await postFormDataToApi({\n url: this.config.url({ path: '/v1/asr', modelId: this.modelId }),\n headers: combineHeaders(this.config.headers?.(), options.headers),\n formData,\n failedResponseHandler: fishAudioFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n fishAudioTranscriptionResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n const segments =\n response.segments?.map(segment => ({\n text: segment.text,\n startSecond: segment.start,\n endSecond: segment.end,\n })) ?? [];\n\n return {\n text: response.text,\n segments,\n // `language_code` is absent from the documented response schema but is\n // returned in practice, and reflects the detected language rather than\n // the requested one.\n language: response.language_code ?? undefined,\n durationInSeconds: response.duration ?? undefined,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n ...(response.language != null && {\n providerMetadata: {\n fishAudio: {\n // Human-readable display name, e.g. `English`. Its exact form is\n // not guaranteed, so `language` above (the ISO-639-1 code) is the\n // value to branch on.\n language: response.language,\n },\n },\n }),\n };\n }\n}\n\nconst fishAudioTranscriptionResponseSchema = z.object({\n text: z.string(),\n // `language` and `language_code` are undocumented but returned in practice.\n // Human-readable name, e.g. `English`.\n language: z.string().nullish(),\n // ISO-639-1 code, e.g. `en`.\n language_code: z.string().nullish(),\n duration: z.number().nullish(),\n segments: z\n .array(\n z.object({\n text: z.string(),\n start: z.number(),\n end: z.number(),\n }),\n )\n .nullish(),\n});\n","import { z } from 'zod/v4';\n\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/speech-to-text\nexport const fishAudioTranscriptionModelOptionsSchema = z.object({\n /**\n * Language of the audio.\n *\n * A hint only. Fish Audio passes it to the model, but auto-detection is\n * authoritative and overrides it, so this changes neither the transcript nor\n * the reported language. The detected language is reported as\n * `result.language`.\n */\n language: z.string().optional(),\n\n /**\n * Whether to skip precise timestamps. Mirrors the Fish Audio\n * `ignore_timestamps` parameter, whose API default is `true`.\n *\n * This provider defaults it to `false` so that `result.segments` is\n * populated. Fish Audio documents an added latency cost for audio shorter\n * than 30 seconds; set this to `true` to trade segments for that latency.\n */\n ignoreTimestamps: z.boolean().optional(),\n});\n\nexport type FishAudioTranscriptionModelOptions = z.infer<\n typeof fishAudioTranscriptionModelOptionsSchema\n>;\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":"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","names":["z","combineHeaders","parseProviderOptions","serializeModelOptions","WORKFLOW_DESERIALIZE","WORKFLOW_SERIALIZE","z","z","WORKFLOW_SERIALIZE","serializeModelOptions","WORKFLOW_DESERIALIZE","parseProviderOptions","combineHeaders","z"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/fish-audio",
3
- "version": "2.0.0",
3
+ "version": "3.0.1",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -29,22 +29,22 @@
29
29
  }
30
30
  },
31
31
  "dependencies": {
32
- "@ai-sdk/provider": "3.0.14",
33
- "@ai-sdk/provider-utils": "4.0.41"
32
+ "@ai-sdk/provider": "4.0.6",
33
+ "@ai-sdk/provider-utils": "5.0.23"
34
34
  },
35
35
  "devDependencies": {
36
- "@types/node": "20.17.24",
37
- "tsup": "^8",
36
+ "@types/node": "22.19.19",
37
+ "tsup": "^8.5.1",
38
38
  "typescript": "5.6.3",
39
39
  "zod": "3.25.76",
40
- "@ai-sdk/test-server": "1.0.6",
40
+ "@ai-sdk/test-server": "2.0.1",
41
41
  "@vercel/ai-tsconfig": "0.0.0"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "zod": "^3.25.76 || ^4.1.8"
45
45
  },
46
46
  "engines": {
47
- "node": ">=18"
47
+ "node": ">=22"
48
48
  },
49
49
  "publishConfig": {
50
50
  "access": "public",
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  NoSuchModelError,
3
- type ProviderV3,
4
- type SpeechModelV3,
5
- type TranscriptionModelV3,
3
+ type ProviderV4,
4
+ type SpeechModelV4,
5
+ type TranscriptionModelV4,
6
6
  } from '@ai-sdk/provider';
7
7
  import {
8
8
  loadApiKey,
@@ -15,7 +15,7 @@ import { FishAudioTranscriptionModel } from './fish-audio-transcription-model';
15
15
  import type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';
16
16
  import { VERSION } from './version';
17
17
 
18
- export interface FishAudioProvider extends ProviderV3 {
18
+ export interface FishAudioProvider extends ProviderV4 {
19
19
  (
20
20
  modelId: FishAudioSpeechModelId,
21
21
  settings?: {},
@@ -26,19 +26,19 @@ export interface FishAudioProvider extends ProviderV3 {
26
26
  /**
27
27
  * Creates a model for speech generation.
28
28
  */
29
- speech(modelId: FishAudioSpeechModelId): SpeechModelV3;
29
+ speech(modelId: FishAudioSpeechModelId): SpeechModelV4;
30
30
 
31
31
  /**
32
32
  * Creates a model for speech generation.
33
33
  *
34
34
  * Narrowed to required: Fish Audio always provides speech models.
35
35
  */
36
- speechModel(modelId: FishAudioSpeechModelId): SpeechModelV3;
36
+ speechModel(modelId: FishAudioSpeechModelId): SpeechModelV4;
37
37
 
38
38
  /**
39
39
  * Creates a model for transcription.
40
40
  */
41
- transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV3;
41
+ transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV4;
42
42
 
43
43
  /**
44
44
  * Creates a model for transcription.
@@ -47,7 +47,7 @@ export interface FishAudioProvider extends ProviderV3 {
47
47
  */
48
48
  transcriptionModel(
49
49
  modelId?: FishAudioTranscriptionModelId,
50
- ): TranscriptionModelV3;
50
+ ): TranscriptionModelV4;
51
51
  }
52
52
 
53
53
  export interface FishAudioProviderSettings {
@@ -122,13 +122,13 @@ export function createFishAudio(
122
122
  };
123
123
  };
124
124
 
125
- provider.specificationVersion = 'v3' as const;
125
+ provider.specificationVersion = 'v4' as const;
126
126
  provider.speech = createSpeechModel;
127
127
  provider.speechModel = createSpeechModel;
128
128
  provider.transcription = createTranscriptionModel;
129
129
  provider.transcriptionModel = createTranscriptionModel;
130
130
 
131
- // Required ProviderV3 methods that are not supported
131
+ // Required ProviderV4 methods that are not supported
132
132
  provider.languageModel = (modelId: string) => {
133
133
  throw new NoSuchModelError({
134
134
  modelId,
@@ -1,9 +1,12 @@
1
- import type { SharedV3Warning, SpeechModelV3 } from '@ai-sdk/provider';
1
+ import type { SharedV4Warning, SpeechModelV4 } from '@ai-sdk/provider';
2
2
  import {
3
3
  combineHeaders,
4
4
  createBinaryResponseHandler,
5
5
  parseProviderOptions,
6
6
  postJsonToApi,
7
+ serializeModelOptions,
8
+ WORKFLOW_DESERIALIZE,
9
+ WORKFLOW_SERIALIZE,
7
10
  } from '@ai-sdk/provider-utils';
8
11
  import type { FishAudioConfig } from './fish-audio-config';
9
12
  import { fishAudioFailedResponseHandler } from './fish-audio-error';
@@ -39,7 +42,7 @@ function resolveFormat({
39
42
  warnings,
40
43
  }: {
41
44
  outputFormat: string | undefined;
42
- warnings: SharedV3Warning[];
45
+ warnings: SharedV4Warning[];
43
46
  }): FishAudioSpeechFormat {
44
47
  if (outputFormat == null) {
45
48
  return DEFAULT_FORMAT;
@@ -60,13 +63,27 @@ function resolveFormat({
60
63
  return matched;
61
64
  }
62
65
 
63
- export class FishAudioSpeechModel implements SpeechModelV3 {
64
- readonly specificationVersion = 'v3';
66
+ export class FishAudioSpeechModel implements SpeechModelV4 {
67
+ readonly specificationVersion = 'v4';
65
68
 
66
69
  get provider(): string {
67
70
  return this.config.provider;
68
71
  }
69
72
 
73
+ static [WORKFLOW_SERIALIZE](model: FishAudioSpeechModel) {
74
+ return serializeModelOptions({
75
+ modelId: model.modelId,
76
+ config: model.config,
77
+ });
78
+ }
79
+
80
+ static [WORKFLOW_DESERIALIZE](options: {
81
+ modelId: FishAudioSpeechModelId;
82
+ config: FishAudioSpeechModelConfig;
83
+ }) {
84
+ return new FishAudioSpeechModel(options.modelId, options.config);
85
+ }
86
+
70
87
  constructor(
71
88
  readonly modelId: FishAudioSpeechModelId,
72
89
  private readonly config: FishAudioSpeechModelConfig,
@@ -80,8 +97,8 @@ export class FishAudioSpeechModel implements SpeechModelV3 {
80
97
  language,
81
98
  speed,
82
99
  providerOptions,
83
- }: Parameters<SpeechModelV3['doGenerate']>[0]) {
84
- const warnings: SharedV3Warning[] = [];
100
+ }: Parameters<SpeechModelV4['doGenerate']>[0]) {
101
+ const warnings: SharedV4Warning[] = [];
85
102
 
86
103
  const fishAudioOptions = await parseProviderOptions({
87
104
  provider: 'fishAudio',
@@ -238,8 +255,8 @@ export class FishAudioSpeechModel implements SpeechModelV3 {
238
255
  }
239
256
 
240
257
  async doGenerate(
241
- options: Parameters<SpeechModelV3['doGenerate']>[0],
242
- ): Promise<Awaited<ReturnType<SpeechModelV3['doGenerate']>>> {
258
+ options: Parameters<SpeechModelV4['doGenerate']>[0],
259
+ ): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>> {
243
260
  const currentDate = this.config._internal?.currentDate?.() ?? new Date();
244
261
  const { requestBody, warnings } = await this.getArgs(options);
245
262
 
@@ -1,4 +1,4 @@
1
- import type { SharedV3Warning, TranscriptionModelV3 } from '@ai-sdk/provider';
1
+ import type { SharedV4Warning, TranscriptionModelV4 } from '@ai-sdk/provider';
2
2
  import {
3
3
  combineHeaders,
4
4
  convertBase64ToUint8Array,
@@ -6,6 +6,9 @@ import {
6
6
  mediaTypeToExtension,
7
7
  parseProviderOptions,
8
8
  postFormDataToApi,
9
+ serializeModelOptions,
10
+ WORKFLOW_DESERIALIZE,
11
+ WORKFLOW_SERIALIZE,
9
12
  } from '@ai-sdk/provider-utils';
10
13
  import { z } from 'zod/v4';
11
14
  import type { FishAudioConfig } from './fish-audio-config';
@@ -19,13 +22,27 @@ interface FishAudioTranscriptionModelConfig extends FishAudioConfig {
19
22
  };
20
23
  }
21
24
 
22
- export class FishAudioTranscriptionModel implements TranscriptionModelV3 {
23
- readonly specificationVersion = 'v3';
25
+ export class FishAudioTranscriptionModel implements TranscriptionModelV4 {
26
+ readonly specificationVersion = 'v4';
24
27
 
25
28
  get provider(): string {
26
29
  return this.config.provider;
27
30
  }
28
31
 
32
+ static [WORKFLOW_SERIALIZE](model: FishAudioTranscriptionModel) {
33
+ return serializeModelOptions({
34
+ modelId: model.modelId,
35
+ config: model.config,
36
+ });
37
+ }
38
+
39
+ static [WORKFLOW_DESERIALIZE](options: {
40
+ modelId: FishAudioTranscriptionModelId;
41
+ config: FishAudioTranscriptionModelConfig;
42
+ }) {
43
+ return new FishAudioTranscriptionModel(options.modelId, options.config);
44
+ }
45
+
29
46
  constructor(
30
47
  readonly modelId: FishAudioTranscriptionModelId,
31
48
  private readonly config: FishAudioTranscriptionModelConfig,
@@ -35,8 +52,8 @@ export class FishAudioTranscriptionModel implements TranscriptionModelV3 {
35
52
  audio,
36
53
  mediaType,
37
54
  providerOptions,
38
- }: Parameters<TranscriptionModelV3['doGenerate']>[0]) {
39
- const warnings: SharedV3Warning[] = [];
55
+ }: Parameters<TranscriptionModelV4['doGenerate']>[0]) {
56
+ const warnings: SharedV4Warning[] = [];
40
57
 
41
58
  const fishAudioOptions = await parseProviderOptions({
42
59
  provider: 'fishAudio',
@@ -72,8 +89,8 @@ export class FishAudioTranscriptionModel implements TranscriptionModelV3 {
72
89
  }
73
90
 
74
91
  async doGenerate(
75
- options: Parameters<TranscriptionModelV3['doGenerate']>[0],
76
- ): Promise<Awaited<ReturnType<TranscriptionModelV3['doGenerate']>>> {
92
+ options: Parameters<TranscriptionModelV4['doGenerate']>[0],
93
+ ): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>> {
77
94
  const currentDate = this.config._internal?.currentDate?.() ?? new Date();
78
95
  const { formData, warnings } = await this.getArgs(options);
79
96