@openclaw/voice-call 2026.7.2-beta.1 → 2026.7.2-beta.2

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.
@@ -1,7 +1,7 @@
1
- import { a as MAX_CALL_RECORD_EVENTS, d as parseVoiceCallRecordLine, i as CALL_RECORD_EVENT_META_MAX_ENTRIES, m as resolveVoiceCallLegacyCallLogPath, n as CALL_RECORD_EVENTS_NAMESPACE, o as RAW_CALL_RECORD_CHUNK_BYTES, p as prepareVoiceCallRecordForStorage, r as CALL_RECORD_EVENT_CHUNKS_NAMESPACE, s as buildVoiceCallLegacyJsonlEventKey, t as CALL_RECORD_CHUNK_MAX_ENTRIES } from "./store-C1pl3avP.js";
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-nYL-yM0S.js";
2
2
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
3
- import os from "node:os";
4
3
  import path from "node:path";
4
+ import os from "node:os";
5
5
  import fs from "node:fs/promises";
6
6
  import { archiveLegacyStateSource, detectOpenClawStateDatabaseSchemaMigrations, repairOpenClawStateDatabaseSchema } from "openclaw/plugin-sdk/runtime-doctor";
7
7
  //#region extensions/voice-call/doctor-contract-api.ts
@@ -50,7 +50,7 @@ function resolveSessionStoreAgentIds(params) {
50
50
  function resolveVoiceCallStorePath(params) {
51
51
  const configuredStore = getVoiceCallConfigStore(params.config);
52
52
  if (configuredStore) return resolveUserPath(configuredStore, params.env);
53
- return path.join(resolveHome(params.env), ".openclaw", "voice-calls");
53
+ return resolveDefaultVoiceCallStoreDir(params.env);
54
54
  }
55
55
  function resolveVoiceCallStateDatabaseEnv(params) {
56
56
  return {
@@ -59,7 +59,13 @@ function resolveVoiceCallStateDatabaseEnv(params) {
59
59
  };
60
60
  }
61
61
  function describeVoiceCallSchemaMigration(migration) {
62
- return migration.kind === "agent-databases-composite-primary-key" ? "agent database registry primary key -> agent_id,path" : "audit event ledger -> versioned message lifecycle schema";
62
+ switch (migration.kind) {
63
+ case "agent-databases-composite-primary-key": return "agent database registry primary key -> agent_id,path";
64
+ case "audit-events-v2": return "audit event ledger -> versioned message lifecycle schema";
65
+ case "operator-approvals-system-agent": return "operator approvals -> OpenClaw system changes";
66
+ case "strict-tables-v3": return "tables -> SQLite STRICT typing";
67
+ }
68
+ return migration.kind;
63
69
  }
64
70
  /** Return true when a path exists and is a file. */
65
71
  /** Build the plugin state key for one migrated event chunk. */
@@ -190,15 +196,14 @@ const stateMigrations = [{
190
196
  const { entries, warnings: readWarnings } = await readLegacyCallRecords(filePath);
191
197
  warnings.push(...readWarnings);
192
198
  const stateDatabaseEnv = resolveVoiceCallStateDatabaseEnv(params);
193
- const schemaMigrations = detectOpenClawStateDatabaseSchemaMigrations({ env: stateDatabaseEnv });
194
- if (schemaMigrations.length > 0) {
199
+ if (detectOpenClawStateDatabaseSchemaMigrations({ env: stateDatabaseEnv }).length > 0) {
195
200
  const repaired = repairOpenClawStateDatabaseSchema({ env: stateDatabaseEnv });
196
201
  warnings.push(...repaired.warnings);
197
202
  if (repaired.warnings.length > 0) return {
198
203
  changes,
199
204
  warnings
200
205
  };
201
- changes.push(...schemaMigrations.map((migration) => `Migrated Voice Call SQLite ${describeVoiceCallSchemaMigration(migration)}`));
206
+ changes.push(...repaired.changes.map((change) => change.replace(/^Migrated shared state /, "Migrated Voice Call SQLite ").replaceAll("→", "->")));
202
207
  }
203
208
  if (entries.length === 0) return {
204
209
  changes,
@@ -1,6 +1,6 @@
1
1
  import { fetchWithSsrFGuard } from "./runtime-api.js";
2
2
  import "./api.js";
3
- import { n as normalizeProxyIp, o as getHeader } from "./runtime-entry-DhTLZ2uB.js";
3
+ import { n as normalizeProxyIp, o as getHeader } from "./runtime-entry-DSgyqIwE.js";
4
4
  import { n as markWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-aaP79dI8.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
@@ -1,7 +1,7 @@
1
1
  import { definePluginEntry, sleep } from "./runtime-api.js";
2
2
  import "./api.js";
3
- import { c as cleanupTailscaleExposureRoute, h as resolveUserPath, l as getTailscaleSelfInfo, s as resolveWebhookExposureStatus, t as createVoiceCallRuntime, u as setupTailscaleExposureRoute, v as VoiceCallConfigSchema, x as validateProviderConfig, y as resolveVoiceCallConfig } from "./runtime-entry-DhTLZ2uB.js";
4
- import { h as setVoiceCallStateRuntime, l as getCallHistoryFromStore } from "./store-C1pl3avP.js";
3
+ import { c as cleanupTailscaleExposureRoute, h as resolveUserPath, l as getTailscaleSelfInfo, s as resolveWebhookExposureStatus, t as createVoiceCallRuntime, u as setupTailscaleExposureRoute, v as VoiceCallConfigSchema, x as validateProviderConfig, y as resolveVoiceCallConfig } from "./runtime-entry-DSgyqIwE.js";
4
+ import { g as setVoiceCallStateRuntime, t as resolveDefaultVoiceCallStoreDir, u as getCallHistoryFromStore } from "./store-path-nYL-yM0S.js";
5
5
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
6
6
  import { ErrorCodes, callGatewayFromCli, errorShape } from "openclaw/plugin-sdk/gateway-runtime";
7
7
  import { MAX_TCP_PORT, MAX_TIMER_TIMEOUT_MS, addTimerTimeoutGraceMs, clampTimerTimeoutMs, parseStrictNonNegativeInteger, resolveTimerTimeoutMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
@@ -10,16 +10,14 @@ import { asOptionalRecord, isRecord, normalizeOptionalLowercaseString, normalize
10
10
  import { jsonResult } from "openclaw/plugin-sdk/tool-results";
11
11
  import { Type } from "typebox";
12
12
  import fs from "node:fs";
13
- import os from "node:os";
14
- import path from "node:path";
15
13
  import { randomUUID } from "node:crypto";
14
+ import path from "node:path";
16
15
  import { format } from "node:util";
17
16
  //#region extensions/voice-call/src/cli.ts
18
17
  const VOICE_CALL_GATEWAY_DEFAULT_TIMEOUT_MS = 5e3;
19
18
  const VOICE_CALL_GATEWAY_OPERATION_TIMEOUT_MS = 3e4;
20
19
  const VOICE_CALL_GATEWAY_TRANSCRIPT_BUFFER_MS = 1e4;
21
20
  const VOICE_CALL_GATEWAY_POLL_INTERVAL_MS = 1e3;
22
- const voiceCallCliDeps = { callGatewayFromCli };
23
21
  function writeStdoutLine(...values) {
24
22
  process.stdout.write(`${format(...values)}\n`);
25
23
  }
@@ -41,7 +39,7 @@ async function callVoiceCallGateway(method, params, opts) {
41
39
  const timeoutMs = typeof opts?.timeoutMs === "number" && Number.isFinite(opts.timeoutMs) ? Math.max(1, Math.ceil(opts.timeoutMs)) : VOICE_CALL_GATEWAY_DEFAULT_TIMEOUT_MS;
42
40
  return {
43
41
  ok: true,
44
- payload: await voiceCallCliDeps.callGatewayFromCli(method, {
42
+ payload: await callGatewayFromCli(method, {
45
43
  json: true,
46
44
  timeout: String(timeoutMs)
47
45
  }, params, { progress: false })
@@ -105,15 +103,7 @@ function resolveMode(input) {
105
103
  return "funnel";
106
104
  }
107
105
  function resolveDefaultStorePath(config) {
108
- const resolvedPreferred = resolveUserPath(path.join(os.homedir(), ".openclaw", "voice-calls"));
109
- const existing = [resolvedPreferred].find((dir) => {
110
- try {
111
- return fs.existsSync(path.join(dir, "calls.jsonl")) || fs.existsSync(dir);
112
- } catch {
113
- return false;
114
- }
115
- }) ?? resolvedPreferred;
116
- const base = config.store?.trim() ? resolveUserPath(config.store) : existing;
106
+ const base = config.store?.trim() ? resolveUserPath(config.store) : resolveDefaultVoiceCallStoreDir();
117
107
  return path.join(base, "calls.jsonl");
118
108
  }
119
109
  function percentile(values, p) {
@@ -1,5 +1,5 @@
1
- import { g as escapeXml, o as getHeader } from "./runtime-entry-DhTLZ2uB.js";
2
- import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-DoLAoIRF.js";
1
+ import { g as escapeXml, o as getHeader } from "./runtime-entry-DSgyqIwE.js";
2
+ import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-BKOgUU1q.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,4 +1,4 @@
1
- import { b as resolveVoiceCallSessionKey, m as resolveCallAgentId, p as resolveVoiceResponseModel } from "./runtime-entry-DhTLZ2uB.js";
1
+ import { b as resolveVoiceCallSessionKey, m as resolveCallAgentId, p as resolveVoiceResponseModel } from "./runtime-entry-DSgyqIwE.js";
2
2
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import crypto from "node:crypto";
4
4
  import { ModelSelectionLockedError, applyModelOverrideToSessionEntry, resolvePersistedSessionRuntimeId } from "openclaw/plugin-sdk/model-session-runtime";
@@ -1,7 +1,7 @@
1
1
  import { TtsConfigSchema, isBlockedHostnameOrIp, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText } from "./runtime-api.js";
2
2
  import "./api.js";
3
3
  import { t as TWILIO_REGIONS } from "./twilio-region-4fkgz3UG.js";
4
- import { c as findCallMatchesInStore, f as persistCallRecord, g as TerminalStates, h as setVoiceCallStateRuntime, l as getCallHistoryFromStore, u as loadActiveCallsFromStore } from "./store-C1pl3avP.js";
4
+ import { _ as TerminalStates, d as loadActiveCallsFromStore, g as setVoiceCallStateRuntime, l as findCallMatchesInStore, p as persistCallRecord, t as resolveDefaultVoiceCallStoreDir, u as getCallHistoryFromStore } from "./store-path-nYL-yM0S.js";
5
5
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
6
6
  import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
7
7
  import { MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
@@ -13,13 +13,14 @@ import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, REALTIME_VOICE_AGENT_CONSULT_TO
13
13
  import { mergeDeep } from "openclaw/plugin-sdk/plugin-config-runtime";
14
14
  import { buildSecretInputSchema, hasConfiguredSecretInput, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
15
15
  import { canonicalizeMainSessionAlias } from "openclaw/plugin-sdk/session-store-runtime";
16
+ import { resolveSpeechProviderApiKey } from "openclaw/plugin-sdk/speech-core";
16
17
  import { WEBHOOK_BODY_READ_DEFAULTS, createWebhookInFlightLimiter, normalizeWebhookPath } from "openclaw/plugin-sdk/webhook-ingress";
17
18
  import { z } from "zod";
18
19
  import fs from "node:fs";
19
- import os from "node:os";
20
- import path from "node:path";
21
20
  import crypto from "node:crypto";
22
21
  import { redactIdentifier } from "openclaw/plugin-sdk/logging-core";
22
+ import path from "node:path";
23
+ import os from "node:os";
23
24
  import { root } from "openclaw/plugin-sdk/security-runtime";
24
25
  import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
25
26
  import { parseTtsDirectives } from "openclaw/plugin-sdk/speech";
@@ -586,28 +587,28 @@ function resolveVoiceCallConfig(config) {
586
587
  const resolved = normalizeVoiceCallConfig(config);
587
588
  if (resolved.provider === "telnyx") {
588
589
  resolved.telnyx = resolved.telnyx ?? {};
589
- resolved.telnyx.apiKey = resolved.telnyx.apiKey ?? process.env.TELNYX_API_KEY;
590
- resolved.telnyx.connectionId = resolved.telnyx.connectionId ?? process.env.TELNYX_CONNECTION_ID;
591
- resolved.telnyx.publicKey = resolved.telnyx.publicKey ?? process.env.TELNYX_PUBLIC_KEY;
590
+ resolved.telnyx.apiKey = resolved.telnyx.apiKey ?? resolveSpeechProviderApiKey(process.env.TELNYX_API_KEY);
591
+ resolved.telnyx.connectionId = resolved.telnyx.connectionId ?? resolveSpeechProviderApiKey(process.env.TELNYX_CONNECTION_ID);
592
+ resolved.telnyx.publicKey = resolved.telnyx.publicKey ?? resolveSpeechProviderApiKey(process.env.TELNYX_PUBLIC_KEY);
592
593
  }
593
594
  if (resolved.provider === "twilio") {
594
- resolved.fromNumber = resolved.fromNumber ?? process.env.TWILIO_FROM_NUMBER;
595
+ resolved.fromNumber = resolved.fromNumber ?? resolveSpeechProviderApiKey(process.env.TWILIO_FROM_NUMBER);
595
596
  resolved.twilio = resolved.twilio ?? {};
596
- resolved.twilio.accountSid = resolved.twilio.accountSid ?? process.env.TWILIO_ACCOUNT_SID;
597
- resolved.twilio.authToken = resolved.twilio.authToken ?? process.env.TWILIO_AUTH_TOKEN;
597
+ resolved.twilio.accountSid = resolved.twilio.accountSid ?? resolveSpeechProviderApiKey(process.env.TWILIO_ACCOUNT_SID);
598
+ resolved.twilio.authToken = resolved.twilio.authToken ?? resolveSpeechProviderApiKey(process.env.TWILIO_AUTH_TOKEN);
598
599
  }
599
600
  if (resolved.provider === "plivo") {
600
601
  resolved.plivo = resolved.plivo ?? {};
601
- resolved.plivo.authId = resolved.plivo.authId ?? process.env.PLIVO_AUTH_ID;
602
- resolved.plivo.authToken = resolved.plivo.authToken ?? process.env.PLIVO_AUTH_TOKEN;
602
+ resolved.plivo.authId = resolved.plivo.authId ?? resolveSpeechProviderApiKey(process.env.PLIVO_AUTH_ID);
603
+ resolved.plivo.authToken = resolved.plivo.authToken ?? resolveSpeechProviderApiKey(process.env.PLIVO_AUTH_TOKEN);
603
604
  }
604
605
  resolved.tunnel = resolved.tunnel ?? {
605
606
  provider: "none",
606
607
  allowNgrokFreeTierLoopbackBypass: false
607
608
  };
608
609
  resolved.tunnel.allowNgrokFreeTierLoopbackBypass = resolved.tunnel.allowNgrokFreeTierLoopbackBypass ?? false;
609
- resolved.tunnel.ngrokAuthToken = resolved.tunnel.ngrokAuthToken ?? process.env.NGROK_AUTHTOKEN;
610
- resolved.tunnel.ngrokDomain = resolved.tunnel.ngrokDomain ?? process.env.NGROK_DOMAIN;
610
+ resolved.tunnel.ngrokAuthToken = resolved.tunnel.ngrokAuthToken ?? resolveSpeechProviderApiKey(process.env.NGROK_AUTHTOKEN);
611
+ resolved.tunnel.ngrokDomain = resolved.tunnel.ngrokDomain ?? resolveSpeechProviderApiKey(process.env.NGROK_DOMAIN);
611
612
  resolved.webhookSecurity = resolved.webhookSecurity ?? {
612
613
  allowedHosts: [],
613
614
  trustForwardingHeaders: false,
@@ -1552,14 +1553,7 @@ function resolveRestoredMaxDurationAnchor(call) {
1552
1553
  function resolveDefaultStoreBase(config, storePath) {
1553
1554
  const rawOverride = storePath?.trim() || config.store?.trim();
1554
1555
  if (rawOverride) return resolveUserPath(rawOverride);
1555
- const preferred = path.join(os.homedir(), ".openclaw", "voice-calls");
1556
- return [preferred].map((dir) => resolveUserPath(dir)).find((dir) => {
1557
- try {
1558
- return fs.existsSync(path.join(dir, "calls.jsonl")) || fs.existsSync(dir);
1559
- } catch {
1560
- return false;
1561
- }
1562
- }) ?? resolveUserPath(preferred);
1556
+ return resolveDefaultVoiceCallStoreDir();
1563
1557
  }
1564
1558
  /**
1565
1559
  * Manages voice calls: state ownership and delegation to manager helper modules.
@@ -3119,15 +3113,19 @@ function startStaleCallReaper(params) {
3119
3113
  const maxAgeSeconds = params.staleCallReaperSeconds;
3120
3114
  if (!maxAgeSeconds || maxAgeSeconds <= 0) return null;
3121
3115
  const maxAgeMs = maxAgeSeconds * 1e3;
3116
+ const callsBeingReaped = /* @__PURE__ */ new Set();
3122
3117
  const interval = setInterval(() => {
3123
3118
  const now = Date.now();
3124
3119
  for (const call of params.manager.getActiveCalls()) {
3125
3120
  if (call.answeredAt || TerminalStates.has(call.state) || LiveConversationStates.has(call.state)) continue;
3126
3121
  const age = now - call.startedAt;
3127
- if (age > maxAgeMs) {
3122
+ if (age > maxAgeMs && !callsBeingReaped.has(call.callId)) {
3123
+ callsBeingReaped.add(call.callId);
3128
3124
  console.log(`[voice-call] Reaping stale call ${call.callId} (age: ${Math.round(age / 1e3)}s, state: ${call.state})`);
3129
3125
  params.manager.endCall(call.callId).catch((err) => {
3130
3126
  console.warn(`[voice-call] Reaper failed to end call ${call.callId}:`, err);
3127
+ }).finally(() => {
3128
+ callsBeingReaped.delete(call.callId);
3131
3129
  });
3132
3130
  }
3133
3131
  }
@@ -3143,7 +3141,7 @@ const WEBHOOK_BODY_TIMEOUT_MS = WEBHOOK_BODY_READ_DEFAULTS.preAuth.timeoutMs;
3143
3141
  const MISSING_REMOTE_ADDRESS_IN_FLIGHT_KEY = "__voice_call_no_remote__";
3144
3142
  const STREAM_DISCONNECT_HANGUP_GRACE_MS = 2e3;
3145
3143
  const loadRealtimeTranscriptionRuntime = createLazyRuntimeModule(() => import("./realtime-transcription.runtime-CbJAs5t_.js"));
3146
- const loadResponseGeneratorModule = createLazyRuntimeModule(() => import("./response-generator-hmAdGp5h.js"));
3144
+ const loadResponseGeneratorModule = createLazyRuntimeModule(() => import("./response-generator-Cdj8EuLg.js"));
3147
3145
  function appendRecentTalkEventMetadata(call, event) {
3148
3146
  const metadata = call.metadata ?? {};
3149
3147
  const recent = Array.isArray(metadata.recentTalkEvents) ? metadata.recentTalkEvents.filter((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry)) : [];
@@ -3818,9 +3816,9 @@ const REALTIME_VOICE_CONSULT_SYSTEM_PROMPT = [
3818
3816
  "Do not print secret values or dump environment variables; only check whether required configuration is present.",
3819
3817
  "Be accurate, brief, and speakable."
3820
3818
  ].join(" ");
3821
- const loadTelnyxProvider = createLazyRuntimeModule(() => import("./telnyx-B9tF5jeJ.js"));
3822
- const loadTwilioProvider = createLazyRuntimeModule(() => import("./twilio-U_myvowz.js"));
3823
- const loadPlivoProvider = createLazyRuntimeModule(() => import("./plivo-BICQA_yK.js"));
3819
+ const loadTelnyxProvider = createLazyRuntimeModule(() => import("./telnyx-DMbLYwj4.js"));
3820
+ const loadTwilioProvider = createLazyRuntimeModule(() => import("./twilio-BTKKlkLT.js"));
3821
+ const loadPlivoProvider = createLazyRuntimeModule(() => import("./plivo-ByAIoPFp.js"));
3824
3822
  const loadMockProvider = createLazyRuntimeModule(() => import("./mock-YsvBTX-7.js"));
3825
3823
  const loadRealtimeVoiceRuntime = createLazyRuntimeModule(() => import("./realtime-voice.runtime-vtdCOWg-.js"));
3826
3824
  const loadRealtimeHandler = createLazyRuntimeModule(() => import("./realtime-handler-DJk-eYyf.js"));
@@ -1,2 +1,2 @@
1
- import { t as createVoiceCallRuntime } from "./runtime-entry-DhTLZ2uB.js";
1
+ import { t as createVoiceCallRuntime } from "./runtime-entry-DSgyqIwE.js";
2
2
  export { createVoiceCallRuntime };
@@ -1,7 +1,8 @@
1
1
  import { z } from "zod";
2
- import path from "node:path";
3
2
  import { createHash, randomUUID } from "node:crypto";
3
+ import path from "node:path";
4
4
  import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
5
+ import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
5
6
  //#region extensions/voice-call/src/types.ts
6
7
  const ProviderNameSchema = z.enum([
7
8
  "telnyx",
@@ -124,7 +125,7 @@ const CallRecordSchema = z.object({
124
125
  });
125
126
  //#endregion
126
127
  //#region extensions/voice-call/src/runtime-state.ts
127
- const { setRuntime: setVoiceCallStateRuntime, clearRuntime: clearVoiceCallStateRuntime, tryGetRuntime: getOptionalVoiceCallStateRuntime } = createPluginRuntimeStore({
128
+ const { setRuntime: setVoiceCallStateRuntime, tryGetRuntime: getOptionalVoiceCallStateRuntime } = createPluginRuntimeStore({
128
129
  pluginId: "voice-call-state",
129
130
  errorMessage: "Voice Call state runtime not initialized"
130
131
  });
@@ -400,4 +401,10 @@ async function getCallHistoryFromStore(storePath, limit = 50) {
400
401
  return readCallHistoryFromStore(storePath).slice(-limit);
401
402
  }
402
403
  //#endregion
403
- export { MAX_CALL_RECORD_EVENTS as a, findCallMatchesInStore as c, parseVoiceCallRecordLine as d, persistCallRecord as f, TerminalStates as g, setVoiceCallStateRuntime as h, CALL_RECORD_EVENT_META_MAX_ENTRIES as i, getCallHistoryFromStore as l, resolveVoiceCallLegacyCallLogPath as m, CALL_RECORD_EVENTS_NAMESPACE as n, RAW_CALL_RECORD_CHUNK_BYTES as o, prepareVoiceCallRecordForStorage as p, CALL_RECORD_EVENT_CHUNKS_NAMESPACE as r, buildVoiceCallLegacyJsonlEventKey as s, CALL_RECORD_CHUNK_MAX_ENTRIES as t, loadActiveCallsFromStore as u };
404
+ //#region extensions/voice-call/src/store-path.ts
405
+ /** Resolve the plugin-owned store below OpenClaw's canonical state directory. */
406
+ function resolveDefaultVoiceCallStoreDir(env = process.env) {
407
+ return path.join(resolveStateDir(env), "voice-calls");
408
+ }
409
+ //#endregion
410
+ export { TerminalStates as _, CALL_RECORD_EVENT_META_MAX_ENTRIES as a, buildVoiceCallLegacyJsonlEventKey as c, loadActiveCallsFromStore as d, parseVoiceCallRecordLine as f, setVoiceCallStateRuntime as g, resolveVoiceCallLegacyCallLogPath as h, CALL_RECORD_EVENT_CHUNKS_NAMESPACE as i, findCallMatchesInStore as l, prepareVoiceCallRecordForStorage as m, CALL_RECORD_CHUNK_MAX_ENTRIES as n, MAX_CALL_RECORD_EVENTS as o, persistCallRecord as p, CALL_RECORD_EVENTS_NAMESPACE as r, RAW_CALL_RECORD_CHUNK_BYTES as s, resolveDefaultVoiceCallStoreDir as t, getCallHistoryFromStore as u };
@@ -1,4 +1,4 @@
1
- import { s as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-DoLAoIRF.js";
1
+ import { s as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-BKOgUU1q.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 { _ as mapVoiceToPolly, a as normalizeProviderStatus, f as chunkAudio, g as escapeXml, i as mapProviderStatusToEndReason, o as getHeader, r as isProviderStatusTerminal } from "./runtime-entry-DhTLZ2uB.js";
5
- import { c as verifyTwilioWebhook, i as readProviderJsonResponseText, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-DoLAoIRF.js";
4
+ import { _ as mapVoiceToPolly, a as normalizeProviderStatus, f as chunkAudio, g as escapeXml, i as mapProviderStatusToEndReason, o as getHeader, r as isProviderStatusTerminal } from "./runtime-entry-DSgyqIwE.js";
5
+ import { c as verifyTwilioWebhook, i as readProviderJsonResponseText, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-BKOgUU1q.js";
6
6
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import crypto from "node:crypto";
8
8
  import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@openclaw/voice-call",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/voice-call",
9
- "version": "2026.7.2-beta.1",
9
+ "version": "2026.7.2-beta.2",
10
10
  "dependencies": {
11
11
  "typebox": "1.3.3",
12
12
  "ws": "8.21.0",
13
13
  "zod": "4.4.3"
14
14
  },
15
15
  "peerDependencies": {
16
- "openclaw": ">=2026.7.2-beta.1"
16
+ "openclaw": ">=2026.7.2-beta.2"
17
17
  },
18
18
  "peerDependenciesMeta": {
19
19
  "openclaw": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/voice-call",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.2",
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.7.2-beta.1"
16
+ "openclaw": ">=2026.7.2-beta.2"
17
17
  },
18
18
  "peerDependenciesMeta": {
19
19
  "openclaw": {
@@ -30,10 +30,10 @@
30
30
  "minHostVersion": ">=2026.4.10"
31
31
  },
32
32
  "compat": {
33
- "pluginApi": ">=2026.7.2-beta.1"
33
+ "pluginApi": ">=2026.7.2-beta.2"
34
34
  },
35
35
  "build": {
36
- "openclawVersion": "2026.7.2-beta.1"
36
+ "openclawVersion": "2026.7.2-beta.2"
37
37
  },
38
38
  "release": {
39
39
  "publishToClawHub": true,