@openclaw/voice-call 2026.10.10 → 2026.11.5-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/.setup/{carrier-api-BgJdQC-e.mjs → carrier-api-CZQtPnYQ.mjs} +15 -28
- package/dist/.setup/{cli-CI9QzIaT.mjs → cli-BUVmNuk8.mjs} +113 -61
- package/dist/.setup/{config-BxESUUSm.mjs → config-D_w9HzxP.mjs} +55 -111
- package/dist/.setup/{mock-BO3pptb-.mjs → mock-fux1a_i_.mjs} +3 -4
- package/dist/.setup/{plivo-C5cLYAup.mjs → plivo-Cpxxx8BT.mjs} +6 -21
- package/dist/.setup/{realtime-handler-B2JJ-8wv.mjs → realtime-handler-BkoZ-ZYd.mjs} +190 -265
- package/dist/.setup/{response-generator-B2nVYBf_.mjs → response-generator-COluXT2F.mjs} +11 -15
- package/dist/.setup/{runtime-entry-CKPPin7r.mjs → runtime-entry-Br7ttAwq.mjs} +382 -522
- package/dist/.setup/{state-retention-api-y5WYfZsQ.mjs → state-retention-api-BDJR8dnG.mjs} +1 -1
- package/dist/.setup/{store-path-Bn3bLr8y.mjs → store-path-C0yJCDE8.mjs} +2 -2
- package/dist/.setup/{telnyx-ZopMHuZl.mjs → telnyx-DdFzdUEf.mjs} +4 -5
- package/dist/.setup/{twilio-BGLnhzpD.mjs → twilio-BqUbz9jp.mjs} +7 -15
- package/dist/.setup/webhook-replay-DnlMxw4z.mjs +30 -0
- package/dist/.source-module-urls/8b7cb5a3dc0f034090cbbda318ba348c0d48853d04f0e3b500529cf7666abe03.json +1 -1
- package/dist/doctor-contract-api.js +21 -2
- package/dist/index.js +106 -195
- package/dist/runtime-entry.js +1 -1
- package/dist/setup-api.js +1 -2
- package/dist/state-retention-api.js +1 -1
- package/node_modules/typebox/build/format/duration.d.mts +2 -2
- package/node_modules/typebox/build/format/duration.mjs +2 -2
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_email.mjs +1 -0
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
- package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
- package/node_modules/typebox/build/format/ipv4.mjs +2 -2
- package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
- package/node_modules/typebox/build/format/ipv6.mjs +1 -1
- package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
- package/node_modules/typebox/build/schema/build.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
- package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
- package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
- package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
- package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
- package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
- package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
- package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
- package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
- package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
- package/node_modules/typebox/build/system/memory/create.mjs +18 -13
- package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
- package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
- package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
- package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
- package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
- package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
- package/node_modules/typebox/build/system/memory/update.mjs +43 -16
- package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
- package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
- package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
- package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
- package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
- package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
- package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
- package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
- package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +1 -1
- package/node_modules/zod/package.json +1 -1
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/zod/v4/core/versions.js +1 -1
- package/openclaw.plugin.json +9 -2
- package/package.json +6 -6
- package/dist/.setup/webhook-replay-B0Eo3Ll5.mjs +0 -42
- package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
- package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { TtsConfigSchema } from "../api.js";
|
|
2
2
|
import { t as TWILIO_REGIONS } from "./twilio-region-DVg9p6JJ.mjs";
|
|
3
|
+
import { MAX_TCP_PORT } from "openclaw/plugin-sdk/number-runtime";
|
|
3
4
|
import { normalizeAgentId, parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
5
|
+
import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
6
|
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, REALTIME_VOICE_AGENT_CONSULT_TOOL_POLICIES, resolveRealtimeVoiceAgentConsultTools } from "openclaw/plugin-sdk/realtime-voice";
|
|
5
7
|
import { z } from "zod";
|
|
6
8
|
import { mergeDeep } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
@@ -8,7 +10,6 @@ import { buildSecretInputSchema, hasConfiguredSecretInput, normalizeResolvedSecr
|
|
|
8
10
|
import { canonicalizeMainSessionAlias } from "openclaw/plugin-sdk/session-store-runtime";
|
|
9
11
|
import { resolveSpeechProviderApiKey } from "openclaw/plugin-sdk/speech-core";
|
|
10
12
|
import { normalizeWebhookPath } from "openclaw/plugin-sdk/webhook-ingress";
|
|
11
|
-
import { MAX_TCP_PORT } from "openclaw/plugin-sdk/number-runtime";
|
|
12
13
|
// extensions/voice-call/src/call-brief-schema.ts
|
|
13
14
|
const text = (max) => z.string().trim().min(1).max(max);
|
|
14
15
|
const CallBriefSchema = z.object({
|
|
@@ -279,7 +280,7 @@ const VoiceCallRealtimeConfigSchema = z.object({
|
|
|
279
280
|
/** Bounded agent persona/context injection for the fast realtime voice path. */
|
|
280
281
|
agentContext: VoiceCallRealtimeAgentContextConfigSchema.default(VoiceCallRealtimeAgentContextConfigSchema.parse({})),
|
|
281
282
|
/** Provider-owned raw config blobs keyed by provider id. */
|
|
282
|
-
providers:
|
|
283
|
+
providers: z.record(z.string(), z.object({ inputTranscriptionModel: z.string().optional().describe("Input transcription model or deployment name. Omit to keep the provider default.") }).catchall(z.unknown())).default({})
|
|
283
284
|
}).strict();
|
|
284
285
|
const VoiceCallStreamingConfigSchema = z.object({
|
|
285
286
|
/** Enable Twilio Media Streams for real-time transcription. */
|
|
@@ -325,7 +326,6 @@ const VoiceCallConfigSchema = z.object({
|
|
|
325
326
|
live: CallLiveConfigSchema,
|
|
326
327
|
callbacks: CallCallbacksConfigSchema,
|
|
327
328
|
voicemail: CallVoicemailConfigSchema,
|
|
328
|
-
/** Maximum call duration in seconds */
|
|
329
329
|
maxDurationSeconds: z.number().int().positive().default(300),
|
|
330
330
|
/**
|
|
331
331
|
* Maximum age of a call in seconds before it is automatically reaped.
|
|
@@ -364,7 +364,6 @@ const VoiceCallConfigSchema = z.object({
|
|
|
364
364
|
message: "Tailscale Funnel HTTPS port must be one of 443, 8443, 10000"
|
|
365
365
|
});
|
|
366
366
|
const TWILIO_AUTH_TOKEN_PATH = "plugins.entries.voice-call.config.twilio.authToken";
|
|
367
|
-
const DEFAULT_VOICE_CALL_CONFIG = VoiceCallConfigSchema.parse({});
|
|
368
367
|
function defaultRealtimeStreamPathForServePath(servePath) {
|
|
369
368
|
const normalized = normalizeWebhookPath(servePath);
|
|
370
369
|
if (normalized.endsWith("/webhook")) return `${normalized.slice(0, -8)}/stream/realtime`;
|
|
@@ -396,10 +395,6 @@ function resolveVoiceCallStreamExposurePaths(config, webhookPaths = {}) {
|
|
|
396
395
|
}
|
|
397
396
|
return exposurePaths;
|
|
398
397
|
}
|
|
399
|
-
function normalizeVoiceCallTtsConfig(defaults, overrides) {
|
|
400
|
-
if (!defaults && !overrides) return;
|
|
401
|
-
return TtsConfigSchema.parse(mergeDeep(defaults ?? {}, overrides ?? {}));
|
|
402
|
-
}
|
|
403
398
|
function resolveVoiceCallNumberRouteKey(config, phone) {
|
|
404
399
|
const routes = config.numbers;
|
|
405
400
|
if (phone && Object.hasOwn(routes, phone)) return phone;
|
|
@@ -419,20 +414,20 @@ function resolveVoiceCallEffectiveConfig(config, phoneOrRouteKey) {
|
|
|
419
414
|
if (!numberRouteKey) return { config };
|
|
420
415
|
const route = config.numbers[numberRouteKey];
|
|
421
416
|
if (!route) return { config };
|
|
417
|
+
const defaultTts = config.tts;
|
|
418
|
+
const routeTts = route.tts;
|
|
422
419
|
return {
|
|
423
420
|
numberRouteKey,
|
|
424
421
|
config: {
|
|
425
422
|
...config,
|
|
426
423
|
...route,
|
|
427
|
-
tts:
|
|
424
|
+
tts: !defaultTts && !routeTts ? void 0 : TtsConfigSchema.parse(mergeDeep(defaultTts ?? {}, routeTts ?? {}))
|
|
428
425
|
}
|
|
429
426
|
};
|
|
430
427
|
}
|
|
431
|
-
function
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
function sanitizeVoiceCallNumberRoutes(value) {
|
|
435
|
-
return Object.fromEntries(Object.entries(value ?? {}).filter(([, route]) => route !== void 0).map(([key, route]) => [key, VoiceCallNumberRouteConfigSchema.parse(route)]));
|
|
428
|
+
function definedConfigEntries(value) {
|
|
429
|
+
const entries = asOptionalRecord(value);
|
|
430
|
+
return entries ? Object.fromEntries(Object.entries(entries).filter(([, entry]) => entry !== void 0)) : value;
|
|
436
431
|
}
|
|
437
432
|
function resolveTwilioAuthToken(config) {
|
|
438
433
|
return normalizeResolvedSecretInputString({
|
|
@@ -440,110 +435,61 @@ function resolveTwilioAuthToken(config) {
|
|
|
440
435
|
path: TWILIO_AUTH_TOKEN_PATH
|
|
441
436
|
});
|
|
442
437
|
}
|
|
443
|
-
function normalizeVoiceCallConfig(
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const streamingProvider = config.streaming?.provider;
|
|
450
|
-
const streamingProviders = sanitizeVoiceCallProviderConfigs(config.streaming?.providers ?? defaults.streaming.providers);
|
|
451
|
-
const realtimeProvider = config.realtime?.provider ?? defaults.realtime.provider;
|
|
452
|
-
const realtimeProviders = sanitizeVoiceCallProviderConfigs(config.realtime?.providers ?? defaults.realtime.providers);
|
|
453
|
-
const realtimeFastContext = {
|
|
454
|
-
...defaults.realtime.fastContext,
|
|
455
|
-
...config.realtime?.fastContext,
|
|
456
|
-
sources: config.realtime?.fastContext?.sources ?? defaults.realtime.fastContext.sources
|
|
457
|
-
};
|
|
458
|
-
const realtimeAgentContext = {
|
|
459
|
-
...defaults.realtime.agentContext,
|
|
460
|
-
...config.realtime?.agentContext,
|
|
461
|
-
files: config.realtime?.agentContext?.files ?? defaults.realtime.agentContext.files
|
|
462
|
-
};
|
|
463
|
-
return {
|
|
464
|
-
...defaults,
|
|
438
|
+
function normalizeVoiceCallConfig(value) {
|
|
439
|
+
const config = asOptionalRecord(value);
|
|
440
|
+
if (!config) return VoiceCallConfigSchema.parse(value);
|
|
441
|
+
const streaming = asOptionalRecord(config.streaming);
|
|
442
|
+
const realtime = asOptionalRecord(config.realtime);
|
|
443
|
+
const normalized = VoiceCallConfigSchema.parse({
|
|
465
444
|
...config,
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
...
|
|
470
|
-
|
|
471
|
-
},
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
tunnel: {
|
|
482
|
-
...defaults.tunnel,
|
|
483
|
-
...config.tunnel
|
|
484
|
-
},
|
|
485
|
-
webhookSecurity: {
|
|
486
|
-
...defaults.webhookSecurity,
|
|
487
|
-
...config.webhookSecurity,
|
|
488
|
-
allowedHosts: config.webhookSecurity?.allowedHosts ?? defaults.webhookSecurity.allowedHosts,
|
|
489
|
-
trustedProxyIPs: config.webhookSecurity?.trustedProxyIPs ?? defaults.webhookSecurity.trustedProxyIPs
|
|
490
|
-
},
|
|
491
|
-
streaming: {
|
|
492
|
-
...defaults.streaming,
|
|
493
|
-
...config.streaming,
|
|
494
|
-
provider: streamingProvider,
|
|
495
|
-
providers: streamingProviders
|
|
496
|
-
},
|
|
497
|
-
realtime: {
|
|
498
|
-
...defaults.realtime,
|
|
499
|
-
...config.realtime,
|
|
500
|
-
provider: realtimeProvider,
|
|
501
|
-
streamPath: config.realtime?.streamPath ?? defaultRealtimeStreamPathForServePath(serve.path ?? defaults.serve.path),
|
|
502
|
-
tools: config.realtime?.tools ?? defaults.realtime.tools,
|
|
503
|
-
consultThinkingLevel: VoiceCallRealtimeConsultThinkingLevelSchema.optional().parse(config.realtime?.consultThinkingLevel ?? defaults.realtime.consultThinkingLevel),
|
|
504
|
-
consultFastMode: config.realtime?.consultFastMode ?? defaults.realtime.consultFastMode,
|
|
505
|
-
fastContext: realtimeFastContext,
|
|
506
|
-
agentContext: realtimeAgentContext,
|
|
507
|
-
providers: realtimeProviders
|
|
508
|
-
},
|
|
509
|
-
tts: normalizeVoiceCallTtsConfig(defaults.tts, config.tts)
|
|
510
|
-
};
|
|
445
|
+
numbers: definedConfigEntries(config.numbers),
|
|
446
|
+
webhookSecurity: config.webhookSecurity === void 0 ? {} : config.webhookSecurity,
|
|
447
|
+
streaming: config.streaming === void 0 || streaming ? {
|
|
448
|
+
...streaming,
|
|
449
|
+
providers: definedConfigEntries(streaming?.providers)
|
|
450
|
+
} : config.streaming,
|
|
451
|
+
realtime: config.realtime === void 0 || realtime ? {
|
|
452
|
+
...realtime,
|
|
453
|
+
fastContext: realtime?.fastContext === void 0 ? {} : realtime.fastContext,
|
|
454
|
+
agentContext: realtime?.agentContext === void 0 ? {} : realtime.agentContext,
|
|
455
|
+
providers: definedConfigEntries(realtime?.providers)
|
|
456
|
+
} : config.realtime
|
|
457
|
+
});
|
|
458
|
+
normalized.realtime.streamPath ??= defaultRealtimeStreamPathForServePath(normalized.serve.path);
|
|
459
|
+
return normalized;
|
|
511
460
|
}
|
|
512
461
|
function resolveVoiceCallSessionKey(params) {
|
|
513
462
|
const explicit = params.explicitSessionKey?.trim();
|
|
514
|
-
if (explicit || params.config.sessionScope === "main")
|
|
515
|
-
|
|
516
|
-
sessionKey
|
|
517
|
-
|
|
518
|
-
|
|
463
|
+
if (explicit || params.config.sessionScope === "main") {
|
|
464
|
+
const sessionKey = (explicit || "main").trim();
|
|
465
|
+
if (!sessionKey) throw new Error("Voice Call session key cannot be empty");
|
|
466
|
+
const lower = sessionKey.toLowerCase();
|
|
467
|
+
const agentId = normalizeAgentId(params.config.agentId);
|
|
468
|
+
if (lower === "global" || lower === "unknown") return lower;
|
|
469
|
+
const parsedInput = parseAgentSessionKey(sessionKey);
|
|
470
|
+
let normalizedScopedKey;
|
|
471
|
+
if (parsedInput && normalizeAgentId(parsedInput.agentId) === parsedInput.agentId && parsedInput.agentId === agentId) normalizedScopedKey = `agent:${parsedInput.agentId}:${parsedInput.rest}`;
|
|
472
|
+
else {
|
|
473
|
+
const wrappedInput = parseAgentSessionKey(`agent:${agentId}:${sessionKey}`);
|
|
474
|
+
if (!wrappedInput) throw new Error("Voice Call session key could not be normalized");
|
|
475
|
+
normalizedScopedKey = `agent:${agentId}:${wrappedInput.rest}`;
|
|
476
|
+
}
|
|
477
|
+
return canonicalizeMainSessionAlias({
|
|
478
|
+
cfg: { session: params.coreSession },
|
|
479
|
+
agentId,
|
|
480
|
+
sessionKey: normalizedScopedKey
|
|
481
|
+
});
|
|
482
|
+
}
|
|
519
483
|
const prefix = `agent:${normalizeAgentId(params.config.agentId)}:voice`;
|
|
520
484
|
if (params.config.sessionScope === "per-call") return `${prefix}:call:${params.callId}`.toLowerCase();
|
|
521
485
|
const normalizedPhone = normalizePhoneNumber(params.phone);
|
|
522
486
|
return (normalizedPhone ? `${prefix}:${normalizedPhone}` : `${prefix}:${params.callId}`).toLowerCase();
|
|
523
487
|
}
|
|
524
|
-
/** Resolve persisted or integration-provided keys into the configured agent namespace. */
|
|
525
|
-
function resolveVoiceCallAgentSessionKey(params) {
|
|
526
|
-
const sessionKey = params.sessionKey.trim();
|
|
527
|
-
if (!sessionKey) throw new Error("Voice Call session key cannot be empty");
|
|
528
|
-
const lower = sessionKey.toLowerCase();
|
|
529
|
-
const agentId = normalizeAgentId(params.config.agentId);
|
|
530
|
-
if (lower === "global" || lower === "unknown") return lower;
|
|
531
|
-
const parsedInput = parseAgentSessionKey(sessionKey);
|
|
532
|
-
let normalizedScopedKey;
|
|
533
|
-
if (parsedInput && normalizeAgentId(parsedInput.agentId) === parsedInput.agentId && parsedInput.agentId === agentId) normalizedScopedKey = `agent:${parsedInput.agentId}:${parsedInput.rest}`;
|
|
534
|
-
else {
|
|
535
|
-
const wrappedInput = parseAgentSessionKey(`agent:${agentId}:${sessionKey}`);
|
|
536
|
-
if (!wrappedInput) throw new Error("Voice Call session key could not be normalized");
|
|
537
|
-
normalizedScopedKey = `agent:${agentId}:${wrappedInput.rest}`;
|
|
538
|
-
}
|
|
539
|
-
return canonicalizeMainSessionAlias({
|
|
540
|
-
cfg: { session: params.coreSession },
|
|
541
|
-
agentId,
|
|
542
|
-
sessionKey: normalizedScopedKey
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
488
|
function resolveVoiceCallConfig(config) {
|
|
546
|
-
const resolved =
|
|
489
|
+
const resolved = {
|
|
490
|
+
...config,
|
|
491
|
+
tunnel: { ...config.tunnel }
|
|
492
|
+
};
|
|
547
493
|
if (resolved.provider === "telnyx") {
|
|
548
494
|
resolved.telnyx = resolved.telnyx ?? {};
|
|
549
495
|
resolved.telnyx.apiKey = resolved.telnyx.apiKey ?? resolveSpeechProviderApiKey(process.env.TELNYX_API_KEY);
|
|
@@ -561,10 +507,8 @@ function resolveVoiceCallConfig(config) {
|
|
|
561
507
|
resolved.plivo.authId = resolved.plivo.authId ?? resolveSpeechProviderApiKey(process.env.PLIVO_AUTH_ID);
|
|
562
508
|
resolved.plivo.authToken = resolved.plivo.authToken ?? resolveSpeechProviderApiKey(process.env.PLIVO_AUTH_TOKEN);
|
|
563
509
|
}
|
|
564
|
-
resolved.tunnel.allowNgrokFreeTierLoopbackBypass = resolved.tunnel.allowNgrokFreeTierLoopbackBypass ?? false;
|
|
565
510
|
resolved.tunnel.ngrokAuthToken = resolved.tunnel.ngrokAuthToken ?? resolveSpeechProviderApiKey(process.env.NGROK_AUTHTOKEN);
|
|
566
511
|
resolved.tunnel.ngrokDomain = resolved.tunnel.ngrokDomain ?? resolveSpeechProviderApiKey(process.env.NGROK_DOMAIN);
|
|
567
|
-
resolved.webhookSecurity.trustForwardingHeaders = resolved.webhookSecurity.trustForwardingHeaders ?? false;
|
|
568
512
|
return resolved;
|
|
569
513
|
}
|
|
570
514
|
function validateProviderConfig(config) {
|
|
@@ -600,4 +544,4 @@ function validateProviderConfig(config) {
|
|
|
600
544
|
errors
|
|
601
545
|
};
|
|
602
546
|
}
|
|
603
|
-
export {
|
|
547
|
+
export { resolveVoiceCallNumberRouteKeyForCall as a, resolveVoiceCallStreamExposurePaths as c, resolveVoiceCallRealtimeTools as d, DEFAULT_VOICEMAIL_HOLD_OPENING_MAX_MS as f, CallBriefSchema as h, resolveVoiceCallEffectiveConfig as i, validateProviderConfig as l, normalizePhoneNumber as m, resolveTwilioAuthToken as n, resolveVoiceCallPublicPathPrefix as o, isAllowlistedCaller as p, resolveVoiceCallConfig as r, resolveVoiceCallSessionKey as s, normalizeVoiceCallConfig as t, REALTIME_VOICE_END_CALL_TOOL_NAME as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as reserveWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-
|
|
2
|
-
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
1
|
+
import { n as reserveWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-DnlMxw4z.mjs";
|
|
3
2
|
import crypto from "node:crypto";
|
|
3
|
+
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
// extensions/voice-call/src/providers/mock.ts
|
|
5
5
|
/**
|
|
6
6
|
* Mock voice call provider for local testing.
|
|
@@ -83,8 +83,7 @@ var MockProvider = class {
|
|
|
83
83
|
...base,
|
|
84
84
|
type: evt.type,
|
|
85
85
|
transcript,
|
|
86
|
-
isFinal: evt.isFinal ?? true
|
|
87
|
-
confidence: evt.confidence
|
|
86
|
+
isFinal: evt.isFinal ?? true
|
|
88
87
|
};
|
|
89
88
|
}
|
|
90
89
|
case "call.silence": return {
|
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import { c as getHeader } from "./runtime-entry-CKPPin7r.mjs";
|
|
2
1
|
import { t as escapeXml } from "./voice-mapping-CvuJ1B50.mjs";
|
|
3
|
-
import { n as
|
|
4
|
-
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
+
import { i as verifyPlivoWebhook, n as assertVoiceCallProviderSetting, r as reconstructWebhookUrl, t as createCarrierApi } from "./carrier-api-CZQtPnYQ.mjs";
|
|
5
3
|
import crypto from "node:crypto";
|
|
4
|
+
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
5
|
// extensions/voice-call/src/providers/plivo.ts
|
|
7
|
-
function createPlivoRequestDedupeKey(ctx) {
|
|
8
|
-
const nonceV3 = getHeader(ctx.headers, "x-plivo-signature-v3-nonce");
|
|
9
|
-
if (nonceV3) return `plivo:v3:${nonceV3}`;
|
|
10
|
-
const nonceV2 = getHeader(ctx.headers, "x-plivo-signature-v2-nonce");
|
|
11
|
-
if (nonceV2) return `plivo:v2:${nonceV2}`;
|
|
12
|
-
return `plivo:fallback:${crypto.createHash("sha256").update(ctx.rawBody).digest("hex")}`;
|
|
13
|
-
}
|
|
14
6
|
var PlivoProvider = class PlivoProvider {
|
|
15
7
|
/**
|
|
16
8
|
* Release all process-local metadata owned by one Plivo call.
|
|
@@ -38,8 +30,8 @@ var PlivoProvider = class PlivoProvider {
|
|
|
38
30
|
this.callUuidToWebhookUrl = /* @__PURE__ */ new Map();
|
|
39
31
|
this.pendingSpeakByCallId = /* @__PURE__ */ new Map();
|
|
40
32
|
this.pendingListenByCallId = /* @__PURE__ */ new Map();
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
assertVoiceCallProviderSetting(config.authId, "Plivo Auth ID is required");
|
|
34
|
+
assertVoiceCallProviderSetting(config.authToken, "Plivo Auth Token is required");
|
|
43
35
|
this.authToken = config.authToken;
|
|
44
36
|
this.options = options;
|
|
45
37
|
this.api = createCarrierApi("Plivo", `https://api.plivo.com/v1/Account/${config.authId}`, `Basic ${Buffer.from(`${config.authId}:${config.authToken}`).toString("base64")}`);
|
|
@@ -54,13 +46,7 @@ var PlivoProvider = class PlivoProvider {
|
|
|
54
46
|
remoteIP: ctx.remoteAddress
|
|
55
47
|
});
|
|
56
48
|
if (!result.ok) console.warn(`[plivo] Webhook verification failed: ${result.reason}`);
|
|
57
|
-
return
|
|
58
|
-
ok: result.ok,
|
|
59
|
-
reason: result.reason,
|
|
60
|
-
isReplay: result.isReplay,
|
|
61
|
-
verifiedRequestKey: result.verifiedRequestKey,
|
|
62
|
-
releaseReplay: result.releaseReplay
|
|
63
|
-
};
|
|
49
|
+
return result;
|
|
64
50
|
}
|
|
65
51
|
parseWebhookEvent(ctx, options) {
|
|
66
52
|
const flow = normalizeOptionalString(ctx.query?.flow) ?? "";
|
|
@@ -86,8 +72,7 @@ var PlivoProvider = class PlivoProvider {
|
|
|
86
72
|
actionUrl
|
|
87
73
|
}) : pendingSpeak ? PlivoProvider.xmlKeepAlive(` <Speak language="${escapeXml(language || "en-US")}">${escapeXml(pendingSpeak.text)}</Speak>\n`) : PlivoProvider.xmlKeepAlive();
|
|
88
74
|
} else {
|
|
89
|
-
|
|
90
|
-
event = this.normalizeEvent(parsed, callId, dedupeKey);
|
|
75
|
+
event = this.normalizeEvent(parsed, callId, options?.verifiedRequestKey);
|
|
91
76
|
providerResponseBody = flow === "answer" || flow === "getinput" ? PlivoProvider.xmlKeepAlive() : "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response></Response>";
|
|
92
77
|
}
|
|
93
78
|
return {
|