@openclaw/inworld-speech 2026.7.1 → 2026.7.2-beta.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.
@@ -111,7 +111,8 @@ function buildInworldSpeechProvider() {
111
111
  if (!apiKey) throw new Error("Inworld API key missing");
112
112
  return listInworldVoices({
113
113
  apiKey,
114
- baseUrl: req.baseUrl ?? config?.baseUrl
114
+ baseUrl: req.baseUrl ?? config?.baseUrl,
115
+ timeoutMs: req.timeoutMs
115
116
  });
116
117
  },
117
118
  isConfigured: ({ providerConfig }) => Boolean(readInworldProviderConfig(providerConfig).apiKey || process.env.INWORLD_API_KEY),
package/dist/tts.js CHANGED
@@ -1,13 +1,14 @@
1
1
  import { MAX_AUDIO_BYTES } from "openclaw/plugin-sdk/media-runtime";
2
2
  import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
3
3
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
4
+ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
4
5
  //#region extensions/inworld/tts.ts
5
6
  const DEFAULT_INWORLD_BASE_URL = "https://api.inworld.ai";
6
7
  const DEFAULT_INWORLD_VOICE_ID = "Sarah";
7
8
  const DEFAULT_INWORLD_MODEL_ID = "inworld-tts-1.5-max";
8
9
  const INWORLD_TTS_BODY_MAX_BYTES = MAX_AUDIO_BYTES * 2;
9
10
  const INWORLD_VOICES_BODY_MAX_BYTES = MAX_AUDIO_BYTES;
10
- const INWORLD_BODY_READ_IDLE_TIMEOUT_MS = 3e4;
11
+ const INWORLD_UPSTREAM_IDLE_TIMEOUT_MS = 3e4;
11
12
  const INWORLD_ERROR_BODY_MAX_BYTES = 8 * 1024;
12
13
  const INWORLD_ERROR_BODY_MAX_CHARS = 400;
13
14
  const INWORLD_ERROR_BODY_READ_IDLE_TIMEOUT_MS = 1e4;
@@ -34,7 +35,7 @@ async function readInworldErrorBodySnippet(response) {
34
35
  return error instanceof InworldErrorBodyOverflow ? "(error body exceeded diagnostic limit; truncated)" : "";
35
36
  }
36
37
  const collapsed = buffer.toString("utf8").replace(/\s+/g, " ").trim();
37
- if (collapsed.length > INWORLD_ERROR_BODY_MAX_CHARS) return `${collapsed.slice(0, INWORLD_ERROR_BODY_MAX_CHARS)}…`;
38
+ if (collapsed.length > INWORLD_ERROR_BODY_MAX_CHARS) return `${truncateUtf16Safe(collapsed, INWORLD_ERROR_BODY_MAX_CHARS)}…`;
38
39
  return collapsed;
39
40
  }
40
41
  const INWORLD_TTS_MODELS = [
@@ -93,7 +94,7 @@ async function inworldTTS(params) {
93
94
  throw new Error(`Inworld TTS API error (${response.status}): ${errorBody}`);
94
95
  }
95
96
  const body = (await readResponseWithLimit(response, INWORLD_TTS_BODY_MAX_BYTES, {
96
- chunkTimeoutMs: INWORLD_BODY_READ_IDLE_TIMEOUT_MS,
97
+ chunkTimeoutMs: INWORLD_UPSTREAM_IDLE_TIMEOUT_MS,
97
98
  onOverflow: ({ size, maxBytes }) => /* @__PURE__ */ new Error(`Inworld TTS audio stream too large: ${size} bytes (limit: ${maxBytes} bytes)`),
98
99
  onIdleTimeout: ({ chunkTimeoutMs }) => /* @__PURE__ */ new Error(`Inworld TTS audio stream stalled: no data received for ${chunkTimeoutMs}ms`)
99
100
  })).toString("utf8");
@@ -106,7 +107,7 @@ async function inworldTTS(params) {
106
107
  try {
107
108
  parsed = JSON.parse(trimmed);
108
109
  } catch {
109
- throw new Error(`Inworld TTS stream parse error: unexpected non-JSON line: ${trimmed.slice(0, 80)}`);
110
+ throw new Error(`Inworld TTS stream parse error: unexpected non-JSON line: ${truncateUtf16Safe(trimmed, 80)}`);
110
111
  }
111
112
  if (parsed.error) throw new Error(`Inworld TTS stream error (${parsed.error.code}): ${parsed.error.message}`);
112
113
  if (parsed.result?.audioContent) {
@@ -131,7 +132,7 @@ async function listInworldVoices(params) {
131
132
  method: "GET",
132
133
  headers: { Authorization: `Basic ${params.apiKey}` }
133
134
  },
134
- timeoutMs: params.timeoutMs,
135
+ timeoutMs: params.timeoutMs ?? INWORLD_UPSTREAM_IDLE_TIMEOUT_MS,
135
136
  policy: ssrfPolicyFromInworldBaseUrl(baseUrl),
136
137
  auditContext: "inworld-voices"
137
138
  });
@@ -141,7 +142,7 @@ async function listInworldVoices(params) {
141
142
  throw new Error(`Inworld voices API error (${response.status}): ${errorBody}`);
142
143
  }
143
144
  const voicesBody = (await readResponseWithLimit(response, INWORLD_VOICES_BODY_MAX_BYTES, {
144
- chunkTimeoutMs: INWORLD_BODY_READ_IDLE_TIMEOUT_MS,
145
+ chunkTimeoutMs: INWORLD_UPSTREAM_IDLE_TIMEOUT_MS,
145
146
  onOverflow: ({ size, maxBytes }) => /* @__PURE__ */ new Error(`Inworld voices response too large: ${size} bytes (limit: ${maxBytes} bytes)`),
146
147
  onIdleTimeout: ({ chunkTimeoutMs }) => /* @__PURE__ */ new Error(`Inworld voices response stalled: no data received for ${chunkTimeoutMs}ms`)
147
148
  })).toString("utf8");
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/inworld-speech",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/inworld-speech",
9
- "version": "2026.7.1"
9
+ "version": "2026.7.2-beta.1"
10
10
  }
11
11
  }
12
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/inworld-speech",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.1",
4
4
  "description": "OpenClaw Inworld speech plugin.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,10 +18,10 @@
18
18
  "minHostVersion": ">=2026.6.8"
19
19
  },
20
20
  "compat": {
21
- "pluginApi": ">=2026.7.1"
21
+ "pluginApi": ">=2026.7.2-beta.1"
22
22
  },
23
23
  "build": {
24
- "openclawVersion": "2026.7.1",
24
+ "openclawVersion": "2026.7.2-beta.1",
25
25
  "bundledDist": false
26
26
  },
27
27
  "release": {
@@ -39,7 +39,7 @@
39
39
  "README.md"
40
40
  ],
41
41
  "peerDependencies": {
42
- "openclaw": ">=2026.7.1"
42
+ "openclaw": ">=2026.7.2-beta.1"
43
43
  },
44
44
  "peerDependenciesMeta": {
45
45
  "openclaw": {