@openclaw/voice-call 2026.9.2 → 2026.9.3
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/{cli-D3DeAqfd.js → cli-D7qQRwUE.js} +2 -2
- package/dist/doctor-contract-api.js +2 -1
- package/dist/{guarded-json-api-BhLtja0F.js → guarded-json-api-Z9SuGiD_.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/{plivo-qIMf0pd2.js → plivo-qSdVTUcE.js} +2 -2
- package/dist/{realtime-handler-CHCnMJfl.js → realtime-handler-BSW48gqM.js} +21 -14
- package/dist/{response-generator-BK43h7yV.js → response-generator-IX26g0hi.js} +1 -1
- package/dist/{runtime-entry-DNmi-vZR.js → runtime-entry-B8SNb2qD.js} +12 -8
- package/dist/runtime-entry.js +1 -1
- package/dist/{store-path-C_z9zKnA.js → store-path-M0GXxUfv.js} +16 -80
- package/dist/{telnyx-DCbnTTjn.js → telnyx-B8shXuBM.js} +1 -1
- package/dist/{twilio-BwJFcA2z.js → twilio-DhsTO8-E.js} +2 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { sleep } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
3
|
import { l as resolveVoiceCallStreamExposurePaths, u as validateProviderConfig } from "./config-DQwvsxeV.js";
|
|
4
|
-
import {
|
|
5
|
-
import { b as setVoiceCallStateRuntime, d as loadActiveCallsFromStore, l as findCallInStore, o as MAX_CALL_RECORD_EVENTS, t as resolveDefaultVoiceCallStoreDir, u as getCallHistoryFromStore } from "./store-path-
|
|
4
|
+
import { d as cleanupTailscaleExposureRoute, f as getTailscaleSelfInfo, p as setupTailscaleExposureRoutes, u as resolveWebhookExposureStatus, v as resolveVoiceCallAgentId, y as resolveUserPath } from "./runtime-entry-B8SNb2qD.js";
|
|
5
|
+
import { b as setVoiceCallStateRuntime, d as loadActiveCallsFromStore, l as findCallInStore, o as MAX_CALL_RECORD_EVENTS, t as resolveDefaultVoiceCallStoreDir, u as getCallHistoryFromStore } from "./store-path-M0GXxUfv.js";
|
|
6
6
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
7
7
|
import { callGatewayFromCli, isGatewayClientRequestError, isGatewayTransportError, redactSensitiveUrlLikeString } from "openclaw/plugin-sdk/gateway-runtime";
|
|
8
8
|
import { isRecord, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as CALL_RECORD_EVENT_META_MAX_ENTRIES, c as buildVoiceCallLegacyJsonlEventKey, f as parseVoiceCallRecordLine, h as resolveVoiceCallLegacyCallLogPath, i as CALL_RECORD_EVENT_CHUNKS_NAMESPACE, m as prepareVoiceCallRecordForStorage, n as CALL_RECORD_CHUNK_MAX_ENTRIES, o as MAX_CALL_RECORD_EVENTS, r as CALL_RECORD_EVENTS_NAMESPACE, s as RAW_CALL_RECORD_CHUNK_BYTES, t as resolveDefaultVoiceCallStoreDir } from "./store-path-
|
|
1
|
+
import { a as CALL_RECORD_EVENT_META_MAX_ENTRIES, c as buildVoiceCallLegacyJsonlEventKey, f as parseVoiceCallRecordLine, h as resolveVoiceCallLegacyCallLogPath, i as CALL_RECORD_EVENT_CHUNKS_NAMESPACE, m as prepareVoiceCallRecordForStorage, n as CALL_RECORD_CHUNK_MAX_ENTRIES, o as MAX_CALL_RECORD_EVENTS, r as CALL_RECORD_EVENTS_NAMESPACE, s as RAW_CALL_RECORD_CHUNK_BYTES, t as resolveDefaultVoiceCallStoreDir } from "./store-path-M0GXxUfv.js";
|
|
2
2
|
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
3
3
|
import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import path from "node:path";
|
|
@@ -68,6 +68,7 @@ function describeVoiceCallSchemaMigration(migration) {
|
|
|
68
68
|
case "state-consolidation-v13": return "cron jobs and subagent runs -> canonical JSON storage";
|
|
69
69
|
case "creator-namespace-v14": return "cron creators -> explicit principal namespaces";
|
|
70
70
|
case "conversation-binding-targets-v15": return "conversation bindings -> exact target keys without agent/session projections";
|
|
71
|
+
case "skill-workshop-directory-ownership-v16": return "Skill Workshop proposals -> per-agent Workshop directory ownership";
|
|
71
72
|
case "worker-placement-execution-mode-v8": return "cloud worker placements -> execution-mode claims";
|
|
72
73
|
case "operator-approvals-system-agent": return "operator approvals -> OpenClaw system changes";
|
|
73
74
|
case "session-watch-cursor-provenance-v4": return "session watch cursors -> provenance column";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fetchWithSsrFGuard } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
|
-
import {
|
|
3
|
+
import { l as getHeader, n as normalizeProxyIp } from "./runtime-entry-B8SNb2qD.js";
|
|
4
4
|
import { n as reserveWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-CCQSoBNF.js";
|
|
5
5
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
6
6
|
import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { definePluginEntry } from "./runtime-api.js";
|
|
|
2
2
|
import "./api.js";
|
|
3
3
|
import { VOICE_CALL_CLI_DESCRIPTOR } from "./cli-output-mode.js";
|
|
4
4
|
import { i as resolveVoiceCallConfig, t as VoiceCallConfigSchema, u as validateProviderConfig } from "./config-DQwvsxeV.js";
|
|
5
|
-
import { t as createVoiceCallRuntime } from "./runtime-entry-
|
|
5
|
+
import { t as createVoiceCallRuntime } from "./runtime-entry-B8SNb2qD.js";
|
|
6
6
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
7
7
|
import { ErrorCodes, errorShape } from "openclaw/plugin-sdk/gateway-runtime";
|
|
8
8
|
import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
|
|
@@ -514,7 +514,7 @@ var voice_call_default = definePluginEntry({
|
|
|
514
514
|
}
|
|
515
515
|
}));
|
|
516
516
|
api.registerCli(async ({ program }) => {
|
|
517
|
-
const { registerVoiceCallCli } = await import("./cli-
|
|
517
|
+
const { registerVoiceCallCli } = await import("./cli-D7qQRwUE.js");
|
|
518
518
|
registerVoiceCallCli({
|
|
519
519
|
program,
|
|
520
520
|
config,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { b as escapeXml, l as getHeader } from "./runtime-entry-B8SNb2qD.js";
|
|
2
|
+
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Z9SuGiD_.js";
|
|
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
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { d as REALTIME_VOICE_END_CALL_TOOL_NAME, s as resolveVoiceCallPublicPathPrefix } from "./config-DQwvsxeV.js";
|
|
2
|
-
import {
|
|
2
|
+
import { c as canonicalizeVoiceCallMediaBase64, o as WebSocket, s as WebSocketServer } from "./runtime-entry-B8SNb2qD.js";
|
|
3
3
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
4
4
|
import { asNullableRecord, asOptionalObjectRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
5
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
@@ -9,7 +9,6 @@ import { isFutureDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openc
|
|
|
9
9
|
import { randomUUID } from "node:crypto";
|
|
10
10
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
11
11
|
import "node:http";
|
|
12
|
-
import WebSocket$1, { WebSocketServer } from "ws";
|
|
13
12
|
//#region extensions/voice-call/src/webhook/realtime-audio-pacer.ts
|
|
14
13
|
const TELEPHONY_SAMPLE_RATE = 8e3;
|
|
15
14
|
const TELEPHONY_CHUNK_BYTES = 160;
|
|
@@ -443,6 +442,15 @@ function appendRecentTalkEventMetadata(call, event) {
|
|
|
443
442
|
}].slice(-12);
|
|
444
443
|
call.metadata = metadata;
|
|
445
444
|
}
|
|
445
|
+
function rejectRealtimeUpgrade(socket, status) {
|
|
446
|
+
const reason = status === 401 ? "Unauthorized" : "Service Unavailable";
|
|
447
|
+
try {
|
|
448
|
+
socket.end(`HTTP/1.1 ${status} ${reason}\r\nConnection: close\r\n\r\n`, () => socket.destroy());
|
|
449
|
+
} catch (error) {
|
|
450
|
+
socket.destroy();
|
|
451
|
+
throw error;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
446
454
|
var RealtimeCallHandler = class {
|
|
447
455
|
constructor(config, manager, resolveCallRegistration, servePath, streamDisconnectLifecycle, coreConfig) {
|
|
448
456
|
this.config = config;
|
|
@@ -506,16 +514,15 @@ var RealtimeCallHandler = class {
|
|
|
506
514
|
}
|
|
507
515
|
}
|
|
508
516
|
handleWebSocketUpgrade(request, socket, head) {
|
|
517
|
+
socket.once("error", () => socket.destroy());
|
|
509
518
|
if (this.closing) {
|
|
510
|
-
socket
|
|
511
|
-
socket.destroy();
|
|
519
|
+
rejectRealtimeUpgrade(socket, 503);
|
|
512
520
|
return;
|
|
513
521
|
}
|
|
514
522
|
const token = new URL(request.url ?? "/", "wss://localhost").pathname.split("/").pop() ?? null;
|
|
515
523
|
const callerMeta = token ? this.consumeStreamToken(token) : null;
|
|
516
524
|
if (!callerMeta) {
|
|
517
|
-
socket
|
|
518
|
-
socket.destroy();
|
|
525
|
+
rejectRealtimeUpgrade(socket, 401);
|
|
519
526
|
return;
|
|
520
527
|
}
|
|
521
528
|
const adapter = (callerMeta.providerName ?? "twilio") === "telnyx" ? new TelnyxStreamFrameAdapter() : new TwilioStreamFrameAdapter();
|
|
@@ -598,7 +605,7 @@ var RealtimeCallHandler = class {
|
|
|
598
605
|
this.pendingStreamTokens.clear();
|
|
599
606
|
const sockets = [...this.activeSockets];
|
|
600
607
|
this.closePromise = Promise.all([shutdownBarrier, ...sockets.map((ws) => new Promise((resolve) => {
|
|
601
|
-
if (ws.readyState === WebSocket
|
|
608
|
+
if (ws.readyState === WebSocket.CLOSED) {
|
|
602
609
|
resolve();
|
|
603
610
|
return;
|
|
604
611
|
}
|
|
@@ -790,7 +797,7 @@ var RealtimeCallHandler = class {
|
|
|
790
797
|
});
|
|
791
798
|
console.log(`[voice-call] Realtime bridge starting for call ${callId} (providerCallId=${callSid}, initialGreeting=${initialGreetingInstructions ? "queued" : "absent"})`);
|
|
792
799
|
const sendString = (message) => {
|
|
793
|
-
if (ws.readyState !== WebSocket
|
|
800
|
+
if (ws.readyState !== WebSocket.OPEN) return false;
|
|
794
801
|
if (ws.bufferedAmount > MAX_REALTIME_WS_BUFFERED_BYTES) {
|
|
795
802
|
console.warn(`[voice-call] realtime outbound websocket backpressure before send callId=${callId} providerCallId=${callSid} bufferedBytes=${ws.bufferedAmount}`);
|
|
796
803
|
ws.close(1013, "Backpressure: send buffer exceeded");
|
|
@@ -813,7 +820,7 @@ var RealtimeCallHandler = class {
|
|
|
813
820
|
},
|
|
814
821
|
onBackpressure: () => {
|
|
815
822
|
console.warn(`[voice-call] realtime paced audio backpressure callId=${callId} providerCallId=${callSid}`);
|
|
816
|
-
if (ws.readyState === WebSocket
|
|
823
|
+
if (ws.readyState === WebSocket.OPEN) ws.close(1013, "Backpressure: paced audio queue exceeded");
|
|
817
824
|
}
|
|
818
825
|
});
|
|
819
826
|
const speechDetector = createSpeechThresholdGate({
|
|
@@ -839,7 +846,7 @@ var RealtimeCallHandler = class {
|
|
|
839
846
|
initialGreetingInstructions,
|
|
840
847
|
triggerGreetingOnReady: Boolean(initialGreetingInstructions),
|
|
841
848
|
audioSink: {
|
|
842
|
-
isOpen: () => ws.readyState === WebSocket
|
|
849
|
+
isOpen: () => ws.readyState === WebSocket.OPEN,
|
|
843
850
|
sendAudio: (muLaw) => {
|
|
844
851
|
harness.recordOutputAudio(muLaw);
|
|
845
852
|
audioPacer.sendAudio(muLaw);
|
|
@@ -1035,7 +1042,7 @@ var RealtimeCallHandler = class {
|
|
|
1035
1042
|
if (ownsCallState) this.clearUserTranscriptState(callId, userTranscriptOwner);
|
|
1036
1043
|
if (reason === "completed" && (!ownsCallState || sessionClosed)) return;
|
|
1037
1044
|
this.streamDisconnectLifecycle.retire(callSid, streamSid);
|
|
1038
|
-
if (ws.readyState === WebSocket
|
|
1045
|
+
if (ws.readyState === WebSocket.OPEN) ws.close(reason === "error" ? 1011 : 1e3, "Bridge disconnected");
|
|
1039
1046
|
if (ownsCallState) emitCallEnd(reason);
|
|
1040
1047
|
}
|
|
1041
1048
|
};
|
|
@@ -1056,7 +1063,7 @@ var RealtimeCallHandler = class {
|
|
|
1056
1063
|
audioPacer.close();
|
|
1057
1064
|
const reason = provisionalCloseReason ?? "error";
|
|
1058
1065
|
if (!hadPredecessorOnAdmission || !this.activeBridgesByCallId.has(callId)) emitCallEnd(reason);
|
|
1059
|
-
if (ws.readyState === WebSocket
|
|
1066
|
+
if (ws.readyState === WebSocket.OPEN) ws.close(reason === "error" ? 1011 : 1e3, "Failed to create realtime bridge");
|
|
1060
1067
|
return null;
|
|
1061
1068
|
}
|
|
1062
1069
|
const session = candidate;
|
|
@@ -1128,7 +1135,7 @@ var RealtimeCallHandler = class {
|
|
|
1128
1135
|
close: (cause) => closeBinding(telephonyBinding, cause),
|
|
1129
1136
|
endCall: () => {
|
|
1130
1137
|
closeBinding(telephonyBinding);
|
|
1131
|
-
if (ws.readyState === WebSocket
|
|
1138
|
+
if (ws.readyState === WebSocket.OPEN) ws.close(1e3, "Call ended");
|
|
1132
1139
|
},
|
|
1133
1140
|
noteMediaActivity: () => {
|
|
1134
1141
|
if (bindingClosed || this.activeTelephonyBindingsByCallId.get(callId) !== telephonyBinding) return;
|
|
@@ -1137,7 +1144,7 @@ var RealtimeCallHandler = class {
|
|
|
1137
1144
|
console.warn(`[voice-call] Realtime media inactive callId=${callId} providerCallId=${callSid} timeoutMs=${REALTIME_MEDIA_INACTIVITY_TIMEOUT_MS} graceMs=${REALTIME_DISCONNECT_HANGUP_GRACE_MS}`);
|
|
1138
1145
|
livenessTimer = setTimeout(() => {
|
|
1139
1146
|
telephonyBinding.close("inactivity");
|
|
1140
|
-
if (ws.readyState === WebSocket
|
|
1147
|
+
if (ws.readyState === WebSocket.OPEN) ws.close(1e3, "Media inactivity");
|
|
1141
1148
|
}, REALTIME_DISCONNECT_HANGUP_GRACE_MS);
|
|
1142
1149
|
livenessTimer.unref?.();
|
|
1143
1150
|
}, REALTIME_MEDIA_INACTIVITY_TIMEOUT_MS);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as resolveVoiceCallSessionKey } from "./config-DQwvsxeV.js";
|
|
2
|
-
import {
|
|
2
|
+
import { _ as resolveCallAgentId, g as resolveVoiceResponseModel } from "./runtime-entry-B8SNb2qD.js";
|
|
3
3
|
import { filterStringEntries, isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import { resolveAgentConfig } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
5
5
|
import { isValidAgentHarnessSessionStoreEntry } from "openclaw/plugin-sdk/session-store-runtime";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { isBlockedHostnameOrIp, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText, sendHttpRequestRejection } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
3
|
import { a as resolveVoiceCallEffectiveConfig, c as resolveVoiceCallSessionKey, f as resolveVoiceCallRealtimeTools, i as resolveVoiceCallConfig, l as resolveVoiceCallStreamExposurePaths, n as normalizeVoiceCallConfig, o as resolveVoiceCallNumberRouteKeyForCall, r as resolveTwilioAuthToken, u as validateProviderConfig } from "./config-DQwvsxeV.js";
|
|
4
|
-
import { _ as releaseRejectedProviderCall, b as setVoiceCallStateRuntime, d as loadActiveCallsFromStore, g as appendCallReplayKey, l as findCallInStore, p as persistCallRecord, t as resolveDefaultVoiceCallStoreDir, u as getCallHistoryFromStore, v as rememberManagerReplayKey, x as TerminalStates, y as reserveRejectedProviderCall } from "./store-path-
|
|
4
|
+
import { _ as releaseRejectedProviderCall, b as setVoiceCallStateRuntime, d as loadActiveCallsFromStore, g as appendCallReplayKey, l as findCallInStore, p as persistCallRecord, t as resolveDefaultVoiceCallStoreDir, u as getCallHistoryFromStore, v as rememberManagerReplayKey, x as TerminalStates, y as reserveRejectedProviderCall } from "./store-path-M0GXxUfv.js";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
5
6
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
6
7
|
import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
|
|
7
8
|
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
@@ -24,7 +25,6 @@ import { runCommandWithTimeout } from "openclaw/plugin-sdk/process-runtime";
|
|
|
24
25
|
import http from "node:http";
|
|
25
26
|
import { URL as URL$1 } from "node:url";
|
|
26
27
|
import { resolveConfiguredCapabilityProvider } from "openclaw/plugin-sdk/provider-selection-runtime";
|
|
27
|
-
import { WebSocket, WebSocketServer } from "ws";
|
|
28
28
|
import { canonicalizeBase64 } from "openclaw/plugin-sdk/media-runtime";
|
|
29
29
|
//#region extensions/voice-call/src/allowlist.ts
|
|
30
30
|
/** Normalize a phone number to digits only. */
|
|
@@ -1850,6 +1850,10 @@ function canonicalizeVoiceCallMediaBase64(payloadBase64) {
|
|
|
1850
1850
|
return canonicalizeBase64(payloadBase64.replaceAll("-", "+").replaceAll("_", "/"));
|
|
1851
1851
|
}
|
|
1852
1852
|
//#endregion
|
|
1853
|
+
//#region extensions/voice-call/src/websocket.ts
|
|
1854
|
+
const require = createRequire(import.meta.url);
|
|
1855
|
+
const { WebSocket, WebSocketServer } = require(path.join(path.dirname(require.resolve("ws/package.json")), "index.js"));
|
|
1856
|
+
//#endregion
|
|
1853
1857
|
//#region extensions/voice-call/src/media-stream.ts
|
|
1854
1858
|
const DEFAULT_PRE_START_TIMEOUT_MS = 5e3;
|
|
1855
1859
|
const DEFAULT_MAX_PENDING_CONNECTIONS = 32;
|
|
@@ -2687,7 +2691,7 @@ const MAX_WEBHOOK_BODY_BYTES = WEBHOOK_BODY_READ_DEFAULTS.preAuth.maxBytes;
|
|
|
2687
2691
|
const WEBHOOK_BODY_TIMEOUT_MS = WEBHOOK_BODY_READ_DEFAULTS.preAuth.timeoutMs;
|
|
2688
2692
|
const MISSING_REMOTE_ADDRESS_IN_FLIGHT_KEY = "__voice_call_no_remote__";
|
|
2689
2693
|
const loadRealtimeTranscriptionRuntime = createLazyRuntimeModule(() => import("./realtime-transcription.runtime-CbJAs5t_.js"));
|
|
2690
|
-
const loadResponseGeneratorModule = createLazyRuntimeModule(() => import("./response-generator-
|
|
2694
|
+
const loadResponseGeneratorModule = createLazyRuntimeModule(() => import("./response-generator-IX26g0hi.js"));
|
|
2691
2695
|
function appendRecentTalkEventMetadata(call, event) {
|
|
2692
2696
|
const metadata = call.metadata ?? {};
|
|
2693
2697
|
const recent = Array.isArray(metadata.recentTalkEvents) ? metadata.recentTalkEvents.filter((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry)) : [];
|
|
@@ -3413,12 +3417,12 @@ const REALTIME_VOICE_CONSULT_SYSTEM_PROMPT = [
|
|
|
3413
3417
|
"Do not print secret values or dump environment variables; only check whether required configuration is present.",
|
|
3414
3418
|
"Be accurate, brief, and speakable."
|
|
3415
3419
|
].join(" ");
|
|
3416
|
-
const loadTelnyxProvider = createLazyRuntimeModule(() => import("./telnyx-
|
|
3417
|
-
const loadTwilioProvider = createLazyRuntimeModule(() => import("./twilio-
|
|
3418
|
-
const loadPlivoProvider = createLazyRuntimeModule(() => import("./plivo-
|
|
3420
|
+
const loadTelnyxProvider = createLazyRuntimeModule(() => import("./telnyx-B8shXuBM.js"));
|
|
3421
|
+
const loadTwilioProvider = createLazyRuntimeModule(() => import("./twilio-DhsTO8-E.js"));
|
|
3422
|
+
const loadPlivoProvider = createLazyRuntimeModule(() => import("./plivo-qSdVTUcE.js"));
|
|
3419
3423
|
const loadMockProvider = createLazyRuntimeModule(() => import("./mock-C57qj18W.js"));
|
|
3420
3424
|
const loadRealtimeVoiceRuntime = createLazyRuntimeModule(() => import("./realtime-voice.runtime-vtdCOWg-.js"));
|
|
3421
|
-
const loadRealtimeHandler = createLazyRuntimeModule(() => import("./realtime-handler-
|
|
3425
|
+
const loadRealtimeHandler = createLazyRuntimeModule(() => import("./realtime-handler-BSW48gqM.js"));
|
|
3422
3426
|
function resolveVoiceCallConsultSessionKey(call) {
|
|
3423
3427
|
return resolveVoiceCallSessionKey({
|
|
3424
3428
|
config: call.config,
|
|
@@ -3760,4 +3764,4 @@ async function createVoiceCallRuntime(params) {
|
|
|
3760
3764
|
}
|
|
3761
3765
|
}
|
|
3762
3766
|
//#endregion
|
|
3763
|
-
export {
|
|
3767
|
+
export { resolveCallAgentId as _, normalizeProviderStatus as a, escapeXml as b, canonicalizeVoiceCallMediaBase64 as c, cleanupTailscaleExposureRoute as d, getTailscaleSelfInfo as f, resolveVoiceResponseModel as g, chunkAudio as h, mapProviderStatusToEndReason as i, getHeader as l, TELEPHONY_DEFAULT_TTS_TIMEOUT_MS as m, normalizeProxyIp as n, WebSocket as o, setupTailscaleExposureRoutes as p, isProviderStatusTerminal as r, WebSocketServer as s, createVoiceCallRuntime as t, resolveWebhookExposureStatus as u, resolveVoiceCallAgentId as v, mapVoiceToPolly as x, resolveUserPath as y };
|
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-B8SNb2qD.js";
|
|
2
2
|
export { createVoiceCallRuntime };
|
|
@@ -10,34 +10,6 @@ const ProviderNameSchema = z.enum([
|
|
|
10
10
|
"plivo",
|
|
11
11
|
"mock"
|
|
12
12
|
]);
|
|
13
|
-
const CallStateSchema = z.enum([
|
|
14
|
-
"initiated",
|
|
15
|
-
"ringing",
|
|
16
|
-
"answered",
|
|
17
|
-
"active",
|
|
18
|
-
"speaking",
|
|
19
|
-
"listening",
|
|
20
|
-
"completed",
|
|
21
|
-
"hangup-user",
|
|
22
|
-
"hangup-bot",
|
|
23
|
-
"timeout",
|
|
24
|
-
"error",
|
|
25
|
-
"failed",
|
|
26
|
-
"no-answer",
|
|
27
|
-
"busy",
|
|
28
|
-
"voicemail"
|
|
29
|
-
]);
|
|
30
|
-
const TerminalStates = /* @__PURE__ */ new Set([
|
|
31
|
-
"completed",
|
|
32
|
-
"hangup-user",
|
|
33
|
-
"hangup-bot",
|
|
34
|
-
"timeout",
|
|
35
|
-
"error",
|
|
36
|
-
"failed",
|
|
37
|
-
"no-answer",
|
|
38
|
-
"busy",
|
|
39
|
-
"voicemail"
|
|
40
|
-
]);
|
|
41
13
|
const EndReasonSchema = z.enum([
|
|
42
14
|
"completed",
|
|
43
15
|
"hangup-user",
|
|
@@ -49,54 +21,16 @@ const EndReasonSchema = z.enum([
|
|
|
49
21
|
"busy",
|
|
50
22
|
"voicemail"
|
|
51
23
|
]);
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
from: z.string().optional(),
|
|
61
|
-
to: z.string().optional()
|
|
62
|
-
});
|
|
63
|
-
z.discriminatedUnion("type", [
|
|
64
|
-
BaseEventSchema.extend({ type: z.literal("call.initiated") }),
|
|
65
|
-
BaseEventSchema.extend({ type: z.literal("call.ringing") }),
|
|
66
|
-
BaseEventSchema.extend({ type: z.literal("call.answered") }),
|
|
67
|
-
BaseEventSchema.extend({ type: z.literal("call.active") }),
|
|
68
|
-
BaseEventSchema.extend({
|
|
69
|
-
type: z.literal("call.speaking"),
|
|
70
|
-
text: z.string()
|
|
71
|
-
}),
|
|
72
|
-
BaseEventSchema.extend({
|
|
73
|
-
type: z.literal("call.assistant-speech"),
|
|
74
|
-
transcript: z.string()
|
|
75
|
-
}),
|
|
76
|
-
BaseEventSchema.extend({
|
|
77
|
-
type: z.literal("call.speech"),
|
|
78
|
-
transcript: z.string(),
|
|
79
|
-
isFinal: z.boolean(),
|
|
80
|
-
confidence: z.number().min(0).max(1).optional()
|
|
81
|
-
}),
|
|
82
|
-
BaseEventSchema.extend({
|
|
83
|
-
type: z.literal("call.silence"),
|
|
84
|
-
durationMs: z.number()
|
|
85
|
-
}),
|
|
86
|
-
BaseEventSchema.extend({
|
|
87
|
-
type: z.literal("call.dtmf"),
|
|
88
|
-
digits: z.string()
|
|
89
|
-
}),
|
|
90
|
-
BaseEventSchema.extend({
|
|
91
|
-
type: z.literal("call.ended"),
|
|
92
|
-
reason: EndReasonSchema
|
|
93
|
-
}),
|
|
94
|
-
BaseEventSchema.extend({
|
|
95
|
-
type: z.literal("call.error"),
|
|
96
|
-
error: z.string(),
|
|
97
|
-
retryable: z.boolean().optional()
|
|
98
|
-
})
|
|
24
|
+
const CallStateSchema = z.enum([
|
|
25
|
+
"initiated",
|
|
26
|
+
"ringing",
|
|
27
|
+
"answered",
|
|
28
|
+
"active",
|
|
29
|
+
"speaking",
|
|
30
|
+
"listening",
|
|
31
|
+
...EndReasonSchema.options
|
|
99
32
|
]);
|
|
33
|
+
const TerminalStates = new Set(EndReasonSchema.options);
|
|
100
34
|
const CallDirectionSchema = z.enum(["outbound", "inbound"]);
|
|
101
35
|
const TranscriptEntrySchema = z.object({
|
|
102
36
|
timestamp: z.number(),
|
|
@@ -358,12 +292,14 @@ function pruneCallRecordEvents(stores) {
|
|
|
358
292
|
for (const row of sorted.slice(0, rows.length - MAX_CALL_RECORD_EVENTS)) deleteCallRecordEventRows(stores, row.key);
|
|
359
293
|
}
|
|
360
294
|
/** Read and reassemble one chunked call record event. */
|
|
361
|
-
function readCallRecordEvent(stores, eventKey) {
|
|
362
|
-
|
|
363
|
-
|
|
295
|
+
function readCallRecordEvent(stores, eventKey, meta) {
|
|
296
|
+
if (!Number.isSafeInteger(meta.chunkCount) || meta.chunkCount < 1 || meta.chunkCount > 48) return null;
|
|
297
|
+
const records = stores.chunks.lookupMany?.(Array.from({ length: meta.chunkCount }, (_, index) => buildChunkKey(eventKey, index)));
|
|
364
298
|
const chunks = [];
|
|
365
299
|
for (let index = 0; index < meta.chunkCount; index += 1) {
|
|
366
|
-
const
|
|
300
|
+
const result = records?.[index];
|
|
301
|
+
if (result && !result.ok) throw result.error;
|
|
302
|
+
const chunk = records ? result?.value : stores.chunks.lookup(buildChunkKey(eventKey, index));
|
|
367
303
|
if (!chunk || chunk.index !== index) return null;
|
|
368
304
|
chunks.push(Buffer.from(chunk.dataBase64, "base64"));
|
|
369
305
|
}
|
|
@@ -372,7 +308,7 @@ function readCallRecordEvent(stores, eventKey) {
|
|
|
372
308
|
/** Read all persisted call records in stable persisted order. */
|
|
373
309
|
function readCallRecordEvents(stores) {
|
|
374
310
|
return stores.events.entries().toSorted((a, b) => a.createdAt - b.createdAt || a.key.localeCompare(b.key)).map((entry) => {
|
|
375
|
-
const call = readCallRecordEvent(stores, entry.key);
|
|
311
|
+
const call = readCallRecordEvent(stores, entry.key, entry.value);
|
|
376
312
|
return call ? {
|
|
377
313
|
call,
|
|
378
314
|
persistedAt: entry.value.persistedAt ?? entry.createdAt,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { s as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Z9SuGiD_.js";
|
|
2
2
|
import crypto from "node:crypto";
|
|
3
3
|
//#region extensions/voice-call/src/providers/telnyx.ts
|
|
4
4
|
function normalizeTelnyxDirection(direction) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { fetchWithSsrFGuard } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
3
|
import { n as requireSupportedTwilioApiHostname, r as resolveTwilioApiBaseUrl } from "./twilio-region-4fkgz3UG.js";
|
|
4
|
-
import { a as normalizeProviderStatus,
|
|
5
|
-
import { c as verifyTwilioWebhook, i as readVoiceCallProviderJsonResponse, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
4
|
+
import { a as normalizeProviderStatus, b as escapeXml, h as chunkAudio, i as mapProviderStatusToEndReason, l as getHeader, r as isProviderStatusTerminal, x as mapVoiceToPolly } from "./runtime-entry-B8SNb2qD.js";
|
|
5
|
+
import { c as verifyTwilioWebhook, i as readVoiceCallProviderJsonResponse, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-Z9SuGiD_.js";
|
|
6
6
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
7
|
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
8
8
|
import crypto from "node:crypto";
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "voice-call",
|
|
3
3
|
"doctorContract": {
|
|
4
4
|
"resolveSessionStoreAgentIds": true,
|
|
5
|
-
"stateMigrations":
|
|
5
|
+
"stateMigrations": [{ "id": "voice-call-calls-jsonl-to-plugin-state" }]
|
|
6
6
|
},
|
|
7
7
|
"name": "Voice Call",
|
|
8
8
|
"description": "OpenClaw voice-call plugin for Twilio, Telnyx, and Plivo phone calls.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/voice-call",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.3",
|
|
4
4
|
"description": "OpenClaw voice-call plugin for Twilio, Telnyx, and Plivo phone calls.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"zod": "4.4.3"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"openclaw": ">=2026.9.
|
|
16
|
+
"openclaw": ">=2026.9.3"
|
|
17
17
|
},
|
|
18
18
|
"peerDependenciesMeta": {
|
|
19
19
|
"openclaw": {
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"minHostVersion": ">=2026.4.10"
|
|
32
32
|
},
|
|
33
33
|
"compat": {
|
|
34
|
-
"pluginApi": ">=2026.9.
|
|
34
|
+
"pluginApi": ">=2026.9.3"
|
|
35
35
|
},
|
|
36
36
|
"build": {
|
|
37
|
-
"openclawVersion": "2026.9.
|
|
37
|
+
"openclawVersion": "2026.9.3"
|
|
38
38
|
},
|
|
39
39
|
"release": {
|
|
40
40
|
"publishToClawHub": true,
|