@openclaw/voice-call 2026.6.11 → 2026.7.1-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/{config-BKDAAd8j.js → config-DNtTB7Iw.js} +40 -4
- package/dist/{config-compat-qDCcKTUt.js → config-compat-CCEjHjAJ.js} +1 -1
- package/dist/doctor-contract-api.js +22 -1
- package/dist/{guarded-json-api-BXeBxB7w.js → guarded-json-api-Dnyy7xHB.js} +1 -1
- package/dist/index.js +20 -7
- package/dist/{plivo-CPxvHw8k.js → plivo-sCM3Jvjh.js} +2 -2
- package/dist/{realtime-handler-rYbJUshl.js → realtime-handler-DdViwdCW.js} +4 -3
- package/dist/{response-generator-DBzGujH_.js → response-generator-DOdrErIH.js} +10 -5
- package/dist/{runtime-entry-DIAae7sB.js → runtime-entry-Cwb6vEQf.js} +20 -16
- package/dist/runtime-entry.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/{telnyx-CYS_IihO.js → telnyx-LSKUJimK.js} +1 -1
- package/dist/{twilio-Bn1ta3tQ.js → twilio-GBk6YOP_.js} +2 -2
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
|
@@ -2,7 +2,9 @@ import { TtsConfigSchema } from "./runtime-api.js";
|
|
|
2
2
|
import "./api.js";
|
|
3
3
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, REALTIME_VOICE_AGENT_CONSULT_TOOL_POLICIES } from "openclaw/plugin-sdk/realtime-voice";
|
|
5
|
+
import { normalizeAgentId, parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
5
6
|
import { buildSecretInputSchema, hasConfiguredSecretInput, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
7
|
+
import { canonicalizeMainSessionAlias } from "openclaw/plugin-sdk/session-store-runtime";
|
|
6
8
|
import { z } from "zod";
|
|
7
9
|
//#region extensions/voice-call/src/deep-merge.ts
|
|
8
10
|
const BLOCKED_MERGE_KEYS = new Set([
|
|
@@ -442,6 +444,13 @@ function resolveVoiceCallNumberRouteKey(config, phone) {
|
|
|
442
444
|
if (!normalizedPhone) return;
|
|
443
445
|
return Object.keys(routes).find((routeKey) => normalizePhoneRouteKey(routeKey) === normalizedPhone);
|
|
444
446
|
}
|
|
447
|
+
/** Resolve inbound-only number routing from a persisted call record. */
|
|
448
|
+
function resolveVoiceCallNumberRouteKeyForCall(call) {
|
|
449
|
+
if (call.direction !== "inbound") return;
|
|
450
|
+
const storedRouteKey = call.metadata?.numberRouteKey;
|
|
451
|
+
if (typeof storedRouteKey === "string") return storedRouteKey;
|
|
452
|
+
return call.to;
|
|
453
|
+
}
|
|
445
454
|
function resolveVoiceCallEffectiveConfig(config, phoneOrRouteKey) {
|
|
446
455
|
const numberRouteKey = resolveVoiceCallNumberRouteKey(config, phoneOrRouteKey);
|
|
447
456
|
if (!numberRouteKey) return { config };
|
|
@@ -538,10 +547,37 @@ function normalizeVoiceCallConfig(config) {
|
|
|
538
547
|
}
|
|
539
548
|
function resolveVoiceCallSessionKey(params) {
|
|
540
549
|
const explicit = params.explicitSessionKey?.trim();
|
|
541
|
-
if (explicit) return
|
|
542
|
-
|
|
550
|
+
if (explicit) return resolveVoiceCallAgentSessionKey({
|
|
551
|
+
config: params.config,
|
|
552
|
+
sessionKey: explicit,
|
|
553
|
+
coreSession: params.coreSession
|
|
554
|
+
});
|
|
555
|
+
const prefix = `agent:${normalizeAgentId(params.config.agentId)}:voice`;
|
|
556
|
+
if (params.config.sessionScope === "per-call") return `${prefix}:call:${params.callId}`.toLowerCase();
|
|
543
557
|
const normalizedPhone = params.phone?.replace(/\D/g, "");
|
|
544
|
-
return normalizedPhone ?
|
|
558
|
+
return (normalizedPhone ? `${prefix}:${normalizedPhone}` : `${prefix}:${params.callId}`).toLowerCase();
|
|
559
|
+
}
|
|
560
|
+
/** Resolve persisted or integration-provided keys into the configured agent namespace. */
|
|
561
|
+
function resolveVoiceCallAgentSessionKey(params) {
|
|
562
|
+
const sessionKey = params.sessionKey.trim();
|
|
563
|
+
if (!sessionKey) throw new Error("Voice Call session key cannot be empty");
|
|
564
|
+
const lower = sessionKey.toLowerCase();
|
|
565
|
+
const agentId = normalizeAgentId(params.config.agentId);
|
|
566
|
+
if (lower === "global" || lower === "unknown") return lower;
|
|
567
|
+
const parsedInput = parseAgentSessionKey(sessionKey);
|
|
568
|
+
let normalizedScopedKey;
|
|
569
|
+
if (parsedInput && normalizeAgentId(parsedInput.agentId) === parsedInput.agentId && parsedInput.agentId === agentId) normalizedScopedKey = `agent:${parsedInput.agentId}:${parsedInput.rest}`;
|
|
570
|
+
else {
|
|
571
|
+
const wrappedInput = parseAgentSessionKey(`agent:${agentId}:${sessionKey}`);
|
|
572
|
+
if (!wrappedInput) throw new Error("Voice Call session key could not be normalized");
|
|
573
|
+
normalizedScopedKey = `agent:${agentId}:${wrappedInput.rest}`;
|
|
574
|
+
}
|
|
575
|
+
const canonicalMain = canonicalizeMainSessionAlias({
|
|
576
|
+
cfg: { session: params.coreSession },
|
|
577
|
+
agentId,
|
|
578
|
+
sessionKey: normalizedScopedKey
|
|
579
|
+
});
|
|
580
|
+
return canonicalMain === normalizedScopedKey ? normalizedScopedKey : canonicalMain;
|
|
545
581
|
}
|
|
546
582
|
/**
|
|
547
583
|
* Resolves the configuration by merging environment variables into missing fields.
|
|
@@ -616,4 +652,4 @@ function validateProviderConfig(config) {
|
|
|
616
652
|
};
|
|
617
653
|
}
|
|
618
654
|
//#endregion
|
|
619
|
-
export { resolveVoiceCallEffectiveConfig as a,
|
|
655
|
+
export { resolveVoiceCallEffectiveConfig as a, validateProviderConfig as c, resolveVoiceCallConfig as i, normalizePath as l, normalizeVoiceCallConfig as n, resolveVoiceCallNumberRouteKeyForCall as o, resolveTwilioAuthToken as r, resolveVoiceCallSessionKey as s, VoiceCallConfigSchema as t, deepMergeDefined as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as VoiceCallConfigSchema } from "./config-
|
|
1
|
+
import { t as VoiceCallConfigSchema } from "./config-DNtTB7Iw.js";
|
|
2
2
|
import { asOptionalRecord, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
//#region extensions/voice-call/src/config-compat.ts
|
|
4
4
|
/** Version where legacy voice-call config shape support is removed. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { a as MAX_CALL_RECORD_EVENTS, f as prepareVoiceCallRecordForStorage, i as CALL_RECORD_EVENT_META_MAX_ENTRIES, n as CALL_RECORD_EVENTS_NAMESPACE, o as RAW_CALL_RECORD_CHUNK_BYTES, p as resolveVoiceCallLegacyCallLogPath, r as CALL_RECORD_EVENT_CHUNKS_NAMESPACE, s as buildVoiceCallLegacyJsonlEventKey, t as CALL_RECORD_CHUNK_MAX_ENTRIES, u as parseVoiceCallRecordLine } from "./store-8M2m4Isq.js";
|
|
2
|
+
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
2
3
|
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import fs from "node:fs/promises";
|
|
@@ -24,6 +25,26 @@ function getVoiceCallConfigStore(config) {
|
|
|
24
25
|
}
|
|
25
26
|
return "";
|
|
26
27
|
}
|
|
28
|
+
function asRecord(value) {
|
|
29
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
30
|
+
}
|
|
31
|
+
/** Return Voice Call agents whose templated core session stores need migration. */
|
|
32
|
+
function resolveSessionStoreAgentIds(params) {
|
|
33
|
+
const agentIds = /* @__PURE__ */ new Set();
|
|
34
|
+
for (const pluginId of ["voice-call", "@openclaw/voice-call"]) {
|
|
35
|
+
const entry = params.cfg.plugins?.entries?.[pluginId];
|
|
36
|
+
if (!entry) continue;
|
|
37
|
+
const config = entry.config === void 0 ? {} : asRecord(entry.config);
|
|
38
|
+
if (!config) continue;
|
|
39
|
+
agentIds.add(normalizeAgentId(typeof config.agentId === "string" ? config.agentId : void 0));
|
|
40
|
+
const numbers = asRecord(config.numbers);
|
|
41
|
+
for (const route of Object.values(numbers ?? {})) {
|
|
42
|
+
const agentId = asRecord(route)?.agentId;
|
|
43
|
+
if (typeof agentId === "string") agentIds.add(normalizeAgentId(agentId));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return [...agentIds].toSorted();
|
|
47
|
+
}
|
|
27
48
|
/** Resolve the voice-call store path used by legacy and plugin-state call records. */
|
|
28
49
|
function resolveVoiceCallStorePath(params) {
|
|
29
50
|
const configuredStore = getVoiceCallConfigStore(params.config);
|
|
@@ -220,4 +241,4 @@ const stateMigrations = [{
|
|
|
220
241
|
}
|
|
221
242
|
}];
|
|
222
243
|
//#endregion
|
|
223
|
-
export { stateMigrations };
|
|
244
|
+
export { resolveSessionStoreAgentIds, stateMigrations };
|
|
@@ -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-
|
|
3
|
+
import { a as getHeader } from "./runtime-entry-Cwb6vEQf.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,9 +1,9 @@
|
|
|
1
1
|
import { definePluginEntry, sleep } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
|
-
import {
|
|
4
|
-
import { c as getTailscaleSelfInfo, l as setupTailscaleExposureRoute, o as resolveWebhookExposureStatus, p as resolveUserPath, s as cleanupTailscaleExposureRoute, t as createVoiceCallRuntime } from "./runtime-entry-
|
|
3
|
+
import { c as validateProviderConfig, i as resolveVoiceCallConfig } from "./config-DNtTB7Iw.js";
|
|
4
|
+
import { c as getTailscaleSelfInfo, l as setupTailscaleExposureRoute, o as resolveWebhookExposureStatus, p as resolveUserPath, s as cleanupTailscaleExposureRoute, t as createVoiceCallRuntime } from "./runtime-entry-Cwb6vEQf.js";
|
|
5
5
|
import { c as getCallHistoryFromStore, m as setVoiceCallStateRuntime } from "./store-8M2m4Isq.js";
|
|
6
|
-
import { i as parseVoiceCallPluginConfig, r as normalizeVoiceCallLegacyConfigInput, t as formatVoiceCallLegacyConfigWarnings } from "./config-compat-
|
|
6
|
+
import { i as parseVoiceCallPluginConfig, r as normalizeVoiceCallLegacyConfigInput, t as formatVoiceCallLegacyConfigWarnings } from "./config-compat-CCEjHjAJ.js";
|
|
7
7
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
8
8
|
import { ErrorCodes, callGatewayFromCli, errorShape } from "openclaw/plugin-sdk/gateway-runtime";
|
|
9
9
|
import { MAX_TCP_PORT, MAX_TIMER_TIMEOUT_MS, addTimerTimeoutGraceMs, clampTimerTimeoutMs, parseStrictNonNegativeInteger, resolveTimerTimeoutMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
|
|
@@ -915,6 +915,19 @@ function asParamRecord(params) {
|
|
|
915
915
|
function isCliOnlyProcess() {
|
|
916
916
|
return process.env.OPENCLAW_CLI === "1" && !process.argv.slice(2).includes("gateway");
|
|
917
917
|
}
|
|
918
|
+
function toVoiceCallStatus(call) {
|
|
919
|
+
return {
|
|
920
|
+
callId: call.callId,
|
|
921
|
+
...call.providerCallId !== void 0 ? { providerCallId: call.providerCallId } : {},
|
|
922
|
+
provider: call.provider,
|
|
923
|
+
direction: call.direction,
|
|
924
|
+
state: call.state,
|
|
925
|
+
startedAt: call.startedAt,
|
|
926
|
+
...call.answeredAt !== void 0 ? { answeredAt: call.answeredAt } : {},
|
|
927
|
+
...call.endedAt !== void 0 ? { endedAt: call.endedAt } : {},
|
|
928
|
+
...call.endReason !== void 0 ? { endReason: call.endReason } : {}
|
|
929
|
+
};
|
|
930
|
+
}
|
|
918
931
|
const VOICE_CALL_RUNTIME_KEY = Symbol.for("openclaw.voice-call.runtime");
|
|
919
932
|
const VOICE_CALL_RUNTIME_PROMISE_KEY = Symbol.for("openclaw.voice-call.runtimePromise");
|
|
920
933
|
const VOICE_CALL_RUNTIME_STOP_PROMISE_KEY = Symbol.for("openclaw.voice-call.runtimeStopPromise");
|
|
@@ -1183,7 +1196,7 @@ var voice_call_default = definePluginEntry({
|
|
|
1183
1196
|
if (!raw) {
|
|
1184
1197
|
respond(true, {
|
|
1185
1198
|
found: true,
|
|
1186
|
-
calls: rt.manager.getActiveCalls()
|
|
1199
|
+
calls: rt.manager.getActiveCalls().map(toVoiceCallStatus)
|
|
1187
1200
|
});
|
|
1188
1201
|
return;
|
|
1189
1202
|
}
|
|
@@ -1194,7 +1207,7 @@ var voice_call_default = definePluginEntry({
|
|
|
1194
1207
|
}
|
|
1195
1208
|
respond(true, {
|
|
1196
1209
|
found: true,
|
|
1197
|
-
call
|
|
1210
|
+
call: toVoiceCallStatus(call)
|
|
1198
1211
|
});
|
|
1199
1212
|
} catch (err) {
|
|
1200
1213
|
sendError(respond, err);
|
|
@@ -1299,7 +1312,7 @@ var voice_call_default = definePluginEntry({
|
|
|
1299
1312
|
const call = rt.manager.getCall(callId) || rt.manager.getCallByProviderCallId(callId);
|
|
1300
1313
|
return json(call ? {
|
|
1301
1314
|
found: true,
|
|
1302
|
-
call
|
|
1315
|
+
call: toVoiceCallStatus(call)
|
|
1303
1316
|
} : { found: false });
|
|
1304
1317
|
}
|
|
1305
1318
|
}
|
|
@@ -1309,7 +1322,7 @@ var voice_call_default = definePluginEntry({
|
|
|
1309
1322
|
const call = rt.manager.getCall(sid) || rt.manager.getCallByProviderCallId(sid);
|
|
1310
1323
|
return json(call ? {
|
|
1311
1324
|
found: true,
|
|
1312
|
-
call
|
|
1325
|
+
call: toVoiceCallStatus(call)
|
|
1313
1326
|
} : { found: false });
|
|
1314
1327
|
}
|
|
1315
1328
|
const to = normalizeOptionalString(rawParams.to) ?? rt.config.toNumber;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as getHeader, m as escapeXml } from "./runtime-entry-
|
|
2
|
-
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { a as getHeader, m as escapeXml } from "./runtime-entry-Cwb6vEQf.js";
|
|
2
|
+
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Dnyy7xHB.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 {
|
|
1
|
+
import { l as normalizePath } from "./config-DNtTB7Iw.js";
|
|
2
2
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
3
3
|
import { isFutureDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
4
4
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
@@ -6,6 +6,7 @@ import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, buildRealtimeVoiceAgentConsultW
|
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
import "node:http";
|
|
8
8
|
import WebSocket, { WebSocketServer } from "ws";
|
|
9
|
+
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
9
10
|
//#region extensions/voice-call/src/webhook/realtime-audio-pacer.ts
|
|
10
11
|
const TELEPHONY_SAMPLE_RATE = 8e3;
|
|
11
12
|
const TELEPHONY_CHUNK_BYTES = 160;
|
|
@@ -379,7 +380,7 @@ function appendTranscriptText(base, fragment) {
|
|
|
379
380
|
}
|
|
380
381
|
function limitPartialUserTranscript(text) {
|
|
381
382
|
if (text.length <= MAX_PARTIAL_USER_TRANSCRIPT_CHARS) return text;
|
|
382
|
-
const tail = text
|
|
383
|
+
const tail = sliceUtf16Safe(text, -1200);
|
|
383
384
|
return tail.replace(/^\S+\s+/, "").trimStart() || tail.trimStart();
|
|
384
385
|
}
|
|
385
386
|
function withFallbackConsultQuestion(args, fallback) {
|
|
@@ -412,7 +413,7 @@ function buildForcedConsultSpeechPrompt(result) {
|
|
|
412
413
|
"Internal OpenClaw consult result is ready.",
|
|
413
414
|
"Do not call tools for this internal result.",
|
|
414
415
|
"Speak the following answer to the caller now, briefly and naturally:",
|
|
415
|
-
trimmed.length <= FORCED_CONSULT_RESULT_MAX_CHARS ? trimmed : `${trimmed
|
|
416
|
+
trimmed.length <= FORCED_CONSULT_RESULT_MAX_CHARS ? trimmed : `${truncateUtf16Safe(trimmed, FORCED_CONSULT_RESULT_MAX_CHARS - 16).trimEnd()} [truncated]`
|
|
416
417
|
].join("\n");
|
|
417
418
|
}
|
|
418
419
|
function appendRecentTalkEventMetadata(call, event) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { f as resolveVoiceResponseModel } from "./runtime-entry-
|
|
1
|
+
import { s as resolveVoiceCallSessionKey } from "./config-DNtTB7Iw.js";
|
|
2
|
+
import { f as resolveVoiceResponseModel } from "./runtime-entry-Cwb6vEQf.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";
|
|
@@ -106,7 +106,8 @@ async function generateVoiceResponse(params) {
|
|
|
106
106
|
config: voiceConfig,
|
|
107
107
|
callId,
|
|
108
108
|
phone: from,
|
|
109
|
-
explicitSessionKey: sessionKey
|
|
109
|
+
explicitSessionKey: sessionKey,
|
|
110
|
+
coreSession: coreConfig.session
|
|
110
111
|
});
|
|
111
112
|
const agentId = voiceConfig.agentId ?? "main";
|
|
112
113
|
const toolsAllow = resolveVoiceAgentToolsAllow(cfg, agentId);
|
|
@@ -154,7 +155,6 @@ async function generateVoiceResponse(params) {
|
|
|
154
155
|
error: "Voice response session could not be initialized"
|
|
155
156
|
};
|
|
156
157
|
const sessionId = sessionEntry.sessionId;
|
|
157
|
-
const sessionFile = agentRuntime.session.resolveSessionFilePath(sessionId, sessionEntry, { agentId });
|
|
158
158
|
const thinkLevel = agentRuntime.resolveThinkingDefault({
|
|
159
159
|
cfg,
|
|
160
160
|
provider,
|
|
@@ -171,10 +171,15 @@ async function generateVoiceResponse(params) {
|
|
|
171
171
|
const result = await agentRuntime.runEmbeddedAgent({
|
|
172
172
|
sessionId,
|
|
173
173
|
sessionKey: resolvedSessionKey,
|
|
174
|
+
sessionTarget: {
|
|
175
|
+
agentId,
|
|
176
|
+
sessionId,
|
|
177
|
+
sessionKey: resolvedSessionKey,
|
|
178
|
+
storePath
|
|
179
|
+
},
|
|
174
180
|
sandboxSessionKey: resolveVoiceSandboxSessionKey(agentId, resolvedSessionKey),
|
|
175
181
|
agentId,
|
|
176
182
|
messageProvider: "voice",
|
|
177
|
-
sessionFile,
|
|
178
183
|
workspaceDir,
|
|
179
184
|
config: cfg,
|
|
180
185
|
prompt: userMessage,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isBlockedHostnameOrIp, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
|
-
import { a as resolveVoiceCallEffectiveConfig,
|
|
3
|
+
import { a as resolveVoiceCallEffectiveConfig, c as validateProviderConfig, i as resolveVoiceCallConfig, n as normalizeVoiceCallConfig, o as resolveVoiceCallNumberRouteKeyForCall, r as resolveTwilioAuthToken, s as resolveVoiceCallSessionKey, u as deepMergeDefined } from "./config-DNtTB7Iw.js";
|
|
4
4
|
import { c as getCallHistoryFromStore, d as persistCallRecord, h as TerminalStates, l as loadActiveCallsFromStore, m as setVoiceCallStateRuntime } from "./store-8M2m4Isq.js";
|
|
5
5
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
6
6
|
import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
|
|
@@ -356,7 +356,8 @@ async function initiateCall(ctx, to, sessionKey, options) {
|
|
|
356
356
|
config: ctx.config,
|
|
357
357
|
callId,
|
|
358
358
|
phone: to,
|
|
359
|
-
explicitSessionKey: sessionKey
|
|
359
|
+
explicitSessionKey: sessionKey,
|
|
360
|
+
coreSession: ctx.coreSession
|
|
360
361
|
}),
|
|
361
362
|
startedAt: Date.now(),
|
|
362
363
|
transcript: [],
|
|
@@ -438,7 +439,7 @@ async function speak(ctx, callId, text) {
|
|
|
438
439
|
});
|
|
439
440
|
transitionState(call, "speaking");
|
|
440
441
|
persistCallRecord(ctx.storePath, call);
|
|
441
|
-
const numberRouteKey =
|
|
442
|
+
const numberRouteKey = resolveVoiceCallNumberRouteKeyForCall(call);
|
|
442
443
|
const voice = resolvePreferredTtsVoice(resolveVoiceCallEffectiveConfig(ctx.config, numberRouteKey).config);
|
|
443
444
|
await provider.playTts({
|
|
444
445
|
callId,
|
|
@@ -910,7 +911,7 @@ function resolveDefaultStoreBase(config, storePath) {
|
|
|
910
911
|
* Manages voice calls: state ownership and delegation to manager helper modules.
|
|
911
912
|
*/
|
|
912
913
|
var CallManager = class {
|
|
913
|
-
constructor(config, storePath) {
|
|
914
|
+
constructor(config, storePath, coreSession) {
|
|
914
915
|
this.activeCalls = /* @__PURE__ */ new Map();
|
|
915
916
|
this.providerCallIdMap = /* @__PURE__ */ new Map();
|
|
916
917
|
this.processedEventIds = /* @__PURE__ */ new Set();
|
|
@@ -922,6 +923,7 @@ var CallManager = class {
|
|
|
922
923
|
this.maxDurationTimers = /* @__PURE__ */ new Map();
|
|
923
924
|
this.initialMessageInFlight = /* @__PURE__ */ new Set();
|
|
924
925
|
this.config = config;
|
|
926
|
+
this.coreSession = coreSession;
|
|
925
927
|
this.storePath = resolveDefaultStoreBase(config, storePath);
|
|
926
928
|
}
|
|
927
929
|
/**
|
|
@@ -1085,6 +1087,7 @@ var CallManager = class {
|
|
|
1085
1087
|
rejectedProviderCallIds: this.rejectedProviderCallIds,
|
|
1086
1088
|
provider: this.provider,
|
|
1087
1089
|
config: this.config,
|
|
1090
|
+
coreSession: this.coreSession,
|
|
1088
1091
|
storePath: this.storePath,
|
|
1089
1092
|
webhookUrl: this.webhookUrl,
|
|
1090
1093
|
activeTurnCalls: this.activeTurnCalls,
|
|
@@ -2510,7 +2513,7 @@ function loadRealtimeTranscriptionRuntime() {
|
|
|
2510
2513
|
return realtimeTranscriptionRuntimePromise;
|
|
2511
2514
|
}
|
|
2512
2515
|
function loadResponseGeneratorModule() {
|
|
2513
|
-
responseGeneratorModulePromise ??= import("./response-generator-
|
|
2516
|
+
responseGeneratorModulePromise ??= import("./response-generator-DOdrErIH.js");
|
|
2514
2517
|
return responseGeneratorModulePromise;
|
|
2515
2518
|
}
|
|
2516
2519
|
function sanitizeTranscriptForLog(value) {
|
|
@@ -3156,7 +3159,7 @@ var VoiceCallWebhookServer = class {
|
|
|
3156
3159
|
}
|
|
3157
3160
|
try {
|
|
3158
3161
|
const { generateVoiceResponse } = await loadResponseGeneratorModule();
|
|
3159
|
-
const numberRouteKey =
|
|
3162
|
+
const numberRouteKey = resolveVoiceCallNumberRouteKeyForCall(call);
|
|
3160
3163
|
const effectiveConfig = resolveVoiceCallEffectiveConfig(this.config, numberRouteKey).config;
|
|
3161
3164
|
const result = await generateVoiceResponse({
|
|
3162
3165
|
voiceConfig: effectiveConfig,
|
|
@@ -3198,15 +3201,15 @@ let mockProviderPromise;
|
|
|
3198
3201
|
let realtimeVoiceRuntimePromise;
|
|
3199
3202
|
let realtimeHandlerPromise;
|
|
3200
3203
|
function loadTelnyxProvider() {
|
|
3201
|
-
telnyxProviderPromise ??= import("./telnyx-
|
|
3204
|
+
telnyxProviderPromise ??= import("./telnyx-LSKUJimK.js");
|
|
3202
3205
|
return telnyxProviderPromise;
|
|
3203
3206
|
}
|
|
3204
3207
|
function loadTwilioProvider() {
|
|
3205
|
-
twilioProviderPromise ??= import("./twilio-
|
|
3208
|
+
twilioProviderPromise ??= import("./twilio-GBk6YOP_.js");
|
|
3206
3209
|
return twilioProviderPromise;
|
|
3207
3210
|
}
|
|
3208
3211
|
function loadPlivoProvider() {
|
|
3209
|
-
plivoProviderPromise ??= import("./plivo-
|
|
3212
|
+
plivoProviderPromise ??= import("./plivo-sCM3Jvjh.js");
|
|
3210
3213
|
return plivoProviderPromise;
|
|
3211
3214
|
}
|
|
3212
3215
|
function loadMockProvider() {
|
|
@@ -3218,16 +3221,16 @@ function loadRealtimeVoiceRuntime() {
|
|
|
3218
3221
|
return realtimeVoiceRuntimePromise;
|
|
3219
3222
|
}
|
|
3220
3223
|
function loadRealtimeHandler() {
|
|
3221
|
-
realtimeHandlerPromise ??= import("./realtime-handler-
|
|
3224
|
+
realtimeHandlerPromise ??= import("./realtime-handler-DdViwdCW.js");
|
|
3222
3225
|
return realtimeHandlerPromise;
|
|
3223
3226
|
}
|
|
3224
3227
|
function resolveVoiceCallConsultSessionKey(call) {
|
|
3225
|
-
if (call.sessionKey) return call.sessionKey;
|
|
3226
|
-
const phone = call.direction === "outbound" ? call.to : call.from;
|
|
3227
3228
|
return resolveVoiceCallSessionKey({
|
|
3228
3229
|
config: call.config,
|
|
3229
3230
|
callId: call.callId,
|
|
3230
|
-
phone
|
|
3231
|
+
phone: call.direction === "outbound" ? call.to : call.from,
|
|
3232
|
+
explicitSessionKey: call.sessionKey,
|
|
3233
|
+
coreSession: call.coreSession
|
|
3231
3234
|
});
|
|
3232
3235
|
}
|
|
3233
3236
|
function mapVoiceCallConsultTranscript(call, context) {
|
|
@@ -3339,7 +3342,7 @@ async function createVoiceCallRuntime(params) {
|
|
|
3339
3342
|
if (!validation.valid) throw new Error(`Invalid voice-call config: ${validation.errors.join("; ")}`);
|
|
3340
3343
|
const provider = await resolveProvider(config);
|
|
3341
3344
|
if (stateRuntime) setVoiceCallStateRuntime({ state: stateRuntime });
|
|
3342
|
-
const manager = new CallManager(config);
|
|
3345
|
+
const manager = new CallManager(config, void 0, cfg.session);
|
|
3343
3346
|
const realtimeProvider = config.realtime.enabled ? await resolveRealtimeProvider({
|
|
3344
3347
|
config,
|
|
3345
3348
|
fullConfig: cfg
|
|
@@ -3361,11 +3364,12 @@ async function createVoiceCallRuntime(params) {
|
|
|
3361
3364
|
if (config.realtime.toolPolicy !== "none") realtimeHandler.registerToolHandler(REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, async (args, callId, handlerContext) => {
|
|
3362
3365
|
const call = manager.getCall(callId);
|
|
3363
3366
|
if (!call) return { error: `Call "${callId}" not found` };
|
|
3364
|
-
const effectiveConfig = resolveVoiceCallEffectiveConfig(config,
|
|
3367
|
+
const effectiveConfig = resolveVoiceCallEffectiveConfig(config, resolveVoiceCallNumberRouteKeyForCall(call)).config;
|
|
3365
3368
|
const agentId = effectiveConfig.agentId ?? "main";
|
|
3366
3369
|
const sessionKey = resolveVoiceCallConsultSessionKey({
|
|
3367
3370
|
...call,
|
|
3368
|
-
config: effectiveConfig
|
|
3371
|
+
config: effectiveConfig,
|
|
3372
|
+
coreSession: cfg.session
|
|
3369
3373
|
});
|
|
3370
3374
|
const requesterSessionKey = typeof call.metadata?.requesterSessionKey === "string" ? call.metadata.requesterSessionKey : void 0;
|
|
3371
3375
|
const fastContext = await resolveRealtimeFastContextConsult({
|
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-Cwb6vEQf.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-CCEjHjAJ.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 { s as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { s as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Dnyy7xHB.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-
|
|
4
|
-
import { c as verifyTwilioWebhook, i as readProviderJsonResponseText, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
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-Cwb6vEQf.js";
|
|
4
|
+
import { c as verifyTwilioWebhook, i as readProviderJsonResponseText, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-Dnyy7xHB.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";
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/voice-call",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.7.1-beta.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/voice-call",
|
|
9
|
-
"version": "2026.
|
|
9
|
+
"version": "2026.7.1-beta.1",
|
|
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.
|
|
17
|
+
"openclaw": ">=2026.7.1-beta.1"
|
|
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.
|
|
3
|
+
"version": "2026.7.1-beta.1",
|
|
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.
|
|
17
|
+
"openclaw": ">=2026.7.1-beta.1"
|
|
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.
|
|
34
|
+
"pluginApi": ">=2026.7.1-beta.1"
|
|
35
35
|
},
|
|
36
36
|
"build": {
|
|
37
|
-
"openclawVersion": "2026.
|
|
37
|
+
"openclawVersion": "2026.7.1-beta.1"
|
|
38
38
|
},
|
|
39
39
|
"release": {
|
|
40
40
|
"publishToClawHub": true,
|