@openclaw/voice-call 2026.5.31-beta.3 → 2026.5.31-beta.4

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.
@@ -58,7 +58,7 @@ function prepareChunks(call) {
58
58
  };
59
59
  }
60
60
  async function readLegacyCallRecords(filePath) {
61
- let content = "";
61
+ let content;
62
62
  try {
63
63
  content = await fs.readFile(filePath, "utf8");
64
64
  } catch {
@@ -1,6 +1,6 @@
1
1
  import { fetchWithSsrFGuard } from "./runtime-api.js";
2
2
  import "./api.js";
3
- import { a as getHeader } from "./runtime-entry-jfYyJL2N.js";
3
+ import { a as getHeader } from "./runtime-entry-13O0Ki99.js";
4
4
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
5
  import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
6
6
  import { isFutureDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
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-BKyRNKHF.js";
4
- import { c as getTailscaleSelfInfo, l as setupTailscaleExposureRoute, o as resolveWebhookExposureStatus, p as resolveUserPath, s as cleanupTailscaleExposureRoute, t as createVoiceCallRuntime } from "./runtime-entry-jfYyJL2N.js";
4
+ import { c as getTailscaleSelfInfo, l as setupTailscaleExposureRoute, o as resolveWebhookExposureStatus, p as resolveUserPath, s as cleanupTailscaleExposureRoute, t as createVoiceCallRuntime } from "./runtime-entry-13O0Ki99.js";
5
5
  import { c as getCallHistoryFromStore, m as setVoiceCallStateRuntime } from "./store-XuAPgOJG.js";
6
6
  import { i as parseVoiceCallPluginConfig, r as normalizeVoiceCallLegacyConfigInput, t as formatVoiceCallLegacyConfigWarnings } from "./config-compat-BLdRz9GR.js";
7
7
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
@@ -1,5 +1,5 @@
1
- import { a as getHeader, m as escapeXml } from "./runtime-entry-jfYyJL2N.js";
2
- import { n as reconstructWebhookUrl, r as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Xqw21Tku.js";
1
+ import { a as getHeader, m as escapeXml } from "./runtime-entry-13O0Ki99.js";
2
+ import { n as reconstructWebhookUrl, r as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-tyxHyrev.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
@@ -83,7 +83,7 @@ var RealtimeAudioPacer = class {
83
83
  const item = this.queue.shift();
84
84
  if (!item) return;
85
85
  let delayMs = 0;
86
- let sent = true;
86
+ let sent;
87
87
  if (item.type === "audio") {
88
88
  this.queuedAudioBytes = Math.max(0, this.queuedAudioBytes - item.chunk.length);
89
89
  sent = this.params.send(this.params.serializer.media(item.chunk.toString("base64")));
@@ -986,7 +986,9 @@ var RealtimeCallHandler = class {
986
986
  const now = Date.now();
987
987
  const quietFor = now - updatedAt;
988
988
  if (quietFor >= CONSULT_TRANSCRIPT_SETTLE_MS || now >= deadline) return;
989
- await new Promise((resolve) => setTimeout(resolve, Math.min(CONSULT_TRANSCRIPT_SETTLE_MS - quietFor, deadline - now)));
989
+ await new Promise((resolve) => {
990
+ setTimeout(resolve, Math.min(CONSULT_TRANSCRIPT_SETTLE_MS - quietFor, deadline - now));
991
+ });
990
992
  }
991
993
  }
992
994
  clearForcedConsultState(callId) {
@@ -1,5 +1,5 @@
1
1
  import { o as resolveVoiceCallSessionKey } from "./config-BKyRNKHF.js";
2
- import { f as resolveVoiceResponseModel } from "./runtime-entry-jfYyJL2N.js";
2
+ import { f as resolveVoiceResponseModel } from "./runtime-entry-13O0Ki99.js";
3
3
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } 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";
@@ -87,15 +87,17 @@ function startMaxDurationTimer(params) {
87
87
  clearMaxDurationTimer(params.ctx, params.callId);
88
88
  const maxDurationMs = params.timeoutMs === void 0 ? resolveVoiceCallSecondsTimerDelayMs(params.ctx.config.maxDurationSeconds) : resolveVoiceCallTimerDelayMs(params.timeoutMs);
89
89
  console.log(`[voice-call] Starting max duration timer (${Math.ceil(maxDurationMs / 1e3)}s) for call ${params.callId}`);
90
- const timer = setTimeout(async () => {
91
- params.ctx.maxDurationTimers.delete(params.callId);
92
- const call = params.ctx.activeCalls.get(params.callId);
93
- if (call && !TerminalStates.has(call.state)) {
94
- console.log(`[voice-call] Max duration reached (${Math.ceil(maxDurationMs / 1e3)}s), ending call ${params.callId}`);
95
- call.endReason = "timeout";
96
- persistCallRecord(params.ctx.storePath, call);
97
- await params.onTimeout(params.callId);
98
- }
90
+ const timer = setTimeout(() => {
91
+ (async () => {
92
+ params.ctx.maxDurationTimers.delete(params.callId);
93
+ const call = params.ctx.activeCalls.get(params.callId);
94
+ if (call && !TerminalStates.has(call.state)) {
95
+ console.log(`[voice-call] Max duration reached (${Math.ceil(maxDurationMs / 1e3)}s), ending call ${params.callId}`);
96
+ call.endReason = "timeout";
97
+ persistCallRecord(params.ctx.storePath, call);
98
+ await params.onTimeout(params.callId);
99
+ }
100
+ })();
99
101
  }, maxDurationMs);
100
102
  params.ctx.maxDurationTimers.set(params.callId, timer);
101
103
  }
@@ -490,12 +492,14 @@ async function speakInitialMessage(ctx, providerCallId) {
490
492
  const delaySec = ctx.config.outbound.notifyHangupDelaySec;
491
493
  const delayMs = resolveVoiceCallSecondsTimerDelayMs(delaySec, 0);
492
494
  console.log(`[voice-call] Notify mode: auto-hangup in ${delaySec}s for call ${call.callId}`);
493
- setTimeout(async () => {
494
- const currentCall = ctx.activeCalls.get(call.callId);
495
- if (currentCall && !TerminalStates.has(currentCall.state)) {
496
- console.log(`[voice-call] Notify mode: hanging up call ${call.callId}`);
497
- await endCall(ctx, call.callId);
498
- }
495
+ setTimeout(() => {
496
+ (async () => {
497
+ const currentCall = ctx.activeCalls.get(call.callId);
498
+ if (currentCall && !TerminalStates.has(currentCall.state)) {
499
+ console.log(`[voice-call] Notify mode: hanging up call ${call.callId}`);
500
+ await endCall(ctx, call.callId);
501
+ }
502
+ })();
499
503
  }, delayMs);
500
504
  } else if (mode === "conversation" && ctx.provider && shouldStartListeningAfterInitialMessage(ctx)) {
501
505
  transitionState(call, "listening");
@@ -1786,7 +1790,9 @@ var MediaStreamHandler = class {
1786
1790
  noServer: true,
1787
1791
  maxPayload: MAX_INBOUND_MESSAGE_BYTES
1788
1792
  });
1789
- this.wss.on("connection", (ws, req) => this.handleConnection(ws, req));
1793
+ this.wss.on("connection", (ws, req) => {
1794
+ this.handleConnection(ws, req);
1795
+ });
1790
1796
  }
1791
1797
  if (this.getCurrentConnectionCount() >= this.maxConnections) {
1792
1798
  this.rejectUpgrade(socket, 503, "Too many media stream connections");
@@ -1831,7 +1837,7 @@ var MediaStreamHandler = class {
1831
1837
  ws.close(1013, "Too many pending media stream connections");
1832
1838
  return;
1833
1839
  }
1834
- ws.on("message", async (data) => {
1840
+ ws.on("message", (data) => {
1835
1841
  try {
1836
1842
  const message = parseTwilioMediaMessage(data);
1837
1843
  switch (message.event) {
@@ -2422,7 +2428,7 @@ function loadRealtimeTranscriptionRuntime() {
2422
2428
  return realtimeTranscriptionRuntimePromise;
2423
2429
  }
2424
2430
  function loadResponseGeneratorModule() {
2425
- responseGeneratorModulePromise ??= import("./response-generator-Drtih8-c.js");
2431
+ responseGeneratorModulePromise ??= import("./response-generator-D6UsHyfH.js");
2426
2432
  return responseGeneratorModulePromise;
2427
2433
  }
2428
2434
  function sanitizeTranscriptForLog(value) {
@@ -3106,15 +3112,15 @@ let mockProviderPromise;
3106
3112
  let realtimeVoiceRuntimePromise;
3107
3113
  let realtimeHandlerPromise;
3108
3114
  function loadTelnyxProvider() {
3109
- telnyxProviderPromise ??= import("./telnyx-nVwnn20d.js");
3115
+ telnyxProviderPromise ??= import("./telnyx-68EYJwaz.js");
3110
3116
  return telnyxProviderPromise;
3111
3117
  }
3112
3118
  function loadTwilioProvider() {
3113
- twilioProviderPromise ??= import("./twilio-PJ1mjc8C.js");
3119
+ twilioProviderPromise ??= import("./twilio-D0dUSGam.js");
3114
3120
  return twilioProviderPromise;
3115
3121
  }
3116
3122
  function loadPlivoProvider() {
3117
- plivoProviderPromise ??= import("./plivo-9ceKrjuk.js");
3123
+ plivoProviderPromise ??= import("./plivo-DeSZeJ0S.js");
3118
3124
  return plivoProviderPromise;
3119
3125
  }
3120
3126
  function loadMockProvider() {
@@ -3126,7 +3132,7 @@ function loadRealtimeVoiceRuntime() {
3126
3132
  return realtimeVoiceRuntimePromise;
3127
3133
  }
3128
3134
  function loadRealtimeHandler() {
3129
- realtimeHandlerPromise ??= import("./realtime-handler-RU9ZmesO.js");
3135
+ realtimeHandlerPromise ??= import("./realtime-handler-BP6_qBNe.js");
3130
3136
  return realtimeHandlerPromise;
3131
3137
  }
3132
3138
  function resolveVoiceCallConsultSessionKey(call) {
@@ -1,2 +1,2 @@
1
- import { t as createVoiceCallRuntime } from "./runtime-entry-jfYyJL2N.js";
1
+ import { t as createVoiceCallRuntime } from "./runtime-entry-13O0Ki99.js";
2
2
  export { createVoiceCallRuntime };
@@ -1,4 +1,4 @@
1
- import { i as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Xqw21Tku.js";
1
+ import { i as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-tyxHyrev.js";
2
2
  import crypto from "node:crypto";
3
3
  //#region extensions/voice-call/src/providers/telnyx.ts
4
4
  function normalizeTelnyxDirection(direction) {
@@ -1,7 +1,7 @@
1
1
  import { fetchWithSsrFGuard } from "./runtime-api.js";
2
2
  import "./api.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-jfYyJL2N.js";
4
- import { a as verifyTwilioWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Xqw21Tku.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-13O0Ki99.js";
4
+ import { a as verifyTwilioWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-tyxHyrev.js";
5
5
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import crypto from "node:crypto";
7
7
  import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
@@ -251,17 +251,15 @@ var TwilioProvider = class TwilioProvider {
251
251
  });
252
252
  }
253
253
  async updateLiveCallTwiml(providerCallId, twiml, operation) {
254
- let retryIndex = 0;
255
- while (true) try {
254
+ for (const retryDelayMs of TWILIO_CALL_UPDATE_RETRY_DELAYS_MS) try {
256
255
  await this.apiRequest(`/Calls/${providerCallId}.json`, { Twiml: twiml });
257
256
  return;
258
257
  } catch (err) {
259
- const retryDelayMs = TWILIO_CALL_UPDATE_RETRY_DELAYS_MS[retryIndex];
260
- if (retryDelayMs === void 0 || !isTwilioCallNotInProgressError(err)) throw err;
261
- retryIndex += 1;
258
+ if (!isTwilioCallNotInProgressError(err)) throw err;
262
259
  console.warn(`[voice-call] Twilio ${operation} update hit call state race (21220); retrying in ${retryDelayMs}ms`);
263
260
  await setTimeout$1(retryDelayMs);
264
261
  }
262
+ await this.apiRequest(`/Calls/${providerCallId}.json`, { Twiml: twiml });
265
263
  }
266
264
  /**
267
265
  * Verify Twilio webhook signature using HMAC-SHA1.
@@ -618,7 +616,9 @@ var TwilioProvider = class TwilioProvider {
618
616
  chunkAttempts += 1;
619
617
  if (sendAudioChunk(chunk).sent) chunkDelivered += 1;
620
618
  const waitMs = nextChunkDueAt - Date.now();
621
- if (waitMs > 0) await new Promise((resolve) => setTimeout(resolve, Math.ceil(waitMs)));
619
+ if (waitMs > 0) await new Promise((resolve) => {
620
+ setTimeout(resolve, Math.ceil(waitMs));
621
+ });
622
622
  nextChunkDueAt += CHUNK_DELAY_MS;
623
623
  if (signal.aborted) break;
624
624
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/voice-call",
3
- "version": "2026.5.31-beta.3",
3
+ "version": "2026.5.31-beta.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/voice-call",
9
- "version": "2026.5.31-beta.3",
9
+ "version": "2026.5.31-beta.4",
10
10
  "dependencies": {
11
11
  "commander": "14.0.3",
12
12
  "typebox": "1.1.39",
@@ -14,7 +14,7 @@
14
14
  "zod": "4.4.3"
15
15
  },
16
16
  "peerDependencies": {
17
- "openclaw": ">=2026.5.31-beta.3"
17
+ "openclaw": ">=2026.5.31-beta.4"
18
18
  },
19
19
  "peerDependenciesMeta": {
20
20
  "openclaw": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/voice-call",
3
- "version": "2026.5.31-beta.3",
3
+ "version": "2026.5.31-beta.4",
4
4
  "description": "OpenClaw voice-call plugin for Twilio, Telnyx, and Plivo phone calls.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,7 @@
14
14
  "zod": "4.4.3"
15
15
  },
16
16
  "peerDependencies": {
17
- "openclaw": ">=2026.5.31-beta.3"
17
+ "openclaw": ">=2026.5.31-beta.4"
18
18
  },
19
19
  "peerDependenciesMeta": {
20
20
  "openclaw": {
@@ -31,10 +31,10 @@
31
31
  "minHostVersion": ">=2026.4.10"
32
32
  },
33
33
  "compat": {
34
- "pluginApi": ">=2026.5.31-beta.3"
34
+ "pluginApi": ">=2026.5.31-beta.4"
35
35
  },
36
36
  "build": {
37
- "openclawVersion": "2026.5.31-beta.3"
37
+ "openclawVersion": "2026.5.31-beta.4"
38
38
  },
39
39
  "release": {
40
40
  "publishToClawHub": true,