diff --git a/extensions/voice-call/src/config.ts b/extensions/voice-call/src/config.ts index fbff23d45de4..f16994c1e6be 100644 --- a/extensions/voice-call/src/config.ts +++ b/extensions/voice-call/src/config.ts @@ -9,6 +9,7 @@ import { import { z } from "zod"; import { TtsConfigSchema } from "../api.js"; import { deepMergeDefined } from "./deep-merge.js"; +import { normalizePath } from "./path-utils.js"; import { DEFAULT_VOICE_CALL_REALTIME_INSTRUCTIONS } from "./realtime-defaults.js"; // ----------------------------------------------------------------------------- @@ -521,20 +522,8 @@ function cloneDefaultVoiceCallConfig(): VoiceCallConfig { return structuredClone(DEFAULT_VOICE_CALL_CONFIG); } -function normalizeWebhookLikePath(pathname: string): string { - const trimmed = pathname.trim(); - if (!trimmed) { - return "/"; - } - const prefixed = trimmed.startsWith("/") ? trimmed : `/${trimmed}`; - if (prefixed === "/") { - return prefixed; - } - return prefixed.endsWith("/") ? prefixed.slice(0, -1) : prefixed; -} - function defaultRealtimeStreamPathForServePath(servePath: string): string { - const normalized = normalizeWebhookLikePath(servePath); + const normalized = normalizePath(servePath); if (normalized.endsWith("/webhook")) { return `${normalized.slice(0, -"/webhook".length)}/stream/realtime`; } diff --git a/extensions/voice-call/src/path-utils.ts b/extensions/voice-call/src/path-utils.ts new file mode 100644 index 000000000000..c2be91c5bafa --- /dev/null +++ b/extensions/voice-call/src/path-utils.ts @@ -0,0 +1,12 @@ +// Voice Call plugin module implements shared path normalization. +export function normalizePath(pathname: string): string { + const trimmed = pathname.trim(); + if (!trimmed) { + return "/"; + } + const prefixed = trimmed.startsWith("/") ? trimmed : `/${trimmed}`; + if (prefixed === "/") { + return prefixed; + } + return prefixed.endsWith("/") ? prefixed.slice(0, -1) : prefixed; +} diff --git a/extensions/voice-call/src/webhook/realtime-handler.ts b/extensions/voice-call/src/webhook/realtime-handler.ts index 47b378d6ed23..c58e05b67a9d 100644 --- a/extensions/voice-call/src/webhook/realtime-handler.ts +++ b/extensions/voice-call/src/webhook/realtime-handler.ts @@ -30,6 +30,7 @@ import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env"; import WebSocket, { WebSocketServer } from "ws"; import type { VoiceCallRealtimeConfig } from "../config.js"; import type { CallManager } from "../manager.js"; +import { normalizePath } from "../path-utils.js"; import type { VoiceCallProvider } from "../providers/base.js"; import type { CallRecord, NormalizedEvent } from "../types.js"; import type { WebhookResponsePayload } from "../webhook.types.js"; @@ -64,18 +65,6 @@ const RECENT_FINAL_USER_TRANSCRIPT_TTL_MS = 2_000; const BARGE_IN_REQUIRED_LOUD_CHUNKS = 2; const logger = createSubsystemLogger("voice-call/realtime"); -function normalizePath(pathname: string): string { - const trimmed = pathname.trim(); - if (!trimmed) { - return "/"; - } - const prefixed = trimmed.startsWith("/") ? trimmed : `/${trimmed}`; - if (prefixed === "/") { - return prefixed; - } - return prefixed.endsWith("/") ? prefixed.slice(0, -1) : prefixed; -} - function buildGreetingInstructions( baseInstructions: string | undefined, greeting: string | undefined,