@openclaw/fish-audio-speech 2026.9.5 → 2026.9.7

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/assets/icon.png CHANGED
Binary file
@@ -1,7 +1,7 @@
1
- import { FISH_AUDIO_STREAM_MAX_BYTES, fishAudioTts, fishAudioTtsStream, listFishAudioVoices, normalizeFishAudioBaseUrl } from "./tts.js";
1
+ import { fishAudioTts, fishAudioTtsStream, listFishAudioVoices, normalizeFishAudioBaseUrl } from "./tts.js";
2
2
  import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
3
- import { parseSpeechDirectiveNumberOverride, resolveSpeechProviderApiKey } from "openclaw/plugin-sdk/speech-provider";
4
- import { asBoolean, asFiniteNumberInRange, asOptionalRecord, normalizeOptionalString, parseBooleanValue } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { MAX_AUDIO_BYTES, parseSpeechDirectiveNumberOverride, resolveSpeechProviderApiKey } from "openclaw/plugin-sdk/speech-provider";
4
+ import { asBoolean, asFiniteNumberInRange, asOptionalRecord, filterStringRecord, normalizeOptionalString, parseBooleanValue } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  //#region extensions/fish-audio-speech/speech-provider.ts
6
6
  const FISH_AUDIO_MODELS = [
7
7
  "s2.1-pro-free",
@@ -24,12 +24,6 @@ function normalizeLatency(value) {
24
24
  if (latency === "low" || latency === "balanced" || latency === "normal") return latency;
25
25
  throw new Error(`invalid Fish Audio latency "${latency}"`);
26
26
  }
27
- function normalizeNumber(value, min, max) {
28
- return asFiniteNumberInRange(value, {
29
- min,
30
- max
31
- });
32
- }
33
27
  function resolveReferenceId(raw) {
34
28
  return normalizeOptionalString(raw?.speakerVoiceId ?? raw?.voiceId ?? raw?.referenceId);
35
29
  }
@@ -45,26 +39,26 @@ function normalizeProviderConfig(rawConfig) {
45
39
  model: normalizeModel(raw?.model ?? raw?.modelId),
46
40
  referenceId: resolveReferenceId(raw),
47
41
  latency: normalizeLatency(raw?.latency),
48
- speed: normalizeNumber(raw?.speed, .5, 2),
49
- temperature: normalizeNumber(raw?.temperature, 0, 1),
50
- topP: normalizeNumber(raw?.topP ?? raw?.top_p, 0, 1),
42
+ speed: asFiniteNumberInRange(raw?.speed, {
43
+ min: .5,
44
+ max: 2
45
+ }),
46
+ temperature: asFiniteNumberInRange(raw?.temperature, {
47
+ min: 0,
48
+ max: 1
49
+ }),
50
+ topP: asFiniteNumberInRange(raw?.topP ?? raw?.top_p, {
51
+ min: 0,
52
+ max: 1
53
+ }),
51
54
  normalize: asBoolean(raw?.normalize)
52
55
  };
53
56
  }
54
57
  function readProviderConfig(config) {
55
- const defaults = normalizeProviderConfig({});
56
- const raw = asOptionalRecord(config) ?? {};
57
- return {
58
- apiKey: normalizeOptionalString(raw.apiKey) ?? defaults.apiKey,
59
- baseUrl: normalizeFishAudioBaseUrl(normalizeOptionalString(raw.baseUrl) ?? defaults.baseUrl),
60
- model: normalizeModel(raw.model ?? raw.modelId ?? defaults.model),
61
- referenceId: resolveReferenceId(raw) ?? defaults.referenceId,
62
- latency: normalizeLatency(raw.latency ?? defaults.latency),
63
- speed: normalizeNumber(raw.speed, .5, 2) ?? defaults.speed,
64
- temperature: normalizeNumber(raw.temperature, 0, 1) ?? defaults.temperature,
65
- topP: normalizeNumber(raw.topP ?? raw.top_p, 0, 1) ?? defaults.topP,
66
- normalize: asBoolean(raw.normalize) ?? defaults.normalize
67
- };
58
+ return normalizeProviderConfig({ "fish-audio": {
59
+ ...config,
60
+ apiKey: normalizeOptionalString(config.apiKey)
61
+ } });
68
62
  }
69
63
  function readOverrides(overrides) {
70
64
  const raw = asOptionalRecord(overrides) ?? {};
@@ -72,9 +66,18 @@ function readOverrides(overrides) {
72
66
  model: normalizeOptionalString(raw.model ?? raw.modelId) ? normalizeModel(raw.model ?? raw.modelId) : void 0,
73
67
  referenceId: resolveReferenceId(raw),
74
68
  latency: normalizeOptionalString(raw.latency) ? normalizeLatency(raw.latency) : void 0,
75
- speed: normalizeNumber(raw.speed, .5, 2),
76
- temperature: normalizeNumber(raw.temperature, 0, 1),
77
- topP: normalizeNumber(raw.topP ?? raw.top_p, 0, 1),
69
+ speed: asFiniteNumberInRange(raw.speed, {
70
+ min: .5,
71
+ max: 2
72
+ }),
73
+ temperature: asFiniteNumberInRange(raw.temperature, {
74
+ min: 0,
75
+ max: 1
76
+ }),
77
+ topP: asFiniteNumberInRange(raw.topP ?? raw.top_p, {
78
+ min: 0,
79
+ max: 1
80
+ }),
78
81
  normalize: asBoolean(raw.normalize)
79
82
  };
80
83
  }
@@ -241,17 +244,33 @@ function buildFishAudioSpeechProvider() {
241
244
  value: talkProviderConfig.apiKey,
242
245
  path: "talk.providers.fish-audio.apiKey"
243
246
  }) },
244
- ...normalizeOptionalString(talkProviderConfig.baseUrl) == null ? {} : { baseUrl: normalizeFishAudioBaseUrl(normalizeOptionalString(talkProviderConfig.baseUrl)) },
245
- ...normalizeOptionalString(talkProviderConfig.modelId ?? talkProviderConfig.model) == null ? {} : { model: normalizeModel(talkProviderConfig.modelId ?? talkProviderConfig.model) },
246
- ...resolveReferenceId(talkProviderConfig) == null ? {} : { referenceId: resolveReferenceId(talkProviderConfig) },
247
- ...normalizeOptionalString(talkProviderConfig.latency) == null ? {} : { latency: normalizeLatency(talkProviderConfig.latency) },
248
- ...normalizeNumber(talkProviderConfig.speed, .5, 2) == null ? {} : { speed: normalizeNumber(talkProviderConfig.speed, .5, 2) }
247
+ ...filterStringRecord({
248
+ baseUrl: normalizeOptionalString(talkProviderConfig.baseUrl) ? normalizeFishAudioBaseUrl(normalizeOptionalString(talkProviderConfig.baseUrl)) : void 0,
249
+ model: normalizeOptionalString(talkProviderConfig.modelId ?? talkProviderConfig.model) ? normalizeModel(talkProviderConfig.modelId ?? talkProviderConfig.model) : void 0,
250
+ referenceId: resolveReferenceId(talkProviderConfig),
251
+ latency: normalizeOptionalString(talkProviderConfig.latency) ? normalizeLatency(talkProviderConfig.latency) : void 0
252
+ }),
253
+ ...asFiniteNumberInRange(talkProviderConfig.speed, {
254
+ min: .5,
255
+ max: 2
256
+ }) == null ? {} : { speed: asFiniteNumberInRange(talkProviderConfig.speed, {
257
+ min: .5,
258
+ max: 2
259
+ }) }
249
260
  };
250
261
  },
251
262
  resolveTalkOverrides: ({ params }) => ({
252
- ...normalizeOptionalString(params.modelId ?? params.model) == null ? {} : { model: normalizeModel(params.modelId ?? params.model) },
253
- ...resolveReferenceId(params) == null ? {} : { referenceId: resolveReferenceId(params) },
254
- ...normalizeNumber(params.speed, .5, 2) == null ? {} : { speed: normalizeNumber(params.speed, .5, 2) }
263
+ ...filterStringRecord({
264
+ model: normalizeOptionalString(params.modelId ?? params.model) ? normalizeModel(params.modelId ?? params.model) : void 0,
265
+ referenceId: resolveReferenceId(params)
266
+ }),
267
+ ...asFiniteNumberInRange(params.speed, {
268
+ min: .5,
269
+ max: 2
270
+ }) == null ? {} : { speed: asFiniteNumberInRange(params.speed, {
271
+ min: .5,
272
+ max: 2
273
+ }) }
255
274
  }),
256
275
  listVoices: async (req) => {
257
276
  const config = readProviderConfig(req.providerConfig ?? {});
@@ -282,7 +301,7 @@ function buildFishAudioSpeechProvider() {
282
301
  const { resolveGeneratedMediaMaxBytes } = await import("openclaw/plugin-sdk/media-generation-runtime");
283
302
  const stream = await fishAudioTtsStream({
284
303
  ...params,
285
- maxBytes: Math.min(resolveGeneratedMediaMaxBytes(req.cfg, "audio"), FISH_AUDIO_STREAM_MAX_BYTES)
304
+ maxBytes: Math.min(resolveGeneratedMediaMaxBytes(req.cfg, "audio"), MAX_AUDIO_BYTES)
286
305
  });
287
306
  return {
288
307
  audioStream: stream.audioStream,
package/dist/tts.js CHANGED
@@ -1,5 +1,4 @@
1
- import { MAX_AUDIO_BYTES } from "openclaw/plugin-sdk/speech-provider";
2
- import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
1
+ import { asOptionalRecord, normalizeOptionalString, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
3
2
  //#region extensions/fish-audio-speech/tts.ts
4
3
  const FISH_AUDIO_BASE_URL = "https://api.fish.audio";
5
4
  const FISH_AUDIO_VOICES_MAX_BYTES = 2097152;
@@ -79,8 +78,8 @@ function parseVoiceItem(value) {
79
78
  const item = asOptionalRecord(value);
80
79
  const id = normalizeOptionalString(item?.["_id"]);
81
80
  if (!id) return;
82
- const languages = Array.isArray(item?.languages) ? item.languages.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
83
- const tags = Array.isArray(item?.tags) ? item.tags.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
81
+ const languages = normalizeTrimmedStringList(item?.languages);
82
+ const tags = normalizeTrimmedStringList(item?.tags);
84
83
  return {
85
84
  id,
86
85
  name: normalizeOptionalString(item?.title),
@@ -141,6 +140,5 @@ async function listFishAudioVoices(params) {
141
140
  return true;
142
141
  });
143
142
  }
144
- const FISH_AUDIO_STREAM_MAX_BYTES = MAX_AUDIO_BYTES;
145
143
  //#endregion
146
- export { FISH_AUDIO_STREAM_MAX_BYTES, fishAudioTts, fishAudioTtsStream, listFishAudioVoices, normalizeFishAudioBaseUrl };
144
+ export { fishAudioTts, fishAudioTtsStream, listFishAudioVoices, normalizeFishAudioBaseUrl };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fish-audio-speech",
3
- "version": "2026.9.5",
3
+ "version": "2026.9.7",
4
4
  "description": "OpenClaw Fish Audio speech plugin.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,10 +18,10 @@
18
18
  "minHostVersion": ">=2026.7.2"
19
19
  },
20
20
  "compat": {
21
- "pluginApi": ">=2026.9.5"
21
+ "pluginApi": ">=2026.9.7"
22
22
  },
23
23
  "build": {
24
- "openclawVersion": "2026.9.5",
24
+ "openclawVersion": "2026.9.7",
25
25
  "bundledDist": false
26
26
  },
27
27
  "release": {
@@ -40,7 +40,7 @@
40
40
  "assets/activity.svg"
41
41
  ],
42
42
  "peerDependencies": {
43
- "openclaw": ">=2026.9.5"
43
+ "openclaw": ">=2026.9.7"
44
44
  },
45
45
  "peerDependenciesMeta": {
46
46
  "openclaw": {