@openclaw/voice-call 2026.7.2-beta.5 → 2026.7.33
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/README.md +3 -2
- package/dist/.setup/config-BBpso-fA.mjs +674 -0
- package/dist/.setup/config-compat-CYRE-SSo.mjs +156 -0
- package/dist/{guarded-json-api-Dxhe25Zi.js → .setup/guarded-json-api-BukKSVNW.mjs} +50 -24
- package/dist/{mock-YsvBTX-7.js → .setup/mock-DY4yTqR2.mjs} +1 -1
- package/dist/{plivo-B-KvPVji.js → .setup/plivo-DFHh72MH.mjs} +3 -2
- package/dist/{realtime-handler-hIVPEZxN.js → .setup/realtime-handler-DWLxvZuO.mjs} +197 -128
- package/dist/{response-generator-z6M9229t.js → .setup/response-generator-DoC6lfcm.mjs} +6 -21
- package/dist/{runtime-entry-CQtitvRd.js → .setup/runtime-entry-CH-CV0Sf.mjs} +384 -868
- package/dist/{store-path-nYL-yM0S.js → .setup/store-1UfyY3HS.mjs} +6 -13
- package/dist/{telnyx-BG56lL7z.js → .setup/telnyx-Bb8X-nin.mjs} +1 -1
- package/dist/{twilio-B3FQ_P9x.js → .setup/twilio-Bsbf3O9A.mjs} +11 -15
- package/dist/{webhook-replay-aaP79dI8.js → .setup/webhook-replay-g3cDA5wr.mjs} +1 -1
- package/dist/cli-metadata.js +1 -5
- package/dist/doctor-contract-api.js +14 -36
- package/dist/index.js +38 -28
- package/dist/runtime-entry.js +1 -1
- package/dist/setup-api.js +2 -86
- package/node_modules/commander/LICENSE +22 -0
- package/node_modules/commander/Readme.md +1172 -0
- package/node_modules/commander/index.js +21 -0
- package/node_modules/commander/lib/argument.js +147 -0
- package/node_modules/commander/lib/command.js +2790 -0
- package/node_modules/commander/lib/error.js +36 -0
- package/node_modules/commander/lib/help.js +731 -0
- package/node_modules/commander/lib/option.js +377 -0
- package/node_modules/commander/lib/suggestSimilar.js +99 -0
- package/node_modules/commander/package-support.json +19 -0
- package/node_modules/commander/package.json +64 -0
- package/node_modules/commander/typings/index.d.ts +1113 -0
- package/node_modules/typebox/build/compile/validator.d.mts +4 -1
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +2 -5
- package/node_modules/typebox/build/guard/string.mjs +4 -16
- package/node_modules/typebox/build/schema/engine/_functions.mjs +15 -34
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +0 -5
- package/node_modules/typebox/build/type/action/readonly_object.mjs +0 -8
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +32 -29
- package/node_modules/ws/lib/permessage-deflate.js +3 -1
- package/node_modules/ws/package.json +1 -1
- package/openclaw.plugin.json +15 -2
- package/package.json +8 -6
- package/dist/cli-output-mode.js +0 -27
- package/dist/twilio-region-4fkgz3UG.js +0 -25
- /package/dist/{realtime-transcription.runtime-CbJAs5t_.js → .setup/realtime-transcription.runtime-CbJAs5t_.mjs} +0 -0
- /package/dist/{realtime-voice.runtime-vtdCOWg-.js → .setup/realtime-voice.runtime-vtdCOWg-.mjs} +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { t as VoiceCallConfigSchema } from "./config-BBpso-fA.mjs";
|
|
2
|
+
import { asOptionalRecord, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
+
//#region extensions/voice-call/src/config-compat.ts
|
|
4
|
+
/** Version where legacy voice-call config shape support is removed. */
|
|
5
|
+
const VOICE_CALL_LEGACY_CONFIG_REMOVAL_VERSION = "2026.6.0";
|
|
6
|
+
const asObject = asOptionalRecord;
|
|
7
|
+
const getString = readStringField;
|
|
8
|
+
/** Read finite numeric config values. */
|
|
9
|
+
function getNumber(obj, key) {
|
|
10
|
+
const value = obj?.[key];
|
|
11
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
12
|
+
}
|
|
13
|
+
/** Merge legacy provider-specific values into the canonical providers map. */
|
|
14
|
+
function mergeProviderConfig(providersValue, providerId, compatValues) {
|
|
15
|
+
if (Object.keys(compatValues).length === 0) return asObject(providersValue);
|
|
16
|
+
const providers = asObject(providersValue) ?? {};
|
|
17
|
+
const existing = asObject(providers[providerId]) ?? {};
|
|
18
|
+
return {
|
|
19
|
+
...providers,
|
|
20
|
+
[providerId]: {
|
|
21
|
+
...existing,
|
|
22
|
+
...compatValues
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** Collect legacy voice-call config keys that should be migrated. */
|
|
27
|
+
function collectVoiceCallLegacyConfigIssues(value) {
|
|
28
|
+
const raw = asObject(value) ?? {};
|
|
29
|
+
const realtime = asObject(raw.realtime);
|
|
30
|
+
const realtimeAgentContext = asObject(realtime?.agentContext);
|
|
31
|
+
const twilio = asObject(raw.twilio);
|
|
32
|
+
const streaming = asObject(raw.streaming);
|
|
33
|
+
const issues = [];
|
|
34
|
+
if (raw.provider === "log") issues.push({
|
|
35
|
+
path: "provider",
|
|
36
|
+
replacement: "provider",
|
|
37
|
+
message: "Replace provider \"log\" with \"mock\"."
|
|
38
|
+
});
|
|
39
|
+
if (typeof twilio?.from === "string") issues.push({
|
|
40
|
+
path: "twilio.from",
|
|
41
|
+
replacement: "fromNumber",
|
|
42
|
+
message: "Move twilio.from to fromNumber."
|
|
43
|
+
});
|
|
44
|
+
if (typeof streaming?.sttProvider === "string") issues.push({
|
|
45
|
+
path: "streaming.sttProvider",
|
|
46
|
+
replacement: "streaming.provider",
|
|
47
|
+
message: "Move streaming.sttProvider to streaming.provider."
|
|
48
|
+
});
|
|
49
|
+
if (typeof streaming?.openaiApiKey === "string") issues.push({
|
|
50
|
+
path: "streaming.openaiApiKey",
|
|
51
|
+
replacement: "streaming.providers.openai.apiKey",
|
|
52
|
+
message: "Move streaming.openaiApiKey to streaming.providers.openai.apiKey."
|
|
53
|
+
});
|
|
54
|
+
if (typeof streaming?.sttModel === "string") issues.push({
|
|
55
|
+
path: "streaming.sttModel",
|
|
56
|
+
replacement: "streaming.providers.openai.model",
|
|
57
|
+
message: "Move streaming.sttModel to streaming.providers.openai.model."
|
|
58
|
+
});
|
|
59
|
+
if (typeof streaming?.silenceDurationMs === "number") issues.push({
|
|
60
|
+
path: "streaming.silenceDurationMs",
|
|
61
|
+
replacement: "streaming.providers.openai.silenceDurationMs",
|
|
62
|
+
message: "Move streaming.silenceDurationMs to streaming.providers.openai.silenceDurationMs."
|
|
63
|
+
});
|
|
64
|
+
if (typeof streaming?.vadThreshold === "number") issues.push({
|
|
65
|
+
path: "streaming.vadThreshold",
|
|
66
|
+
replacement: "streaming.providers.openai.vadThreshold",
|
|
67
|
+
message: "Move streaming.vadThreshold to streaming.providers.openai.vadThreshold."
|
|
68
|
+
});
|
|
69
|
+
if (realtimeAgentContext && Object.hasOwn(realtimeAgentContext, "includeSystemPrompt")) issues.push({
|
|
70
|
+
path: "realtime.agentContext.includeSystemPrompt",
|
|
71
|
+
replacement: "realtime.agentContext",
|
|
72
|
+
message: "Remove realtime.agentContext.includeSystemPrompt; realtime context now uses the generated agent prompt."
|
|
73
|
+
});
|
|
74
|
+
return issues;
|
|
75
|
+
}
|
|
76
|
+
/** Format runtime warnings for legacy voice-call config keys. */
|
|
77
|
+
function formatVoiceCallLegacyConfigWarnings(params) {
|
|
78
|
+
const issues = collectVoiceCallLegacyConfigIssues(params.value);
|
|
79
|
+
if (issues.length === 0) return [];
|
|
80
|
+
return [`[voice-call] legacy config keys detected under ${params.configPathPrefix}; runtime loading will not rewrite them, and support for the legacy shape will be removed in ${VOICE_CALL_LEGACY_CONFIG_REMOVAL_VERSION}. Run "${params.doctorFixCommand}".`, ...issues.map((issue) => `[voice-call] ${params.configPathPrefix}.${issue.path}: ${issue.message}`)];
|
|
81
|
+
}
|
|
82
|
+
/** Migrate legacy voice-call config input to the current canonical shape. */
|
|
83
|
+
function migrateVoiceCallLegacyConfigInput(params) {
|
|
84
|
+
const raw = asObject(params.value) ?? {};
|
|
85
|
+
const realtime = asObject(raw.realtime);
|
|
86
|
+
const realtimeAgentContext = asObject(realtime?.agentContext);
|
|
87
|
+
const twilio = asObject(raw.twilio);
|
|
88
|
+
const streaming = asObject(raw.streaming);
|
|
89
|
+
const configPathPrefix = params.configPathPrefix ?? "plugins.entries.voice-call.config";
|
|
90
|
+
const issues = collectVoiceCallLegacyConfigIssues(raw);
|
|
91
|
+
const legacyStreamingOpenAICompat = {};
|
|
92
|
+
const streamingOpenAIApiKey = getString(streaming, "openaiApiKey");
|
|
93
|
+
if (streamingOpenAIApiKey) legacyStreamingOpenAICompat.apiKey = streamingOpenAIApiKey;
|
|
94
|
+
const streamingSttModel = getString(streaming, "sttModel");
|
|
95
|
+
if (streamingSttModel) legacyStreamingOpenAICompat.model = streamingSttModel;
|
|
96
|
+
const streamingSilenceDurationMs = getNumber(streaming, "silenceDurationMs");
|
|
97
|
+
if (streamingSilenceDurationMs !== void 0) legacyStreamingOpenAICompat.silenceDurationMs = streamingSilenceDurationMs;
|
|
98
|
+
const streamingVadThreshold = getNumber(streaming, "vadThreshold");
|
|
99
|
+
if (streamingVadThreshold !== void 0) legacyStreamingOpenAICompat.vadThreshold = streamingVadThreshold;
|
|
100
|
+
const streamingProvider = getString(streaming, "provider");
|
|
101
|
+
const legacyStreamingProvider = getString(streaming, "sttProvider");
|
|
102
|
+
const normalizedStreaming = streaming ? {
|
|
103
|
+
...streaming,
|
|
104
|
+
provider: streamingProvider ?? legacyStreamingProvider,
|
|
105
|
+
providers: mergeProviderConfig(streaming.providers, "openai", legacyStreamingOpenAICompat)
|
|
106
|
+
} : void 0;
|
|
107
|
+
if (normalizedStreaming) {
|
|
108
|
+
delete normalizedStreaming.sttProvider;
|
|
109
|
+
delete normalizedStreaming.openaiApiKey;
|
|
110
|
+
delete normalizedStreaming.sttModel;
|
|
111
|
+
delete normalizedStreaming.silenceDurationMs;
|
|
112
|
+
delete normalizedStreaming.vadThreshold;
|
|
113
|
+
}
|
|
114
|
+
const normalizedTwilio = twilio ? { ...twilio } : void 0;
|
|
115
|
+
if (normalizedTwilio) delete normalizedTwilio.from;
|
|
116
|
+
const normalizedRealtimeAgentContext = realtimeAgentContext ? { ...realtimeAgentContext } : void 0;
|
|
117
|
+
if (normalizedRealtimeAgentContext) delete normalizedRealtimeAgentContext.includeSystemPrompt;
|
|
118
|
+
const normalizedRealtime = realtime ? {
|
|
119
|
+
...realtime,
|
|
120
|
+
agentContext: normalizedRealtimeAgentContext ?? realtime.agentContext
|
|
121
|
+
} : void 0;
|
|
122
|
+
const config = {
|
|
123
|
+
...raw,
|
|
124
|
+
provider: raw.provider === "log" ? "mock" : raw.provider,
|
|
125
|
+
fromNumber: raw.fromNumber ?? (typeof twilio?.from === "string" ? twilio.from : void 0),
|
|
126
|
+
twilio: normalizedTwilio,
|
|
127
|
+
streaming: normalizedStreaming,
|
|
128
|
+
realtime: normalizedRealtime
|
|
129
|
+
};
|
|
130
|
+
const changes = [];
|
|
131
|
+
if (raw.provider === "log") changes.push(`Moved ${configPathPrefix}.provider "log" → "mock".`);
|
|
132
|
+
if (typeof twilio?.from === "string" && typeof raw.fromNumber !== "string") changes.push(`Moved ${configPathPrefix}.twilio.from → ${configPathPrefix}.fromNumber.`);
|
|
133
|
+
if (typeof streaming?.sttProvider === "string") changes.push(`Moved ${configPathPrefix}.streaming.sttProvider → ${configPathPrefix}.streaming.provider.`);
|
|
134
|
+
if (typeof streaming?.openaiApiKey === "string") changes.push(`Moved ${configPathPrefix}.streaming.openaiApiKey → ${configPathPrefix}.streaming.providers.openai.apiKey.`);
|
|
135
|
+
if (typeof streaming?.sttModel === "string") changes.push(`Moved ${configPathPrefix}.streaming.sttModel → ${configPathPrefix}.streaming.providers.openai.model.`);
|
|
136
|
+
if (getNumber(streaming, "silenceDurationMs") !== void 0) changes.push(`Moved ${configPathPrefix}.streaming.silenceDurationMs → ${configPathPrefix}.streaming.providers.openai.silenceDurationMs.`);
|
|
137
|
+
else if (typeof streaming?.silenceDurationMs === "number") changes.push(`Removed invalid ${configPathPrefix}.streaming.silenceDurationMs.`);
|
|
138
|
+
if (getNumber(streaming, "vadThreshold") !== void 0) changes.push(`Moved ${configPathPrefix}.streaming.vadThreshold → ${configPathPrefix}.streaming.providers.openai.vadThreshold.`);
|
|
139
|
+
else if (typeof streaming?.vadThreshold === "number") changes.push(`Removed invalid ${configPathPrefix}.streaming.vadThreshold.`);
|
|
140
|
+
if (realtimeAgentContext && Object.hasOwn(realtimeAgentContext, "includeSystemPrompt")) changes.push(`Removed ${configPathPrefix}.realtime.agentContext.includeSystemPrompt.`);
|
|
141
|
+
return {
|
|
142
|
+
config,
|
|
143
|
+
changes,
|
|
144
|
+
issues
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** Normalize legacy voice-call config input without returning migration metadata. */
|
|
148
|
+
function normalizeVoiceCallLegacyConfigInput(value) {
|
|
149
|
+
return migrateVoiceCallLegacyConfigInput({ value }).config;
|
|
150
|
+
}
|
|
151
|
+
/** Parse voice-call plugin config after applying legacy normalization. */
|
|
152
|
+
function parseVoiceCallPluginConfig(value) {
|
|
153
|
+
return VoiceCallConfigSchema.parse(normalizeVoiceCallLegacyConfigInput(value));
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
export { parseVoiceCallPluginConfig as i, migrateVoiceCallLegacyConfigInput as n, normalizeVoiceCallLegacyConfigInput as r, formatVoiceCallLegacyConfigWarnings as t };
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { fetchWithSsrFGuard } from "
|
|
2
|
-
import "
|
|
3
|
-
import { n as normalizeProxyIp,
|
|
4
|
-
import { n as markWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-
|
|
1
|
+
import { fetchWithSsrFGuard } from "../runtime-api.js";
|
|
2
|
+
import "../api.js";
|
|
3
|
+
import { n as normalizeProxyIp, o as getHeader } from "./runtime-entry-CH-CV0Sf.mjs";
|
|
4
|
+
import { n as markWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-g3cDA5wr.mjs";
|
|
5
5
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
6
6
|
import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
|
|
7
7
|
import { normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
8
|
import crypto from "node:crypto";
|
|
9
9
|
import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
10
|
-
import { readResponseTextPrefix, readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
|
11
10
|
//#region extensions/voice-call/src/webhook-security.ts
|
|
12
11
|
const twilioReplayCache = createWebhookReplayCache();
|
|
13
12
|
const plivoReplayCache = createWebhookReplayCache();
|
|
@@ -29,7 +28,8 @@ function createSkippedVerificationReplayKey(provider, ctx) {
|
|
|
29
28
|
function validateTwilioSignature(authToken, signature, url, params) {
|
|
30
29
|
if (!signature) return false;
|
|
31
30
|
const dataToSign = buildTwilioDataToSign(url, params);
|
|
32
|
-
|
|
31
|
+
const expectedSignature = crypto.createHmac("sha1", authToken).update(dataToSign).digest("base64");
|
|
32
|
+
return safeEqualSecret(signature, expectedSignature);
|
|
33
33
|
}
|
|
34
34
|
function buildTwilioDataToSign(url, params) {
|
|
35
35
|
let dataToSign = url;
|
|
@@ -54,14 +54,16 @@ function isValidHostname(hostname) {
|
|
|
54
54
|
*/
|
|
55
55
|
function extractHostname(hostHeader) {
|
|
56
56
|
if (!hostHeader) return null;
|
|
57
|
+
let hostname;
|
|
57
58
|
if (hostHeader.startsWith("[")) {
|
|
58
59
|
const endBracket = hostHeader.indexOf("]");
|
|
59
60
|
if (endBracket === -1) return null;
|
|
60
|
-
|
|
61
|
+
hostname = hostHeader.slice(1, endBracket);
|
|
62
|
+
return normalizeLowercaseStringOrEmpty(hostname);
|
|
61
63
|
}
|
|
62
64
|
if (hostHeader.includes("@")) return null;
|
|
63
|
-
|
|
64
|
-
if (!
|
|
65
|
+
hostname = hostHeader.split(":")[0];
|
|
66
|
+
if (!isValidHostname(hostname)) return null;
|
|
65
67
|
return normalizeLowercaseStringOrEmpty(hostname);
|
|
66
68
|
}
|
|
67
69
|
function extractHostnameFromHeader(headerValue) {
|
|
@@ -272,7 +274,7 @@ function verifyTelnyxWebhook(ctx, publicKey, options) {
|
|
|
272
274
|
ok: false,
|
|
273
275
|
reason: "Invalid signature"
|
|
274
276
|
};
|
|
275
|
-
const maxSkewMs = options?.maxSkewMs ??
|
|
277
|
+
const maxSkewMs = options?.maxSkewMs ?? 3e5;
|
|
276
278
|
const eventTimeMs = eventTimeSec * 1e3;
|
|
277
279
|
if (Math.abs(Date.now() - eventTimeMs) > maxSkewMs) return {
|
|
278
280
|
ok: false,
|
|
@@ -381,7 +383,9 @@ function createPlivoV3ReplayKey(params) {
|
|
|
381
383
|
}
|
|
382
384
|
function validatePlivoV2Signature(params) {
|
|
383
385
|
const baseUrl = getBaseUrlNoQuery(params.url);
|
|
384
|
-
|
|
386
|
+
const expected = normalizeSignatureBase64(crypto.createHmac("sha256", params.authToken).update(baseUrl + params.nonce).digest("base64"));
|
|
387
|
+
const provided = normalizeSignatureBase64(params.signature);
|
|
388
|
+
return safeEqualSecret(expected, provided);
|
|
385
389
|
}
|
|
386
390
|
function toParamMapFromSearchParams(sp) {
|
|
387
391
|
const map = {};
|
|
@@ -393,18 +397,16 @@ function toParamMapFromSearchParams(sp) {
|
|
|
393
397
|
}
|
|
394
398
|
function sortedQueryString(params) {
|
|
395
399
|
const parts = [];
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
const values = [...entryValues].toSorted();
|
|
400
|
+
for (const key of Object.keys(params).toSorted()) {
|
|
401
|
+
const values = [...params[key]].toSorted();
|
|
399
402
|
for (const value of values) parts.push(`${key}=${value}`);
|
|
400
403
|
}
|
|
401
404
|
return parts.join("&");
|
|
402
405
|
}
|
|
403
406
|
function sortedParamsString(params) {
|
|
404
407
|
const parts = [];
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
const values = [...entryValues].toSorted();
|
|
408
|
+
for (const key of Object.keys(params).toSorted()) {
|
|
409
|
+
const values = [...params[key]].toSorted();
|
|
408
410
|
for (const value of values) parts.push(`${key}${value}`);
|
|
409
411
|
}
|
|
410
412
|
return parts.join("");
|
|
@@ -462,6 +464,7 @@ function verifyPlivoWebhook(ctx, authToken, options) {
|
|
|
462
464
|
if (options?.publicUrl) try {
|
|
463
465
|
const req = new URL(reconstructed);
|
|
464
466
|
const base = new URL(options.publicUrl);
|
|
467
|
+
base.pathname = req.pathname;
|
|
465
468
|
base.search = req.search;
|
|
466
469
|
verificationUrl = base.toString();
|
|
467
470
|
} catch {
|
|
@@ -534,8 +537,8 @@ function verifyPlivoWebhook(ctx, authToken, options) {
|
|
|
534
537
|
}
|
|
535
538
|
//#endregion
|
|
536
539
|
//#region extensions/voice-call/src/providers/shared/response-body.ts
|
|
537
|
-
const PROVIDER_JSON_RESPONSE_MAX_BYTES =
|
|
538
|
-
const PROVIDER_ERROR_RESPONSE_MAX_BYTES =
|
|
540
|
+
const PROVIDER_JSON_RESPONSE_MAX_BYTES = 1048576;
|
|
541
|
+
const PROVIDER_ERROR_RESPONSE_MAX_BYTES = 8192;
|
|
539
542
|
const TRUNCATED_SUFFIX = "... [truncated]";
|
|
540
543
|
async function cancelProviderResponseBody(response) {
|
|
541
544
|
await response.body?.cancel().catch(() => void 0);
|
|
@@ -544,12 +547,35 @@ function appendTruncatedSuffix(text) {
|
|
|
544
547
|
return `${text.trimEnd()}${TRUNCATED_SUFFIX}`;
|
|
545
548
|
}
|
|
546
549
|
async function readProviderResponseTextWithLimit(params) {
|
|
547
|
-
if (params.
|
|
548
|
-
|
|
549
|
-
|
|
550
|
+
if (!params.response.body) return "";
|
|
551
|
+
const reader = params.response.body.getReader();
|
|
552
|
+
const decoder = new TextDecoder();
|
|
553
|
+
let totalBytes = 0;
|
|
554
|
+
let text = "";
|
|
555
|
+
try {
|
|
556
|
+
while (true) {
|
|
557
|
+
const { done, value } = await reader.read();
|
|
558
|
+
if (done) return text + decoder.decode();
|
|
559
|
+
if (!value?.byteLength) continue;
|
|
560
|
+
const remainingBytes = params.maxBytes - totalBytes;
|
|
561
|
+
if (value.byteLength > remainingBytes) {
|
|
562
|
+
if (params.truncateOnLimit) {
|
|
563
|
+
const clipped = remainingBytes > 0 ? value.slice(0, remainingBytes) : void 0;
|
|
564
|
+
if (clipped) text += decoder.decode(clipped, { stream: true });
|
|
565
|
+
await reader.cancel().catch(() => void 0);
|
|
566
|
+
return appendTruncatedSuffix(text + decoder.decode());
|
|
567
|
+
}
|
|
568
|
+
await reader.cancel().catch(() => void 0);
|
|
569
|
+
throw new Error(`provider response body too large: ${totalBytes + value.byteLength} bytes (limit: ${params.maxBytes} bytes)`);
|
|
570
|
+
}
|
|
571
|
+
text += decoder.decode(value, { stream: true });
|
|
572
|
+
totalBytes += value.byteLength;
|
|
573
|
+
}
|
|
574
|
+
} finally {
|
|
575
|
+
try {
|
|
576
|
+
reader.releaseLock();
|
|
577
|
+
} catch {}
|
|
550
578
|
}
|
|
551
|
-
const body = await readResponseWithLimit(params.response, params.maxBytes, { onOverflow: ({ size, maxBytes }) => /* @__PURE__ */ new Error(`provider response body too large: ${size} bytes (limit: ${maxBytes} bytes)`) });
|
|
552
|
-
return new TextDecoder().decode(body);
|
|
553
579
|
}
|
|
554
580
|
async function readProviderJsonResponseText(response) {
|
|
555
581
|
return await readProviderResponseTextWithLimit({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as markWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-
|
|
1
|
+
import { n as markWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-g3cDA5wr.mjs";
|
|
2
2
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import crypto from "node:crypto";
|
|
4
4
|
//#region extensions/voice-call/src/providers/mock.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { g as escapeXml, o as getHeader } from "./runtime-entry-CH-CV0Sf.mjs";
|
|
2
|
+
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-BukKSVNW.mjs";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
5
|
//#region extensions/voice-call/src/providers/plivo.ts
|
|
@@ -371,6 +371,7 @@ var PlivoProvider = class PlivoProvider {
|
|
|
371
371
|
try {
|
|
372
372
|
if (this.options.publicUrl) {
|
|
373
373
|
const base = new URL(this.options.publicUrl);
|
|
374
|
+
base.pathname = new URL(ctx.url).pathname;
|
|
374
375
|
return `${base.origin}${base.pathname}`;
|
|
375
376
|
}
|
|
376
377
|
const u = new URL(reconstructWebhookUrl(ctx, {
|