@openclaw/voice-call 2026.7.1-beta.6 → 2026.7.2-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/README.md +1 -2
- package/dist/doctor-contract-api.js +27 -10
- package/dist/{guarded-json-api-CLVDU_h1.js → guarded-json-api-DoLAoIRF.js} +32 -41
- package/dist/index.js +9 -15
- package/dist/{plivo-D5wI4-pi.js → plivo-BICQA_yK.js} +2 -2
- package/dist/{realtime-handler-Bz-MNWtD.js → realtime-handler-DJk-eYyf.js} +31 -20
- package/dist/{response-generator-D3YO-WtN.js → response-generator-hmAdGp5h.js} +20 -4
- package/dist/{runtime-entry-DwMgbq2p.js → runtime-entry-DhTLZ2uB.js} +811 -263
- package/dist/runtime-entry.js +1 -1
- package/dist/setup-api.js +86 -2
- package/dist/{store-DtewuuOb.js → store-C1pl3avP.js} +2 -2
- package/dist/{telnyx-DksS6q0n.js → telnyx-B9tF5jeJ.js} +1 -1
- package/dist/{twilio-BYcsdUkj.js → twilio-U_myvowz.js} +7 -10
- package/dist/twilio-region-4fkgz3UG.js +25 -0
- package/npm-shrinkwrap.json +3 -13
- package/openclaw.plugin.json +1 -0
- package/package.json +4 -6
- package/dist/config-CDSeuGp3.js +0 -674
- package/dist/config-compat-D8fcjOHp.js +0 -156
- package/node_modules/commander/LICENSE +0 -22
- package/node_modules/commander/Readme.md +0 -1172
- package/node_modules/commander/index.js +0 -21
- package/node_modules/commander/lib/argument.js +0 -147
- package/node_modules/commander/lib/command.js +0 -2790
- package/node_modules/commander/lib/error.js +0 -36
- package/node_modules/commander/lib/help.js +0 -731
- package/node_modules/commander/lib/option.js +0 -377
- package/node_modules/commander/lib/suggestSimilar.js +0 -99
- package/node_modules/commander/package-support.json +0 -19
- package/node_modules/commander/package.json +0 -64
- package/node_modules/commander/typings/index.d.ts +0 -1113
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-DhTLZ2uB.js";
|
|
2
2
|
export { createVoiceCallRuntime };
|
package/dist/setup-api.js
CHANGED
|
@@ -1,6 +1,90 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
1
|
+
import { asOptionalRecord, isRecord, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
2
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
|
+
//#region extensions/voice-call/src/config-migration.ts
|
|
4
|
+
const asObject = asOptionalRecord;
|
|
5
|
+
const getString = readStringField;
|
|
6
|
+
/** Read finite numeric config values. */
|
|
7
|
+
function getNumber(obj, key) {
|
|
8
|
+
const value = obj?.[key];
|
|
9
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
10
|
+
}
|
|
11
|
+
/** Merge legacy provider-specific values into the canonical providers map. */
|
|
12
|
+
function mergeProviderConfig(providersValue, providerId, compatValues) {
|
|
13
|
+
if (Object.keys(compatValues).length === 0) return asObject(providersValue);
|
|
14
|
+
const providers = asObject(providersValue) ?? {};
|
|
15
|
+
const existing = asObject(providers[providerId]) ?? {};
|
|
16
|
+
return {
|
|
17
|
+
...providers,
|
|
18
|
+
[providerId]: {
|
|
19
|
+
...existing,
|
|
20
|
+
...compatValues
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Migrate legacy voice-call config input to the current canonical shape. */
|
|
25
|
+
function migrateVoiceCallLegacyConfigInput(params) {
|
|
26
|
+
const raw = asObject(params.value) ?? {};
|
|
27
|
+
const realtime = asObject(raw.realtime);
|
|
28
|
+
const realtimeAgentContext = asObject(realtime?.agentContext);
|
|
29
|
+
const twilio = asObject(raw.twilio);
|
|
30
|
+
const streaming = asObject(raw.streaming);
|
|
31
|
+
const configPathPrefix = params.configPathPrefix ?? "plugins.entries.voice-call.config";
|
|
32
|
+
const legacyStreamingOpenAICompat = {};
|
|
33
|
+
const streamingOpenAIApiKey = getString(streaming, "openaiApiKey");
|
|
34
|
+
if (streamingOpenAIApiKey) legacyStreamingOpenAICompat.apiKey = streamingOpenAIApiKey;
|
|
35
|
+
const streamingSttModel = getString(streaming, "sttModel");
|
|
36
|
+
if (streamingSttModel) legacyStreamingOpenAICompat.model = streamingSttModel;
|
|
37
|
+
const streamingSilenceDurationMs = getNumber(streaming, "silenceDurationMs");
|
|
38
|
+
if (streamingSilenceDurationMs !== void 0) legacyStreamingOpenAICompat.silenceDurationMs = streamingSilenceDurationMs;
|
|
39
|
+
const streamingVadThreshold = getNumber(streaming, "vadThreshold");
|
|
40
|
+
if (streamingVadThreshold !== void 0) legacyStreamingOpenAICompat.vadThreshold = streamingVadThreshold;
|
|
41
|
+
const streamingProvider = getString(streaming, "provider");
|
|
42
|
+
const legacyStreamingProvider = getString(streaming, "sttProvider");
|
|
43
|
+
const normalizedStreaming = streaming ? {
|
|
44
|
+
...streaming,
|
|
45
|
+
provider: streamingProvider ?? legacyStreamingProvider,
|
|
46
|
+
providers: mergeProviderConfig(streaming.providers, "openai", legacyStreamingOpenAICompat)
|
|
47
|
+
} : void 0;
|
|
48
|
+
if (normalizedStreaming) {
|
|
49
|
+
delete normalizedStreaming.sttProvider;
|
|
50
|
+
delete normalizedStreaming.openaiApiKey;
|
|
51
|
+
delete normalizedStreaming.sttModel;
|
|
52
|
+
delete normalizedStreaming.silenceDurationMs;
|
|
53
|
+
delete normalizedStreaming.vadThreshold;
|
|
54
|
+
}
|
|
55
|
+
const normalizedTwilio = twilio ? { ...twilio } : void 0;
|
|
56
|
+
if (normalizedTwilio) delete normalizedTwilio.from;
|
|
57
|
+
const normalizedRealtimeAgentContext = realtimeAgentContext ? { ...realtimeAgentContext } : void 0;
|
|
58
|
+
if (normalizedRealtimeAgentContext) delete normalizedRealtimeAgentContext.includeSystemPrompt;
|
|
59
|
+
const normalizedRealtime = realtime ? {
|
|
60
|
+
...realtime,
|
|
61
|
+
agentContext: normalizedRealtimeAgentContext ?? realtime.agentContext
|
|
62
|
+
} : void 0;
|
|
63
|
+
const config = {
|
|
64
|
+
...raw,
|
|
65
|
+
provider: raw.provider === "log" ? "mock" : raw.provider,
|
|
66
|
+
fromNumber: raw.fromNumber ?? (typeof twilio?.from === "string" ? twilio.from : void 0),
|
|
67
|
+
twilio: normalizedTwilio,
|
|
68
|
+
streaming: normalizedStreaming,
|
|
69
|
+
realtime: normalizedRealtime
|
|
70
|
+
};
|
|
71
|
+
const changes = [];
|
|
72
|
+
if (raw.provider === "log") changes.push(`Moved ${configPathPrefix}.provider "log" → "mock".`);
|
|
73
|
+
if (typeof twilio?.from === "string" && typeof raw.fromNumber !== "string") changes.push(`Moved ${configPathPrefix}.twilio.from → ${configPathPrefix}.fromNumber.`);
|
|
74
|
+
if (typeof streaming?.sttProvider === "string") changes.push(`Moved ${configPathPrefix}.streaming.sttProvider → ${configPathPrefix}.streaming.provider.`);
|
|
75
|
+
if (typeof streaming?.openaiApiKey === "string") changes.push(`Moved ${configPathPrefix}.streaming.openaiApiKey → ${configPathPrefix}.streaming.providers.openai.apiKey.`);
|
|
76
|
+
if (typeof streaming?.sttModel === "string") changes.push(`Moved ${configPathPrefix}.streaming.sttModel → ${configPathPrefix}.streaming.providers.openai.model.`);
|
|
77
|
+
if (getNumber(streaming, "silenceDurationMs") !== void 0) changes.push(`Moved ${configPathPrefix}.streaming.silenceDurationMs → ${configPathPrefix}.streaming.providers.openai.silenceDurationMs.`);
|
|
78
|
+
else if (typeof streaming?.silenceDurationMs === "number") changes.push(`Removed invalid ${configPathPrefix}.streaming.silenceDurationMs.`);
|
|
79
|
+
if (getNumber(streaming, "vadThreshold") !== void 0) changes.push(`Moved ${configPathPrefix}.streaming.vadThreshold → ${configPathPrefix}.streaming.providers.openai.vadThreshold.`);
|
|
80
|
+
else if (typeof streaming?.vadThreshold === "number") changes.push(`Removed invalid ${configPathPrefix}.streaming.vadThreshold.`);
|
|
81
|
+
if (realtimeAgentContext && Object.hasOwn(realtimeAgentContext, "includeSystemPrompt")) changes.push(`Removed ${configPathPrefix}.realtime.agentContext.includeSystemPrompt.`);
|
|
82
|
+
return {
|
|
83
|
+
config,
|
|
84
|
+
changes
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
4
88
|
//#region extensions/voice-call/setup-api.ts
|
|
5
89
|
/** Migrate voice-call plugin config inside the full OpenClaw config object. */
|
|
6
90
|
function migrateVoiceCallPluginConfig(config) {
|
|
@@ -203,8 +203,8 @@ function buildNewEventKey(order) {
|
|
|
203
203
|
}
|
|
204
204
|
/** Recover the sequence segment from newer event keys. */
|
|
205
205
|
function parseEventKeySequence(key) {
|
|
206
|
-
const
|
|
207
|
-
return
|
|
206
|
+
const sequence = /^event:[^:]+:(\d+):/.exec(key)?.[1];
|
|
207
|
+
return sequence ? Number.parseInt(sequence, 10) : 0;
|
|
208
208
|
}
|
|
209
209
|
/** Parse a stored call record line from v2 envelope or legacy raw-call JSON. */
|
|
210
210
|
function parseVoiceCallRecordLine(line, sequence = 0) {
|
|
@@ -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-DoLAoIRF.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
|
-
import {
|
|
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-
|
|
5
|
-
import { c as verifyTwilioWebhook, i as readProviderJsonResponseText, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
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";
|
|
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";
|
|
@@ -132,10 +132,7 @@ function verifyTwilioProviderWebhook(params) {
|
|
|
132
132
|
trustedProxyIPs: params.options.webhookSecurity?.trustedProxyIPs,
|
|
133
133
|
remoteIP: params.ctx.remoteAddress
|
|
134
134
|
});
|
|
135
|
-
if (!result.ok) {
|
|
136
|
-
console.warn(`[twilio] Webhook verification failed: ${result.reason}`);
|
|
137
|
-
if (result.verificationUrl) console.warn(`[twilio] Verification URL: ${result.verificationUrl}`);
|
|
138
|
-
}
|
|
135
|
+
if (!result.ok) console.warn(`[twilio] Webhook verification failed: ${result.reason}`);
|
|
139
136
|
return {
|
|
140
137
|
ok: result.ok,
|
|
141
138
|
reason: result.reason,
|
|
@@ -181,9 +178,9 @@ var TwilioProvider = class TwilioProvider {
|
|
|
181
178
|
deleteStoredTwimlForProviderCall(providerCallId) {
|
|
182
179
|
const webhookUrl = this.callWebhookUrls.get(providerCallId);
|
|
183
180
|
if (!webhookUrl) return;
|
|
184
|
-
const
|
|
185
|
-
if (!
|
|
186
|
-
this.deleteStoredTwiml(
|
|
181
|
+
const callId = webhookUrl.match(/callId=([^&]+)/)?.[1];
|
|
182
|
+
if (!callId) return;
|
|
183
|
+
this.deleteStoredTwiml(callId);
|
|
187
184
|
this.streamAuthTokens.delete(providerCallId);
|
|
188
185
|
}
|
|
189
186
|
constructor(config, options = {}) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region extensions/voice-call/src/providers/twilio-region.ts
|
|
2
|
+
const TWILIO_REGIONS = [
|
|
3
|
+
"us1",
|
|
4
|
+
"ie1",
|
|
5
|
+
"au1"
|
|
6
|
+
];
|
|
7
|
+
const TWILIO_API_HOSTNAME_BY_REGION = {
|
|
8
|
+
us1: "api.twilio.com",
|
|
9
|
+
ie1: "api.dublin.ie1.twilio.com",
|
|
10
|
+
au1: "api.sydney.au1.twilio.com"
|
|
11
|
+
};
|
|
12
|
+
const TWILIO_API_HOSTNAMES = new Set(Object.values(TWILIO_API_HOSTNAME_BY_REGION));
|
|
13
|
+
function resolveTwilioApiHostname(region) {
|
|
14
|
+
return TWILIO_API_HOSTNAME_BY_REGION[region ?? "us1"];
|
|
15
|
+
}
|
|
16
|
+
function resolveTwilioApiBaseUrl(params) {
|
|
17
|
+
return `https://${resolveTwilioApiHostname(params.region)}/2010-04-01/Accounts/${params.accountSid}`;
|
|
18
|
+
}
|
|
19
|
+
function requireSupportedTwilioApiHostname(baseUrl) {
|
|
20
|
+
const hostname = new URL(baseUrl).hostname;
|
|
21
|
+
if (!TWILIO_API_HOSTNAMES.has(hostname)) throw new Error(`Unsupported Twilio API hostname: ${hostname}`);
|
|
22
|
+
return hostname;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { requireSupportedTwilioApiHostname as n, resolveTwilioApiBaseUrl as r, TWILIO_REGIONS as t };
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/voice-call",
|
|
3
|
-
"version": "2026.7.
|
|
3
|
+
"version": "2026.7.2-beta.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/voice-call",
|
|
9
|
-
"version": "2026.7.
|
|
9
|
+
"version": "2026.7.2-beta.1",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"commander": "15.0.0",
|
|
12
11
|
"typebox": "1.3.3",
|
|
13
12
|
"ws": "8.21.0",
|
|
14
13
|
"zod": "4.4.3"
|
|
15
14
|
},
|
|
16
15
|
"peerDependencies": {
|
|
17
|
-
"openclaw": ">=2026.7.
|
|
16
|
+
"openclaw": ">=2026.7.2-beta.1"
|
|
18
17
|
},
|
|
19
18
|
"peerDependenciesMeta": {
|
|
20
19
|
"openclaw": {
|
|
@@ -22,15 +21,6 @@
|
|
|
22
21
|
}
|
|
23
22
|
}
|
|
24
23
|
},
|
|
25
|
-
"node_modules/commander": {
|
|
26
|
-
"version": "15.0.0",
|
|
27
|
-
"resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz",
|
|
28
|
-
"integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==",
|
|
29
|
-
"license": "MIT",
|
|
30
|
-
"engines": {
|
|
31
|
-
"node": ">=22.12.0"
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
24
|
"node_modules/typebox": {
|
|
35
25
|
"version": "1.3.3",
|
|
36
26
|
"resolved": "https://registry.npmjs.org/typebox/-/typebox-1.3.3.tgz",
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/voice-call",
|
|
3
|
-
"version": "2026.7.
|
|
3
|
+
"version": "2026.7.2-beta.1",
|
|
4
4
|
"description": "OpenClaw voice-call plugin for Twilio, Telnyx, and Plivo phone calls.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,13 +8,12 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"commander": "15.0.0",
|
|
12
11
|
"typebox": "1.3.3",
|
|
13
12
|
"ws": "8.21.0",
|
|
14
13
|
"zod": "4.4.3"
|
|
15
14
|
},
|
|
16
15
|
"peerDependencies": {
|
|
17
|
-
"openclaw": ">=2026.7.
|
|
16
|
+
"openclaw": ">=2026.7.2-beta.1"
|
|
18
17
|
},
|
|
19
18
|
"peerDependenciesMeta": {
|
|
20
19
|
"openclaw": {
|
|
@@ -31,10 +30,10 @@
|
|
|
31
30
|
"minHostVersion": ">=2026.4.10"
|
|
32
31
|
},
|
|
33
32
|
"compat": {
|
|
34
|
-
"pluginApi": ">=2026.7.
|
|
33
|
+
"pluginApi": ">=2026.7.2-beta.1"
|
|
35
34
|
},
|
|
36
35
|
"build": {
|
|
37
|
-
"openclawVersion": "2026.7.
|
|
36
|
+
"openclawVersion": "2026.7.2-beta.1"
|
|
38
37
|
},
|
|
39
38
|
"release": {
|
|
40
39
|
"publishToClawHub": true,
|
|
@@ -52,7 +51,6 @@
|
|
|
52
51
|
"skills/**"
|
|
53
52
|
],
|
|
54
53
|
"bundledDependencies": [
|
|
55
|
-
"commander",
|
|
56
54
|
"typebox",
|
|
57
55
|
"ws",
|
|
58
56
|
"zod"
|