@openclaw/voice-call 2026.5.14-beta.1 → 2026.5.16-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.
- package/dist/{guarded-json-api-D26auOvl.js → guarded-json-api-D_aM8XmA.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/{plivo-P0n73IxS.js → plivo--HUS8UBT.js} +2 -3
- package/dist/{response-generator-4wAlt0EM.js → response-generator-ZeNpwsyL.js} +1 -1
- package/dist/{runtime-entry-CmYLshgT.js → runtime-entry-ox4PGoxT.js} +103 -17
- package/dist/runtime-entry.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/{telnyx-3TbRULg_.js → telnyx-Df3IfYAS.js} +1 -1
- package/dist/{twilio-DjcNE_Rb.js → twilio-B3zpyWY5.js} +2 -4
- package/package.json +5 -5
- package/dist/call-status-CuIeqfac.js +0 -32
- package/dist/http-headers-B5L5gMpK.js +0 -10
- package/dist/response-model-CyF5K80p.js +0 -12
- package/dist/voice-mapping-DMm-YvxM.js +0 -37
- /package/dist/{config-compat-Monzho4R.js → config-compat-DJqJ8NzH.js} +0 -0
- /package/dist/{mock-0CEjFJi5.js → mock-BvTP8Rmx.js} +0 -0
- /package/dist/{realtime-handler-DQPIcvi-.js → realtime-handler-Cj_3954k.js} +0 -0
- /package/dist/{realtime-transcription.runtime-B2h70y2W.js → realtime-transcription.runtime-CuOCFrMc.js} +0 -0
- /package/dist/{realtime-voice.runtime-Bkh4nvLn.js → realtime-voice.runtime-BM0lAf0B.js} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fetchWithSsrFGuard } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
|
-
import {
|
|
3
|
+
import { a as getHeader } from "./runtime-entry-ox4PGoxT.js";
|
|
4
4
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
5
5
|
import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
|
|
6
6
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { definePluginEntry, sleep } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
3
|
import { i as resolveVoiceCallConfig, s as validateProviderConfig } from "./config-C8gX5Cik.js";
|
|
4
|
-
import {
|
|
5
|
-
import { i as parseVoiceCallPluginConfig, r as normalizeVoiceCallLegacyConfigInput, t as formatVoiceCallLegacyConfigWarnings } from "./config-compat-
|
|
4
|
+
import { c as getTailscaleSelfInfo, l as setupTailscaleExposureRoute, o as resolveWebhookExposureStatus, p as resolveUserPath, s as cleanupTailscaleExposureRoute, t as createVoiceCallRuntime } from "./runtime-entry-ox4PGoxT.js";
|
|
5
|
+
import { i as parseVoiceCallPluginConfig, r as normalizeVoiceCallLegacyConfigInput, t as formatVoiceCallLegacyConfigWarnings } from "./config-compat-DJqJ8NzH.js";
|
|
6
6
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
7
7
|
import { ErrorCodes, callGatewayFromCli, errorShape } from "openclaw/plugin-sdk/gateway-runtime";
|
|
8
8
|
import { normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
3
|
-
import { n as reconstructWebhookUrl, r as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-D26auOvl.js";
|
|
1
|
+
import { a as getHeader, m as escapeXml } from "./runtime-entry-ox4PGoxT.js";
|
|
2
|
+
import { n as reconstructWebhookUrl, r as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-D_aM8XmA.js";
|
|
4
3
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
4
|
import crypto from "node:crypto";
|
|
6
5
|
//#region extensions/voice-call/src/providers/plivo.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { o as resolveVoiceCallSessionKey } from "./config-C8gX5Cik.js";
|
|
2
|
-
import {
|
|
2
|
+
import { f as resolveVoiceResponseModel } from "./runtime-entry-ox4PGoxT.js";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
5
|
import { applyModelOverrideToSessionEntry } from "openclaw/plugin-sdk/model-session-runtime";
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { isBlockedHostnameOrIp, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
3
|
import { a as resolveVoiceCallEffectiveConfig, c as deepMergeDefined, i as resolveVoiceCallConfig, n as normalizeVoiceCallConfig, o as resolveVoiceCallSessionKey, r as resolveTwilioAuthToken, s as validateProviderConfig } from "./config-C8gX5Cik.js";
|
|
4
|
-
import { n as mapVoiceToPolly, t as escapeXml } from "./voice-mapping-DMm-YvxM.js";
|
|
5
|
-
import { t as resolveVoiceResponseModel } from "./response-model-CyF5K80p.js";
|
|
6
|
-
import { a as convertPcmToMulaw8k, t as isProviderStatusTerminal } from "./call-status-CuIeqfac.js";
|
|
7
|
-
import { t as getHeader } from "./http-headers-B5L5gMpK.js";
|
|
8
4
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
9
5
|
import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
|
|
10
|
-
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
|
-
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, buildRealtimeVoiceAgentConsultPolicyInstructions, consultRealtimeVoiceAgent, createTalkSessionController, recordTalkObservabilityEvent, resolveRealtimeVoiceAgentConsultTools, resolveRealtimeVoiceAgentConsultToolsAllow, resolveRealtimeVoiceFastContextConsult } from "openclaw/plugin-sdk/realtime-voice";
|
|
6
|
+
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
|
+
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, buildRealtimeVoiceAgentConsultPolicyInstructions, consultRealtimeVoiceAgent, convertPcmToMulaw8k, createTalkSessionController, recordTalkObservabilityEvent, resolveRealtimeVoiceAgentConsultTools, resolveRealtimeVoiceAgentConsultToolsAllow, resolveRealtimeVoiceFastContextConsult } from "openclaw/plugin-sdk/realtime-voice";
|
|
12
8
|
import { z } from "zod";
|
|
13
9
|
import fs from "node:fs";
|
|
14
10
|
import os from "node:os";
|
|
@@ -351,6 +347,41 @@ function resolvePreferredTtsVoice(config) {
|
|
|
351
347
|
return resolveProviderVoiceSetting(config.tts?.providers?.[providerId]);
|
|
352
348
|
}
|
|
353
349
|
//#endregion
|
|
350
|
+
//#region extensions/voice-call/src/voice-mapping.ts
|
|
351
|
+
/**
|
|
352
|
+
* Escape XML special characters for TwiML and other XML responses.
|
|
353
|
+
*/
|
|
354
|
+
function escapeXml(text) {
|
|
355
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Map of OpenAI voice names to similar Twilio Polly voices.
|
|
359
|
+
*/
|
|
360
|
+
const OPENAI_TO_POLLY_MAP = {
|
|
361
|
+
alloy: "Polly.Joanna",
|
|
362
|
+
echo: "Polly.Matthew",
|
|
363
|
+
fable: "Polly.Amy",
|
|
364
|
+
onyx: "Polly.Brian",
|
|
365
|
+
nova: "Polly.Salli",
|
|
366
|
+
shimmer: "Polly.Kimberly"
|
|
367
|
+
};
|
|
368
|
+
/**
|
|
369
|
+
* Default Polly voice when no mapping is found.
|
|
370
|
+
*/
|
|
371
|
+
const DEFAULT_POLLY_VOICE = "Polly.Joanna";
|
|
372
|
+
/**
|
|
373
|
+
* Map OpenAI voice names to Twilio Polly equivalents.
|
|
374
|
+
* Falls through if already a valid Polly/Google voice.
|
|
375
|
+
*
|
|
376
|
+
* @param voice - OpenAI voice name (alloy, echo, etc.) or Polly voice name
|
|
377
|
+
* @returns Polly voice name suitable for Twilio TwiML
|
|
378
|
+
*/
|
|
379
|
+
function mapVoiceToPolly(voice) {
|
|
380
|
+
if (!voice) return DEFAULT_POLLY_VOICE;
|
|
381
|
+
if (voice.startsWith("Polly.") || voice.startsWith("Google.")) return voice;
|
|
382
|
+
return OPENAI_TO_POLLY_MAP[normalizeLowercaseStringOrEmpty(voice)] || "Polly.Joanna";
|
|
383
|
+
}
|
|
384
|
+
//#endregion
|
|
354
385
|
//#region extensions/voice-call/src/manager/twiml.ts
|
|
355
386
|
function generateNotifyTwiml(message, voice) {
|
|
356
387
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -1274,6 +1305,27 @@ async function resolveRealtimeFastContextConsult(params) {
|
|
|
1274
1305
|
});
|
|
1275
1306
|
}
|
|
1276
1307
|
//#endregion
|
|
1308
|
+
//#region extensions/voice-call/src/response-model.ts
|
|
1309
|
+
function resolveVoiceResponseModel(params) {
|
|
1310
|
+
const modelRef = params.voiceConfig.responseModel ?? `${params.agentRuntime.defaults.provider}/${params.agentRuntime.defaults.model}`;
|
|
1311
|
+
const slashIndex = modelRef.indexOf("/");
|
|
1312
|
+
return {
|
|
1313
|
+
modelRef,
|
|
1314
|
+
provider: slashIndex === -1 ? params.agentRuntime.defaults.provider : modelRef.slice(0, slashIndex),
|
|
1315
|
+
model: slashIndex === -1 ? modelRef : modelRef.slice(slashIndex + 1)
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
//#endregion
|
|
1319
|
+
//#region extensions/voice-call/src/telephony-audio.ts
|
|
1320
|
+
/**
|
|
1321
|
+
* Chunk audio buffer into 20ms frames for streaming (8kHz mono mu-law).
|
|
1322
|
+
*/
|
|
1323
|
+
function chunkAudio(audio, chunkSize = 160) {
|
|
1324
|
+
return (function* () {
|
|
1325
|
+
for (let i = 0; i < audio.length; i += chunkSize) yield audio.subarray(i, Math.min(i + chunkSize, audio.length));
|
|
1326
|
+
})();
|
|
1327
|
+
}
|
|
1328
|
+
//#endregion
|
|
1277
1329
|
//#region extensions/voice-call/src/telephony-tts.ts
|
|
1278
1330
|
const TELEPHONY_DEFAULT_TTS_TIMEOUT_MS = 8e3;
|
|
1279
1331
|
function createTelephonyTtsProvider(params) {
|
|
@@ -1755,6 +1807,14 @@ function resolveWebhookExposureStatus(config) {
|
|
|
1755
1807
|
};
|
|
1756
1808
|
}
|
|
1757
1809
|
//#endregion
|
|
1810
|
+
//#region extensions/voice-call/src/http-headers.ts
|
|
1811
|
+
function getHeader(headers, name) {
|
|
1812
|
+
const target = normalizeLowercaseStringOrEmpty(name);
|
|
1813
|
+
const value = headers[target] ?? Object.entries(headers).find(([key]) => normalizeLowercaseStringOrEmpty(key) === target)?.[1];
|
|
1814
|
+
if (Array.isArray(value)) return value[0];
|
|
1815
|
+
return value;
|
|
1816
|
+
}
|
|
1817
|
+
//#endregion
|
|
1758
1818
|
//#region extensions/voice-call/src/media-stream.ts
|
|
1759
1819
|
const DEFAULT_PRE_START_TIMEOUT_MS = 5e3;
|
|
1760
1820
|
const DEFAULT_MAX_PENDING_CONNECTIONS = 32;
|
|
@@ -1773,6 +1833,14 @@ function normalizeWsMessageData(data) {
|
|
|
1773
1833
|
if (Array.isArray(data)) return Buffer.concat(data);
|
|
1774
1834
|
return Buffer.from(data);
|
|
1775
1835
|
}
|
|
1836
|
+
function parseTwilioMediaMessage(data) {
|
|
1837
|
+
const raw = normalizeWsMessageData(data);
|
|
1838
|
+
try {
|
|
1839
|
+
return JSON.parse(raw.toString("utf8"));
|
|
1840
|
+
} catch (cause) {
|
|
1841
|
+
throw new Error("Twilio media stream message was malformed JSON", { cause });
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1776
1844
|
/**
|
|
1777
1845
|
* Manages WebSocket connections for Twilio media streams.
|
|
1778
1846
|
*/
|
|
@@ -1848,8 +1916,7 @@ var MediaStreamHandler = class {
|
|
|
1848
1916
|
}
|
|
1849
1917
|
ws.on("message", async (data) => {
|
|
1850
1918
|
try {
|
|
1851
|
-
const
|
|
1852
|
-
const message = JSON.parse(raw.toString("utf8"));
|
|
1919
|
+
const message = parseTwilioMediaMessage(data);
|
|
1853
1920
|
switch (message.event) {
|
|
1854
1921
|
case "connected":
|
|
1855
1922
|
console.log("[MediaStream] Twilio connected");
|
|
@@ -2382,6 +2449,25 @@ Content-Length: ${Buffer.byteLength(body)}\r\n\r
|
|
|
2382
2449
|
}
|
|
2383
2450
|
};
|
|
2384
2451
|
//#endregion
|
|
2452
|
+
//#region extensions/voice-call/src/providers/shared/call-status.ts
|
|
2453
|
+
const TERMINAL_PROVIDER_STATUS_TO_END_REASON = {
|
|
2454
|
+
completed: "completed",
|
|
2455
|
+
failed: "failed",
|
|
2456
|
+
busy: "busy",
|
|
2457
|
+
"no-answer": "no-answer",
|
|
2458
|
+
canceled: "hangup-bot"
|
|
2459
|
+
};
|
|
2460
|
+
function normalizeProviderStatus(status) {
|
|
2461
|
+
const normalized = normalizeOptionalLowercaseString(status);
|
|
2462
|
+
return normalized && normalized.length > 0 ? normalized : "unknown";
|
|
2463
|
+
}
|
|
2464
|
+
function mapProviderStatusToEndReason(status) {
|
|
2465
|
+
return TERMINAL_PROVIDER_STATUS_TO_END_REASON[normalizeProviderStatus(status)] ?? null;
|
|
2466
|
+
}
|
|
2467
|
+
function isProviderStatusTerminal(status) {
|
|
2468
|
+
return mapProviderStatusToEndReason(status) !== null;
|
|
2469
|
+
}
|
|
2470
|
+
//#endregion
|
|
2385
2471
|
//#region extensions/voice-call/src/webhook/stale-call-reaper.ts
|
|
2386
2472
|
const CHECK_INTERVAL_MS = 3e4;
|
|
2387
2473
|
function startStaleCallReaper(params) {
|
|
@@ -2415,11 +2501,11 @@ const TRANSCRIPT_LOG_MAX_CHARS = 200;
|
|
|
2415
2501
|
let realtimeTranscriptionRuntimePromise;
|
|
2416
2502
|
let responseGeneratorModulePromise;
|
|
2417
2503
|
function loadRealtimeTranscriptionRuntime() {
|
|
2418
|
-
realtimeTranscriptionRuntimePromise ??= import("./realtime-transcription.runtime-
|
|
2504
|
+
realtimeTranscriptionRuntimePromise ??= import("./realtime-transcription.runtime-CuOCFrMc.js");
|
|
2419
2505
|
return realtimeTranscriptionRuntimePromise;
|
|
2420
2506
|
}
|
|
2421
2507
|
function loadResponseGeneratorModule() {
|
|
2422
|
-
responseGeneratorModulePromise ??= import("./response-generator-
|
|
2508
|
+
responseGeneratorModulePromise ??= import("./response-generator-ZeNpwsyL.js");
|
|
2423
2509
|
return responseGeneratorModulePromise;
|
|
2424
2510
|
}
|
|
2425
2511
|
function sanitizeTranscriptForLog(value) {
|
|
@@ -3036,27 +3122,27 @@ let mockProviderPromise;
|
|
|
3036
3122
|
let realtimeVoiceRuntimePromise;
|
|
3037
3123
|
let realtimeHandlerPromise;
|
|
3038
3124
|
function loadTelnyxProvider() {
|
|
3039
|
-
telnyxProviderPromise ??= import("./telnyx-
|
|
3125
|
+
telnyxProviderPromise ??= import("./telnyx-Df3IfYAS.js");
|
|
3040
3126
|
return telnyxProviderPromise;
|
|
3041
3127
|
}
|
|
3042
3128
|
function loadTwilioProvider() {
|
|
3043
|
-
twilioProviderPromise ??= import("./twilio-
|
|
3129
|
+
twilioProviderPromise ??= import("./twilio-B3zpyWY5.js");
|
|
3044
3130
|
return twilioProviderPromise;
|
|
3045
3131
|
}
|
|
3046
3132
|
function loadPlivoProvider() {
|
|
3047
|
-
plivoProviderPromise ??= import("./plivo
|
|
3133
|
+
plivoProviderPromise ??= import("./plivo--HUS8UBT.js");
|
|
3048
3134
|
return plivoProviderPromise;
|
|
3049
3135
|
}
|
|
3050
3136
|
function loadMockProvider() {
|
|
3051
|
-
mockProviderPromise ??= import("./mock-
|
|
3137
|
+
mockProviderPromise ??= import("./mock-BvTP8Rmx.js");
|
|
3052
3138
|
return mockProviderPromise;
|
|
3053
3139
|
}
|
|
3054
3140
|
function loadRealtimeVoiceRuntime() {
|
|
3055
|
-
realtimeVoiceRuntimePromise ??= import("./realtime-voice.runtime-
|
|
3141
|
+
realtimeVoiceRuntimePromise ??= import("./realtime-voice.runtime-BM0lAf0B.js");
|
|
3056
3142
|
return realtimeVoiceRuntimePromise;
|
|
3057
3143
|
}
|
|
3058
3144
|
function loadRealtimeHandler() {
|
|
3059
|
-
realtimeHandlerPromise ??= import("./realtime-handler-
|
|
3145
|
+
realtimeHandlerPromise ??= import("./realtime-handler-Cj_3954k.js");
|
|
3060
3146
|
return realtimeHandlerPromise;
|
|
3061
3147
|
}
|
|
3062
3148
|
function resolveVoiceCallConsultSessionKey(call) {
|
|
@@ -3320,4 +3406,4 @@ async function createVoiceCallRuntime(params) {
|
|
|
3320
3406
|
}
|
|
3321
3407
|
}
|
|
3322
3408
|
//#endregion
|
|
3323
|
-
export {
|
|
3409
|
+
export { getHeader as a, getTailscaleSelfInfo as c, chunkAudio as d, resolveVoiceResponseModel as f, mapVoiceToPolly as h, normalizeProviderStatus as i, setupTailscaleExposureRoute as l, escapeXml as m, isProviderStatusTerminal as n, resolveWebhookExposureStatus as o, resolveUserPath as p, mapProviderStatusToEndReason as r, cleanupTailscaleExposureRoute as s, createVoiceCallRuntime as t, TELEPHONY_DEFAULT_TTS_TIMEOUT_MS as u };
|
package/dist/runtime-entry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createVoiceCallRuntime } from "./runtime-entry-
|
|
1
|
+
import { t as createVoiceCallRuntime } from "./runtime-entry-ox4PGoxT.js";
|
|
2
2
|
export { createVoiceCallRuntime };
|
package/dist/setup-api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as migrateVoiceCallLegacyConfigInput } from "./config-compat-
|
|
1
|
+
import { n as migrateVoiceCallLegacyConfigInput } from "./config-compat-DJqJ8NzH.js";
|
|
2
2
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
4
4
|
//#region extensions/voice-call/setup-api.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { i as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-D_aM8XmA.js";
|
|
2
2
|
import crypto from "node:crypto";
|
|
3
3
|
//#region extensions/voice-call/src/providers/telnyx.ts
|
|
4
4
|
function normalizeTelnyxDirection(direction) {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { fetchWithSsrFGuard } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { t as getHeader } from "./http-headers-B5L5gMpK.js";
|
|
6
|
-
import { a as verifyTwilioWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-D26auOvl.js";
|
|
3
|
+
import { a as getHeader, d as chunkAudio, h as mapVoiceToPolly, i as normalizeProviderStatus, m as escapeXml, n as isProviderStatusTerminal, r as mapProviderStatusToEndReason } from "./runtime-entry-ox4PGoxT.js";
|
|
4
|
+
import { a as verifyTwilioWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-D_aM8XmA.js";
|
|
7
5
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
6
|
import crypto from "node:crypto";
|
|
9
7
|
import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/voice-call",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.16-beta.1",
|
|
4
4
|
"description": "OpenClaw voice-call plugin",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"commander": "14.0.3",
|
|
12
12
|
"typebox": "1.1.38",
|
|
13
|
-
"ws": "8.20.
|
|
13
|
+
"ws": "8.20.1",
|
|
14
14
|
"zod": "4.4.3"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"openclaw": "workspace:*"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
|
-
"openclaw": ">=2026.5.
|
|
21
|
+
"openclaw": ">=2026.5.16-beta.1"
|
|
22
22
|
},
|
|
23
23
|
"peerDependenciesMeta": {
|
|
24
24
|
"openclaw": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"minHostVersion": ">=2026.4.10"
|
|
36
36
|
},
|
|
37
37
|
"compat": {
|
|
38
|
-
"pluginApi": ">=2026.5.
|
|
38
|
+
"pluginApi": ">=2026.5.16-beta.1"
|
|
39
39
|
},
|
|
40
40
|
"build": {
|
|
41
|
-
"openclawVersion": "2026.5.
|
|
41
|
+
"openclawVersion": "2026.5.16-beta.1"
|
|
42
42
|
},
|
|
43
43
|
"release": {
|
|
44
44
|
"publishToClawHub": true,
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
-
import { convertPcmToMulaw8k } from "openclaw/plugin-sdk/realtime-voice";
|
|
3
|
-
//#region extensions/voice-call/src/telephony-audio.ts
|
|
4
|
-
/**
|
|
5
|
-
* Chunk audio buffer into 20ms frames for streaming (8kHz mono mu-law).
|
|
6
|
-
*/
|
|
7
|
-
function chunkAudio(audio, chunkSize = 160) {
|
|
8
|
-
return (function* () {
|
|
9
|
-
for (let i = 0; i < audio.length; i += chunkSize) yield audio.subarray(i, Math.min(i + chunkSize, audio.length));
|
|
10
|
-
})();
|
|
11
|
-
}
|
|
12
|
-
//#endregion
|
|
13
|
-
//#region extensions/voice-call/src/providers/shared/call-status.ts
|
|
14
|
-
const TERMINAL_PROVIDER_STATUS_TO_END_REASON = {
|
|
15
|
-
completed: "completed",
|
|
16
|
-
failed: "failed",
|
|
17
|
-
busy: "busy",
|
|
18
|
-
"no-answer": "no-answer",
|
|
19
|
-
canceled: "hangup-bot"
|
|
20
|
-
};
|
|
21
|
-
function normalizeProviderStatus(status) {
|
|
22
|
-
const normalized = normalizeOptionalLowercaseString(status);
|
|
23
|
-
return normalized && normalized.length > 0 ? normalized : "unknown";
|
|
24
|
-
}
|
|
25
|
-
function mapProviderStatusToEndReason(status) {
|
|
26
|
-
return TERMINAL_PROVIDER_STATUS_TO_END_REASON[normalizeProviderStatus(status)] ?? null;
|
|
27
|
-
}
|
|
28
|
-
function isProviderStatusTerminal(status) {
|
|
29
|
-
return mapProviderStatusToEndReason(status) !== null;
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { convertPcmToMulaw8k as a, chunkAudio as i, mapProviderStatusToEndReason as n, normalizeProviderStatus as r, isProviderStatusTerminal as t };
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
-
//#region extensions/voice-call/src/http-headers.ts
|
|
3
|
-
function getHeader(headers, name) {
|
|
4
|
-
const target = normalizeLowercaseStringOrEmpty(name);
|
|
5
|
-
const value = headers[target] ?? Object.entries(headers).find(([key]) => normalizeLowercaseStringOrEmpty(key) === target)?.[1];
|
|
6
|
-
if (Array.isArray(value)) return value[0];
|
|
7
|
-
return value;
|
|
8
|
-
}
|
|
9
|
-
//#endregion
|
|
10
|
-
export { getHeader as t };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
//#region extensions/voice-call/src/response-model.ts
|
|
2
|
-
function resolveVoiceResponseModel(params) {
|
|
3
|
-
const modelRef = params.voiceConfig.responseModel ?? `${params.agentRuntime.defaults.provider}/${params.agentRuntime.defaults.model}`;
|
|
4
|
-
const slashIndex = modelRef.indexOf("/");
|
|
5
|
-
return {
|
|
6
|
-
modelRef,
|
|
7
|
-
provider: slashIndex === -1 ? params.agentRuntime.defaults.provider : modelRef.slice(0, slashIndex),
|
|
8
|
-
model: slashIndex === -1 ? modelRef : modelRef.slice(slashIndex + 1)
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
|
-
export { resolveVoiceResponseModel as t };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
-
//#region extensions/voice-call/src/voice-mapping.ts
|
|
3
|
-
/**
|
|
4
|
-
* Escape XML special characters for TwiML and other XML responses.
|
|
5
|
-
*/
|
|
6
|
-
function escapeXml(text) {
|
|
7
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Map of OpenAI voice names to similar Twilio Polly voices.
|
|
11
|
-
*/
|
|
12
|
-
const OPENAI_TO_POLLY_MAP = {
|
|
13
|
-
alloy: "Polly.Joanna",
|
|
14
|
-
echo: "Polly.Matthew",
|
|
15
|
-
fable: "Polly.Amy",
|
|
16
|
-
onyx: "Polly.Brian",
|
|
17
|
-
nova: "Polly.Salli",
|
|
18
|
-
shimmer: "Polly.Kimberly"
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Default Polly voice when no mapping is found.
|
|
22
|
-
*/
|
|
23
|
-
const DEFAULT_POLLY_VOICE = "Polly.Joanna";
|
|
24
|
-
/**
|
|
25
|
-
* Map OpenAI voice names to Twilio Polly equivalents.
|
|
26
|
-
* Falls through if already a valid Polly/Google voice.
|
|
27
|
-
*
|
|
28
|
-
* @param voice - OpenAI voice name (alloy, echo, etc.) or Polly voice name
|
|
29
|
-
* @returns Polly voice name suitable for Twilio TwiML
|
|
30
|
-
*/
|
|
31
|
-
function mapVoiceToPolly(voice) {
|
|
32
|
-
if (!voice) return DEFAULT_POLLY_VOICE;
|
|
33
|
-
if (voice.startsWith("Polly.") || voice.startsWith("Google.")) return voice;
|
|
34
|
-
return OPENAI_TO_POLLY_MAP[normalizeLowercaseStringOrEmpty(voice)] || "Polly.Joanna";
|
|
35
|
-
}
|
|
36
|
-
//#endregion
|
|
37
|
-
export { mapVoiceToPolly as n, escapeXml as t };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|