@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.
Files changed (120) hide show
  1. package/dist/.setup/{carrier-api-BgJdQC-e.mjs → carrier-api-CZQtPnYQ.mjs} +15 -28
  2. package/dist/.setup/{cli-CI9QzIaT.mjs → cli-BUVmNuk8.mjs} +113 -61
  3. package/dist/.setup/{config-BxESUUSm.mjs → config-D_w9HzxP.mjs} +55 -111
  4. package/dist/.setup/{mock-BO3pptb-.mjs → mock-fux1a_i_.mjs} +3 -4
  5. package/dist/.setup/{plivo-C5cLYAup.mjs → plivo-Cpxxx8BT.mjs} +6 -21
  6. package/dist/.setup/{realtime-handler-B2JJ-8wv.mjs → realtime-handler-BkoZ-ZYd.mjs} +190 -265
  7. package/dist/.setup/{response-generator-B2nVYBf_.mjs → response-generator-COluXT2F.mjs} +11 -15
  8. package/dist/.setup/{runtime-entry-CKPPin7r.mjs → runtime-entry-Br7ttAwq.mjs} +382 -522
  9. package/dist/.setup/{state-retention-api-y5WYfZsQ.mjs → state-retention-api-BDJR8dnG.mjs} +1 -1
  10. package/dist/.setup/{store-path-Bn3bLr8y.mjs → store-path-C0yJCDE8.mjs} +2 -2
  11. package/dist/.setup/{telnyx-ZopMHuZl.mjs → telnyx-DdFzdUEf.mjs} +4 -5
  12. package/dist/.setup/{twilio-BGLnhzpD.mjs → twilio-BqUbz9jp.mjs} +7 -15
  13. package/dist/.setup/webhook-replay-DnlMxw4z.mjs +30 -0
  14. package/dist/.source-module-urls/8b7cb5a3dc0f034090cbbda318ba348c0d48853d04f0e3b500529cf7666abe03.json +1 -1
  15. package/dist/doctor-contract-api.js +21 -2
  16. package/dist/index.js +106 -195
  17. package/dist/runtime-entry.js +1 -1
  18. package/dist/setup-api.js +1 -2
  19. package/dist/state-retention-api.js +1 -1
  20. package/node_modules/typebox/build/format/duration.d.mts +2 -2
  21. package/node_modules/typebox/build/format/duration.mjs +2 -2
  22. package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
  23. package/node_modules/typebox/build/format/idn_email.mjs +1 -0
  24. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
  25. package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
  26. package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
  27. package/node_modules/typebox/build/format/ipv4.mjs +2 -2
  28. package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
  29. package/node_modules/typebox/build/format/ipv6.mjs +1 -1
  30. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  31. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  32. package/node_modules/typebox/build/schema/build.mjs +1 -0
  33. package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
  34. package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
  35. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
  36. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
  37. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
  38. package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
  39. package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
  40. package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
  41. package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
  42. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
  43. package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
  44. package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
  45. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
  46. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
  47. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
  48. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
  49. package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
  50. package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
  51. package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
  52. package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
  53. package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
  54. package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
  55. package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
  56. package/node_modules/typebox/build/system/memory/create.mjs +18 -13
  57. package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
  58. package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
  59. package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
  60. package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
  61. package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
  62. package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
  63. package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
  64. package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
  65. package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
  66. package/node_modules/typebox/build/system/memory/update.mjs +43 -16
  67. package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
  68. package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
  69. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
  70. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
  71. package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
  72. package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
  73. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
  74. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
  75. package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
  76. package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
  77. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
  78. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
  79. package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
  80. package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
  81. package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
  82. package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
  83. package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
  84. package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
  85. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
  86. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
  87. package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
  88. package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
  89. package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
  90. package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
  91. package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
  92. package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
  93. package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
  94. package/node_modules/typebox/package.json +1 -1
  95. package/node_modules/typebox/readme.md +1 -1
  96. package/node_modules/zod/package.json +1 -1
  97. package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
  98. package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
  99. package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
  100. package/node_modules/zod/src/v4/core/compile.ts +9 -0
  101. package/node_modules/zod/src/v4/core/schemas.ts +35 -1
  102. package/node_modules/zod/src/v4/core/util.ts +13 -0
  103. package/node_modules/zod/src/v4/core/versions.ts +1 -1
  104. package/node_modules/zod/v4/core/compile.cjs +8 -0
  105. package/node_modules/zod/v4/core/compile.js +8 -0
  106. package/node_modules/zod/v4/core/schemas.cjs +30 -0
  107. package/node_modules/zod/v4/core/schemas.d.cts +3 -1
  108. package/node_modules/zod/v4/core/schemas.d.ts +3 -1
  109. package/node_modules/zod/v4/core/schemas.js +30 -0
  110. package/node_modules/zod/v4/core/util.cjs +15 -0
  111. package/node_modules/zod/v4/core/util.d.cts +2 -0
  112. package/node_modules/zod/v4/core/util.d.ts +2 -0
  113. package/node_modules/zod/v4/core/util.js +14 -0
  114. package/node_modules/zod/v4/core/versions.cjs +1 -1
  115. package/node_modules/zod/v4/core/versions.js +1 -1
  116. package/openclaw.plugin.json +9 -2
  117. package/package.json +6 -6
  118. package/dist/.setup/webhook-replay-B0Eo3Ll5.mjs +0 -42
  119. package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
  120. 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: VoiceCallProvidersConfigSchema
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: normalizeVoiceCallTtsConfig(config.tts, route.tts)
424
+ tts: !defaultTts && !routeTts ? void 0 : TtsConfigSchema.parse(mergeDeep(defaultTts ?? {}, routeTts ?? {}))
428
425
  }
429
426
  };
430
427
  }
431
- function sanitizeVoiceCallProviderConfigs(value) {
432
- return Object.fromEntries(Object.entries(value ?? {}).filter((entry) => entry[1] !== void 0));
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(config) {
444
- const defaults = structuredClone(DEFAULT_VOICE_CALL_CONFIG);
445
- const serve = {
446
- ...defaults.serve,
447
- ...config.serve
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
- allowFrom: config.allowFrom ?? defaults.allowFrom,
467
- numbers: sanitizeVoiceCallNumberRoutes(config.numbers ?? defaults.numbers),
468
- outbound: {
469
- ...defaults.outbound,
470
- ...config.outbound
471
- },
472
- reports: CallReportsConfigSchema.parse(config.reports),
473
- live: CallLiveConfigSchema.parse(config.live),
474
- callbacks: CallCallbacksConfigSchema.parse(config.callbacks),
475
- voicemail: CallVoicemailConfigSchema.parse(config.voicemail),
476
- serve,
477
- tailscale: {
478
- ...defaults.tailscale,
479
- ...config.tailscale
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") return resolveVoiceCallAgentSessionKey({
515
- config: params.config,
516
- sessionKey: explicit || "main",
517
- coreSession: params.coreSession
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 = normalizeVoiceCallConfig(config);
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 { resolveVoiceCallEffectiveConfig as a, resolveVoiceCallSessionKey as c, REALTIME_VOICE_END_CALL_TOOL_NAME as d, resolveVoiceCallRealtimeTools as f, CallBriefSchema as g, normalizePhoneNumber as h, resolveVoiceCallConfig as i, resolveVoiceCallStreamExposurePaths as l, isAllowlistedCaller as m, normalizeVoiceCallConfig as n, resolveVoiceCallNumberRouteKeyForCall as o, DEFAULT_VOICEMAIL_HOLD_OPENING_MAX_MS as p, resolveTwilioAuthToken as r, resolveVoiceCallPublicPathPrefix as s, VoiceCallConfigSchema as t, validateProviderConfig as u };
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-B0Eo3Ll5.mjs";
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 reconstructWebhookUrl, r as verifyPlivoWebhook, t as createCarrierApi } from "./carrier-api-BgJdQC-e.mjs";
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
- if (!config.authId) throw new Error("Plivo Auth ID is required");
42
- if (!config.authToken) throw new Error("Plivo Auth Token is required");
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
- const dedupeKey = options?.verifiedRequestKey ?? createPlivoRequestDedupeKey(ctx);
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 {