@openclaw/voice-call 2026.9.1-beta.1 → 2026.9.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 -1
- package/dist/api.js +2 -2
- package/dist/cli-DNq2qUU0.js +630 -0
- package/dist/config-DQwvsxeV.js +697 -0
- package/dist/doctor-contract-api.js +9 -6
- package/dist/{guarded-json-api-BmMfqKzQ.js → guarded-json-api-9je4i7qf.js} +10 -7
- package/dist/index.js +18 -582
- package/dist/{mock-Dv7KxYGt.js → mock-C57qj18W.js} +1 -1
- package/dist/{plivo-CNPyQgvw.js → plivo-BfKoYCMW.js} +2 -2
- package/dist/{realtime-handler-DYTBiNVr.js → realtime-handler-BYWqpZ6N.js} +67 -45
- package/dist/{response-generator-BCm6S1G6.js → response-generator-C0577tL-.js} +3 -3
- package/dist/runtime-api.js +2 -2
- package/dist/{runtime-entry-ptAKgGER.js → runtime-entry-gE2Yd4V8.js} +138 -766
- package/dist/runtime-entry.js +1 -1
- package/dist/setup-api.js +58 -38
- package/dist/{store-path-51_oC_xn.js → store-path-C_z9zKnA.js} +11 -21
- package/dist/{telnyx-DWpKHVeV.js → telnyx-rcjslHOP.js} +1 -1
- package/dist/{twilio-DUIVX0Eb.js → twilio-B100ALoj.js} +5 -4
- package/dist/{webhook-replay-FQrEGVSM.js → webhook-replay-CCQSoBNF.js} +1 -1
- package/node_modules/typebox/build/format/email.mjs +1 -1
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/node_modules/typebox/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +8 -6
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-gE2Yd4V8.js";
|
|
2
2
|
export { createVoiceCallRuntime };
|
package/dist/setup-api.js
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
import { asFiniteNumber, asOptionalRecord, isRecord, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
2
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
3
|
//#region extensions/voice-call/src/config-migration.ts
|
|
4
|
-
/** Merge legacy provider-specific values into the canonical providers map. */
|
|
5
|
-
function mergeProviderConfig(providersValue, providerId, compatValues) {
|
|
6
|
-
if (Object.keys(compatValues).length === 0) return asOptionalRecord(providersValue);
|
|
7
|
-
const providers = asOptionalRecord(providersValue) ?? {};
|
|
8
|
-
const existing = asOptionalRecord(providers[providerId]) ?? {};
|
|
9
|
-
return {
|
|
10
|
-
...providers,
|
|
11
|
-
[providerId]: {
|
|
12
|
-
...existing,
|
|
13
|
-
...compatValues
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
4
|
/** Migrate legacy voice-call config input to the current canonical shape. */
|
|
18
5
|
function migrateVoiceCallLegacyConfigInput(params) {
|
|
19
6
|
const raw = asOptionalRecord(params.value) ?? {};
|
|
@@ -22,28 +9,71 @@ function migrateVoiceCallLegacyConfigInput(params) {
|
|
|
22
9
|
const twilio = asOptionalRecord(raw.twilio);
|
|
23
10
|
const streaming = asOptionalRecord(raw.streaming);
|
|
24
11
|
const configPathPrefix = params.configPathPrefix ?? "plugins.entries.voice-call.config";
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const streamingVadThreshold = asFiniteNumber(streaming?.vadThreshold);
|
|
33
|
-
if (streamingVadThreshold !== void 0) legacyStreamingOpenAICompat.vadThreshold = streamingVadThreshold;
|
|
12
|
+
const changes = [];
|
|
13
|
+
if (raw.provider === "log") changes.push(`Moved ${configPathPrefix}.provider "log" → "mock".`);
|
|
14
|
+
if (typeof twilio?.from === "string") {
|
|
15
|
+
const source = `${configPathPrefix}.twilio.from`;
|
|
16
|
+
const target = `${configPathPrefix}.fromNumber`;
|
|
17
|
+
changes.push(raw.fromNumber != null ? `Removed ${source} (kept ${target}).` : `Moved ${source} → ${target}.`);
|
|
18
|
+
}
|
|
34
19
|
const streamingProvider = readStringField(streaming, "provider");
|
|
35
20
|
const legacyStreamingProvider = readStringField(streaming, "sttProvider");
|
|
36
21
|
const normalizedStreaming = streaming ? {
|
|
37
22
|
...streaming,
|
|
38
|
-
provider: streamingProvider ?? legacyStreamingProvider
|
|
39
|
-
providers: mergeProviderConfig(streaming.providers, "openai", legacyStreamingOpenAICompat)
|
|
23
|
+
provider: streamingProvider ?? legacyStreamingProvider
|
|
40
24
|
} : void 0;
|
|
41
25
|
if (normalizedStreaming) {
|
|
42
26
|
delete normalizedStreaming.sttProvider;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
27
|
+
if (legacyStreamingProvider !== void 0) {
|
|
28
|
+
const source = `${configPathPrefix}.streaming.sttProvider`;
|
|
29
|
+
const target = `${configPathPrefix}.streaming.provider`;
|
|
30
|
+
changes.push(streamingProvider !== void 0 ? `Removed ${source} (kept ${target}).` : `Moved ${source} → ${target}.`);
|
|
31
|
+
}
|
|
32
|
+
for (const [legacyKey, canonicalKey, value] of [
|
|
33
|
+
[
|
|
34
|
+
"openaiApiKey",
|
|
35
|
+
"apiKey",
|
|
36
|
+
readStringField(streaming, "openaiApiKey")
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
"sttModel",
|
|
40
|
+
"model",
|
|
41
|
+
readStringField(streaming, "sttModel")
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
"silenceDurationMs",
|
|
45
|
+
"silenceDurationMs",
|
|
46
|
+
asFiniteNumber(streaming?.silenceDurationMs)
|
|
47
|
+
],
|
|
48
|
+
[
|
|
49
|
+
"vadThreshold",
|
|
50
|
+
"vadThreshold",
|
|
51
|
+
asFiniteNumber(streaming?.vadThreshold)
|
|
52
|
+
]
|
|
53
|
+
]) {
|
|
54
|
+
if (!Object.hasOwn(normalizedStreaming, legacyKey)) continue;
|
|
55
|
+
delete normalizedStreaming[legacyKey];
|
|
56
|
+
const source = `${configPathPrefix}.streaming.${legacyKey}`;
|
|
57
|
+
if (value === void 0 || value === "") {
|
|
58
|
+
changes.push(`Removed invalid ${source}.`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const providers = asOptionalRecord(normalizedStreaming.providers);
|
|
62
|
+
const existing = asOptionalRecord(providers?.openai);
|
|
63
|
+
const target = `${configPathPrefix}.streaming.providers.openai.${canonicalKey}`;
|
|
64
|
+
if (existing?.[canonicalKey] !== void 0) {
|
|
65
|
+
changes.push(`Removed ${source} (kept ${target}).`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
normalizedStreaming.providers = {
|
|
69
|
+
...providers,
|
|
70
|
+
openai: {
|
|
71
|
+
...existing,
|
|
72
|
+
[canonicalKey]: value
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
changes.push(`Moved ${source} → ${target}.`);
|
|
76
|
+
}
|
|
47
77
|
}
|
|
48
78
|
const normalizedTwilio = twilio ? { ...twilio } : void 0;
|
|
49
79
|
if (normalizedTwilio) delete normalizedTwilio.from;
|
|
@@ -61,16 +91,6 @@ function migrateVoiceCallLegacyConfigInput(params) {
|
|
|
61
91
|
streaming: normalizedStreaming,
|
|
62
92
|
realtime: normalizedRealtime
|
|
63
93
|
};
|
|
64
|
-
const changes = [];
|
|
65
|
-
if (raw.provider === "log") changes.push(`Moved ${configPathPrefix}.provider "log" → "mock".`);
|
|
66
|
-
if (typeof twilio?.from === "string" && typeof raw.fromNumber !== "string") changes.push(`Moved ${configPathPrefix}.twilio.from → ${configPathPrefix}.fromNumber.`);
|
|
67
|
-
if (typeof streaming?.sttProvider === "string") changes.push(`Moved ${configPathPrefix}.streaming.sttProvider → ${configPathPrefix}.streaming.provider.`);
|
|
68
|
-
if (typeof streaming?.openaiApiKey === "string") changes.push(`Moved ${configPathPrefix}.streaming.openaiApiKey → ${configPathPrefix}.streaming.providers.openai.apiKey.`);
|
|
69
|
-
if (typeof streaming?.sttModel === "string") changes.push(`Moved ${configPathPrefix}.streaming.sttModel → ${configPathPrefix}.streaming.providers.openai.model.`);
|
|
70
|
-
if (asFiniteNumber(streaming?.silenceDurationMs) !== void 0) changes.push(`Moved ${configPathPrefix}.streaming.silenceDurationMs → ${configPathPrefix}.streaming.providers.openai.silenceDurationMs.`);
|
|
71
|
-
else if (typeof streaming?.silenceDurationMs === "number") changes.push(`Removed invalid ${configPathPrefix}.streaming.silenceDurationMs.`);
|
|
72
|
-
if (asFiniteNumber(streaming?.vadThreshold) !== void 0) changes.push(`Moved ${configPathPrefix}.streaming.vadThreshold → ${configPathPrefix}.streaming.providers.openai.vadThreshold.`);
|
|
73
|
-
else if (typeof streaming?.vadThreshold === "number") changes.push(`Removed invalid ${configPathPrefix}.streaming.vadThreshold.`);
|
|
74
94
|
if (realtimeAgentContext && Object.hasOwn(realtimeAgentContext, "includeSystemPrompt")) changes.push(`Removed ${configPathPrefix}.realtime.agentContext.includeSystemPrompt.`);
|
|
75
95
|
return {
|
|
76
96
|
config,
|
|
@@ -133,14 +133,7 @@ const { setRuntime: setVoiceCallStateRuntime, tryGetRuntime: getOptionalVoiceCal
|
|
|
133
133
|
//#region extensions/voice-call/src/manager/replay-keys.ts
|
|
134
134
|
/** Match the existing voice-call webhook replay-cache cardinality. */
|
|
135
135
|
const MAX_MANAGER_REPLAY_KEYS = 1e4;
|
|
136
|
-
function
|
|
137
|
-
while (keys.size > maxEntries) {
|
|
138
|
-
const oldest = keys.values().next().value;
|
|
139
|
-
if (oldest === void 0) break;
|
|
140
|
-
keys.delete(oldest);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
function pruneOldestMapEntries(keys, maxEntries) {
|
|
136
|
+
function pruneOldestEntries(keys, maxEntries) {
|
|
144
137
|
while (keys.size > maxEntries) {
|
|
145
138
|
const oldest = keys.keys().next().value;
|
|
146
139
|
if (oldest === void 0) break;
|
|
@@ -150,7 +143,7 @@ function pruneOldestMapEntries(keys, maxEntries) {
|
|
|
150
143
|
/** Remember one manager replay key without refreshing duplicate insertion order. */
|
|
151
144
|
function rememberManagerReplayKey(keys, key, maxEntries = MAX_MANAGER_REPLAY_KEYS) {
|
|
152
145
|
keys.add(key);
|
|
153
|
-
|
|
146
|
+
pruneOldestEntries(keys, maxEntries);
|
|
154
147
|
}
|
|
155
148
|
/** Append one per-call replay key and retain only the newest bounded suffix. */
|
|
156
149
|
function appendCallReplayKey(keys, key, maxEntries = 500) {
|
|
@@ -170,7 +163,7 @@ function reserveRejectedProviderCall(calls, providerCallId, maxEntries = MAX_MAN
|
|
|
170
163
|
if (calls.has(providerCallId)) return;
|
|
171
164
|
const reservation = Symbol(providerCallId);
|
|
172
165
|
calls.set(providerCallId, reservation);
|
|
173
|
-
|
|
166
|
+
pruneOldestEntries(calls, maxEntries);
|
|
174
167
|
return reservation;
|
|
175
168
|
}
|
|
176
169
|
/** Release a rejected-call reservation only when the failing attempt still owns it. */
|
|
@@ -189,7 +182,7 @@ const MAX_CALL_RECORD_EVENTS = 1e3;
|
|
|
189
182
|
const CALL_RECORD_EVENT_META_MAX_ENTRIES = 1100;
|
|
190
183
|
const CALL_RECORD_CHUNK_MAX_ENTRIES = 48048;
|
|
191
184
|
/** Raw UTF-8 bytes stored per call record chunk before base64 encoding. */
|
|
192
|
-
const RAW_CALL_RECORD_CHUNK_BYTES =
|
|
185
|
+
const RAW_CALL_RECORD_CHUNK_BYTES = 48128;
|
|
193
186
|
let callRecordEventSequence = 0;
|
|
194
187
|
/** Return the pre-SQLite JSONL call log path for migration/compat checks. */
|
|
195
188
|
function resolveVoiceCallLegacyCallLogPath(storePath) {
|
|
@@ -205,7 +198,7 @@ function resolvePluginStateEnv(storePath) {
|
|
|
205
198
|
/** Open the plugin state stores when the runtime is available. */
|
|
206
199
|
function createCallRecordStateStores(storePath) {
|
|
207
200
|
const runtime = getOptionalVoiceCallStateRuntime();
|
|
208
|
-
if (!runtime)
|
|
201
|
+
if (!runtime) throw new Error("Voice Call state runtime not initialized");
|
|
209
202
|
const env = resolvePluginStateEnv(storePath);
|
|
210
203
|
return {
|
|
211
204
|
events: runtime.state.openSyncKeyedStore({
|
|
@@ -392,7 +385,6 @@ function readCallRecordEvents(stores) {
|
|
|
392
385
|
function persistCallRecord(storePath, call) {
|
|
393
386
|
try {
|
|
394
387
|
const stores = createCallRecordStateStores(storePath);
|
|
395
|
-
if (!stores) throw new Error("Voice Call state runtime not initialized");
|
|
396
388
|
const order = nextCallRecordOrder();
|
|
397
389
|
registerCallRecordEvent(stores, buildNewEventKey(order), call, order);
|
|
398
390
|
} catch (err) {
|
|
@@ -444,13 +436,11 @@ function readCallHistoryFromStore(storePath) {
|
|
|
444
436
|
}
|
|
445
437
|
return [];
|
|
446
438
|
}
|
|
447
|
-
/**
|
|
448
|
-
|
|
449
|
-
const calls =
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
byProviderCallId: calls.findLast((call) => call.providerCallId === callId)
|
|
453
|
-
};
|
|
439
|
+
/** Resolve an internal ID or retained provider alias to its newest logical call snapshot. */
|
|
440
|
+
function findCallInStore(storePath, callId) {
|
|
441
|
+
const calls = readCallRecordEvents(createCallRecordStateStores(storePath));
|
|
442
|
+
const match = calls.findLast((call) => call.callId === callId) ?? calls.findLast((call) => call.providerCallId === callId);
|
|
443
|
+
return match ? calls.findLast((call) => call.callId === match.callId) : void 0;
|
|
454
444
|
}
|
|
455
445
|
/** Return the newest persisted call history rows up to the requested limit. */
|
|
456
446
|
async function getCallHistoryFromStore(storePath, limit = 50) {
|
|
@@ -464,4 +454,4 @@ function resolveDefaultVoiceCallStoreDir(env = process.env) {
|
|
|
464
454
|
return path.join(resolveStateDir(env), "voice-calls");
|
|
465
455
|
}
|
|
466
456
|
//#endregion
|
|
467
|
-
export { releaseRejectedProviderCall as _, CALL_RECORD_EVENT_META_MAX_ENTRIES as a, setVoiceCallStateRuntime as b, buildVoiceCallLegacyJsonlEventKey as c, loadActiveCallsFromStore as d, parseVoiceCallRecordLine as f, appendCallReplayKey as g, resolveVoiceCallLegacyCallLogPath as h, CALL_RECORD_EVENT_CHUNKS_NAMESPACE as i,
|
|
457
|
+
export { releaseRejectedProviderCall as _, CALL_RECORD_EVENT_META_MAX_ENTRIES as a, setVoiceCallStateRuntime as b, buildVoiceCallLegacyJsonlEventKey as c, loadActiveCallsFromStore as d, parseVoiceCallRecordLine as f, appendCallReplayKey as g, resolveVoiceCallLegacyCallLogPath as h, CALL_RECORD_EVENT_CHUNKS_NAMESPACE as i, findCallInStore 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, rememberManagerReplayKey as v, TerminalStates as x, reserveRejectedProviderCall as y };
|
|
@@ -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-9je4i7qf.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 {
|
|
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, i as mapProviderStatusToEndReason, p as chunkAudio, r as isProviderStatusTerminal, s as getHeader, v as escapeXml, y as mapVoiceToPolly } from "./runtime-entry-gE2Yd4V8.js";
|
|
5
|
+
import { c as verifyTwilioWebhook, i as readVoiceCallProviderJsonResponse, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-9je4i7qf.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";
|
|
@@ -218,8 +218,9 @@ var TwilioProvider = class TwilioProvider {
|
|
|
218
218
|
this.callStreamMap.set(callSid, streamSid);
|
|
219
219
|
this.activeStreamCalls.add(callSid);
|
|
220
220
|
}
|
|
221
|
-
hasRegisteredStream(callSid) {
|
|
222
|
-
|
|
221
|
+
hasRegisteredStream(callSid, streamSid) {
|
|
222
|
+
const current = this.callStreamMap.get(callSid);
|
|
223
|
+
return current !== void 0 && (streamSid === void 0 || current === streamSid);
|
|
223
224
|
}
|
|
224
225
|
unregisterCallStream(callSid, streamSid) {
|
|
225
226
|
const currentStreamSid = this.callStreamMap.get(callSid);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isFutureDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
2
2
|
//#region extensions/voice-call/src/webhook-replay.ts
|
|
3
|
-
const REPLAY_WINDOW_MS =
|
|
3
|
+
const REPLAY_WINDOW_MS = 6e5;
|
|
4
4
|
const REPLAY_CACHE_MAX_ENTRIES = 1e4;
|
|
5
5
|
const REPLAY_CACHE_PRUNE_INTERVAL = 64;
|
|
6
6
|
function createWebhookReplayCache() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const Email = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[^"\\]
|
|
1
|
+
const Email = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[^"\\]|\\[\x20-\x7e])*")@(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*|\[(?:IPv6:[a-f0-9:]+|(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})\])$/i;
|
|
2
2
|
/**
|
|
3
3
|
* Returns true if the value is an Email
|
|
4
4
|
* @specification https://datatracker.ietf.org/doc/html/rfc5322
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as FormatBidi from './format/bidi.mjs';
|
|
2
2
|
import * as LabelUnicode from './label/unicode.mjs';
|
|
3
3
|
import * as LabelPuny from './label/puny.mjs';
|
|
4
|
+
// ------------------------------------------------------------------
|
|
5
|
+
// IsLabel
|
|
6
|
+
// ------------------------------------------------------------------
|
|
4
7
|
function IsValidLabelLength(value) {
|
|
5
8
|
return value.length > 0 && value.length <= 63;
|
|
6
9
|
}
|
|
@@ -8,9 +11,24 @@ function IsLabel(value) {
|
|
|
8
11
|
return IsValidLabelLength(value) && (LabelPuny.IsPunyLabel(value) ||
|
|
9
12
|
LabelUnicode.IsUnicodeLabel(value));
|
|
10
13
|
}
|
|
14
|
+
// ------------------------------------------------------------------
|
|
15
|
+
// NormalizeHostname
|
|
16
|
+
//
|
|
17
|
+
// Normalizes a hostname for label validation. Normalizes for NFC
|
|
18
|
+
// such that equivalent codepoint sequences can be uniformly
|
|
19
|
+
// compared. It also removes codepoints that IDNA mapping ignores,
|
|
20
|
+
// and converts full stop variants to ASCII '.' so the hostname can
|
|
21
|
+
// be split into labels.
|
|
22
|
+
// ------------------------------------------------------------------
|
|
11
23
|
function NormalizeHostname(value) {
|
|
12
|
-
return value
|
|
24
|
+
return value
|
|
25
|
+
.normalize('NFC')
|
|
26
|
+
.replace(/[\u00ad\u034f\u180b-\u180d\u200b\ufe00-\ufe0f\u{e0100}-\u{e01ef}]/gu, '') // RE_IGNORED_MAPPING
|
|
27
|
+
.replace(/[\u002E\u3002\uFF0E\uFF61]/g, '.'); // RE_FULL_STOP_MAPPING
|
|
13
28
|
}
|
|
29
|
+
// ------------------------------------------------------------------
|
|
30
|
+
// IsIdnHostname
|
|
31
|
+
// ------------------------------------------------------------------
|
|
14
32
|
export function IsIdnHostname(value) {
|
|
15
33
|
if (value.length === 0 || value.includes(' '))
|
|
16
34
|
return false;
|
package/openclaw.plugin.json
CHANGED
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
},
|
|
243
243
|
"agentId": {
|
|
244
244
|
"label": "Response Agent ID",
|
|
245
|
-
"help": "Agent
|
|
245
|
+
"help": "Agent used for voice responses and session storage. Defaults to the sole configured agent; set explicitly for a multi-agent fleet.",
|
|
246
246
|
"advanced": true
|
|
247
247
|
},
|
|
248
248
|
"sessionScope": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/voice-call",
|
|
3
|
-
"version": "2026.9.1
|
|
3
|
+
"version": "2026.9.1",
|
|
4
4
|
"description": "OpenClaw voice-call plugin for Twilio, Telnyx, and Plivo phone calls.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"typebox": "1.3.
|
|
11
|
+
"typebox": "1.3.17",
|
|
12
12
|
"ws": "8.21.3",
|
|
13
13
|
"zod": "4.4.3"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"openclaw": ">=2026.9.1
|
|
16
|
+
"openclaw": ">=2026.9.1"
|
|
17
17
|
},
|
|
18
18
|
"peerDependenciesMeta": {
|
|
19
19
|
"openclaw": {
|
|
@@ -24,16 +24,17 @@
|
|
|
24
24
|
"extensions": [
|
|
25
25
|
"./index.ts"
|
|
26
26
|
],
|
|
27
|
+
"setupEntry": "./dist/setup-api.js",
|
|
27
28
|
"install": {
|
|
28
29
|
"npmSpec": "@openclaw/voice-call",
|
|
29
30
|
"defaultChoice": "npm",
|
|
30
31
|
"minHostVersion": ">=2026.4.10"
|
|
31
32
|
},
|
|
32
33
|
"compat": {
|
|
33
|
-
"pluginApi": ">=2026.9.1
|
|
34
|
+
"pluginApi": ">=2026.9.1"
|
|
34
35
|
},
|
|
35
36
|
"build": {
|
|
36
|
-
"openclawVersion": "2026.9.1
|
|
37
|
+
"openclawVersion": "2026.9.1"
|
|
37
38
|
},
|
|
38
39
|
"release": {
|
|
39
40
|
"publishToClawHub": true,
|
|
@@ -41,7 +42,8 @@
|
|
|
41
42
|
},
|
|
42
43
|
"runtimeExtensions": [
|
|
43
44
|
"./dist/index.js"
|
|
44
|
-
]
|
|
45
|
+
],
|
|
46
|
+
"runtimeSetupEntry": "./dist/setup-api.js"
|
|
45
47
|
},
|
|
46
48
|
"files": [
|
|
47
49
|
"dist/**",
|