UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

157 lines (156 loc) 8.6 kB
import { i as asOptionalRecord, s as readStringField } from "./record-coerce-DHZ4bFlT.js"; import "./string-coerce-runtime-CEGJWkQ_.js"; import { t as VoiceCallConfigSchema } from "./config-BYJnzp4g.js"; //#region extensions/voice-call/src/config-compat.ts /** Version where legacy voice-call config shape support is removed. */ const VOICE_CALL_LEGACY_CONFIG_REMOVAL_VERSION = "2026.6.0"; const asObject = asOptionalRecord; const getString = readStringField; /** Read finite numeric config values. */ function getNumber(obj, key) { const value = obj?.[key]; return typeof value === "number" && Number.isFinite(value) ? value : void 0; } /** Merge legacy provider-specific values into the canonical providers map. */ function mergeProviderConfig(providersValue, providerId, compatValues) { if (Object.keys(compatValues).length === 0) return asObject(providersValue); const providers = asObject(providersValue) ?? {}; const existing = asObject(providers[providerId]) ?? {}; return { ...providers, [providerId]: { ...existing, ...compatValues } }; } /** Collect legacy voice-call config keys that should be migrated. */ function collectVoiceCallLegacyConfigIssues(value) { const raw = asObject(value) ?? {}; const realtimeAgentContext = asObject(asObject(raw.realtime)?.agentContext); const twilio = asObject(raw.twilio); const streaming = asObject(raw.streaming); const issues = []; if (raw.provider === "log") issues.push({ path: "provider", replacement: "provider", message: "Replace provider \"log\" with \"mock\"." }); if (typeof twilio?.from === "string") issues.push({ path: "twilio.from", replacement: "fromNumber", message: "Move twilio.from to fromNumber." }); if (typeof streaming?.sttProvider === "string") issues.push({ path: "streaming.sttProvider", replacement: "streaming.provider", message: "Move streaming.sttProvider to streaming.provider." }); if (typeof streaming?.openaiApiKey === "string") issues.push({ path: "streaming.openaiApiKey", replacement: "streaming.providers.openai.apiKey", message: "Move streaming.openaiApiKey to streaming.providers.openai.apiKey." }); if (typeof streaming?.sttModel === "string") issues.push({ path: "streaming.sttModel", replacement: "streaming.providers.openai.model", message: "Move streaming.sttModel to streaming.providers.openai.model." }); if (typeof streaming?.silenceDurationMs === "number") issues.push({ path: "streaming.silenceDurationMs", replacement: "streaming.providers.openai.silenceDurationMs", message: "Move streaming.silenceDurationMs to streaming.providers.openai.silenceDurationMs." }); if (typeof streaming?.vadThreshold === "number") issues.push({ path: "streaming.vadThreshold", replacement: "streaming.providers.openai.vadThreshold", message: "Move streaming.vadThreshold to streaming.providers.openai.vadThreshold." }); if (realtimeAgentContext && Object.hasOwn(realtimeAgentContext, "includeSystemPrompt")) issues.push({ path: "realtime.agentContext.includeSystemPrompt", replacement: "realtime.agentContext", message: "Remove realtime.agentContext.includeSystemPrompt; realtime context now uses the generated agent prompt." }); return issues; } /** Format runtime warnings for legacy voice-call config keys. */ function formatVoiceCallLegacyConfigWarnings(params) { const issues = collectVoiceCallLegacyConfigIssues(params.value); if (issues.length === 0) return []; return [`[voice-call] legacy config keys detected under ${params.configPathPrefix}; runtime loading will not rewrite them, and support for the legacy shape will be removed in ${VOICE_CALL_LEGACY_CONFIG_REMOVAL_VERSION}. Run "${params.doctorFixCommand}".`, ...issues.map((issue) => `[voice-call] ${params.configPathPrefix}.${issue.path}: ${issue.message}`)]; } /** Migrate legacy voice-call config input to the current canonical shape. */ function migrateVoiceCallLegacyConfigInput(params) { const raw = asObject(params.value) ?? {}; const realtime = asObject(raw.realtime); const realtimeAgentContext = asObject(realtime?.agentContext); const twilio = asObject(raw.twilio); const streaming = asObject(raw.streaming); const configPathPrefix = params.configPathPrefix ?? "plugins.entries.voice-call.config"; const issues = collectVoiceCallLegacyConfigIssues(raw); const legacyStreamingOpenAICompat = {}; const streamingOpenAIApiKey = getString(streaming, "openaiApiKey"); if (streamingOpenAIApiKey) legacyStreamingOpenAICompat.apiKey = streamingOpenAIApiKey; const streamingSttModel = getString(streaming, "sttModel"); if (streamingSttModel) legacyStreamingOpenAICompat.model = streamingSttModel; const streamingSilenceDurationMs = getNumber(streaming, "silenceDurationMs"); if (streamingSilenceDurationMs !== void 0) legacyStreamingOpenAICompat.silenceDurationMs = streamingSilenceDurationMs; const streamingVadThreshold = getNumber(streaming, "vadThreshold"); if (streamingVadThreshold !== void 0) legacyStreamingOpenAICompat.vadThreshold = streamingVadThreshold; const streamingProvider = getString(streaming, "provider"); const legacyStreamingProvider = getString(streaming, "sttProvider"); const normalizedStreaming = streaming ? { ...streaming, provider: streamingProvider ?? legacyStreamingProvider, providers: mergeProviderConfig(streaming.providers, "openai", legacyStreamingOpenAICompat) } : void 0; if (normalizedStreaming) { delete normalizedStreaming.sttProvider; delete normalizedStreaming.openaiApiKey; delete normalizedStreaming.sttModel; delete normalizedStreaming.silenceDurationMs; delete normalizedStreaming.vadThreshold; } const normalizedTwilio = twilio ? { ...twilio } : void 0; if (normalizedTwilio) delete normalizedTwilio.from; const normalizedRealtimeAgentContext = realtimeAgentContext ? { ...realtimeAgentContext } : void 0; if (normalizedRealtimeAgentContext) delete normalizedRealtimeAgentContext.includeSystemPrompt; const normalizedRealtime = realtime ? { ...realtime, agentContext: normalizedRealtimeAgentContext ?? realtime.agentContext } : void 0; const config = { ...raw, provider: raw.provider === "log" ? "mock" : raw.provider, fromNumber: raw.fromNumber ?? (typeof twilio?.from === "string" ? twilio.from : void 0), twilio: normalizedTwilio, streaming: normalizedStreaming, realtime: normalizedRealtime }; const changes = []; if (raw.provider === "log") changes.push(`Moved ${configPathPrefix}.provider "log""mock".`); if (typeof twilio?.from === "string" && typeof raw.fromNumber !== "string") changes.push(`Moved ${configPathPrefix}.twilio.from → ${configPathPrefix}.fromNumber.`); if (typeof streaming?.sttProvider === "string") changes.push(`Moved ${configPathPrefix}.streaming.sttProvider → ${configPathPrefix}.streaming.provider.`); if (typeof streaming?.openaiApiKey === "string") changes.push(`Moved ${configPathPrefix}.streaming.openaiApiKey → ${configPathPrefix}.streaming.providers.openai.apiKey.`); if (typeof streaming?.sttModel === "string") changes.push(`Moved ${configPathPrefix}.streaming.sttModel → ${configPathPrefix}.streaming.providers.openai.model.`); if (getNumber(streaming, "silenceDurationMs") !== void 0) changes.push(`Moved ${configPathPrefix}.streaming.silenceDurationMs → ${configPathPrefix}.streaming.providers.openai.silenceDurationMs.`); else if (typeof streaming?.silenceDurationMs === "number") changes.push(`Removed invalid ${configPathPrefix}.streaming.silenceDurationMs.`); if (getNumber(streaming, "vadThreshold") !== void 0) changes.push(`Moved ${configPathPrefix}.streaming.vadThreshold → ${configPathPrefix}.streaming.providers.openai.vadThreshold.`); else if (typeof streaming?.vadThreshold === "number") changes.push(`Removed invalid ${configPathPrefix}.streaming.vadThreshold.`); if (realtimeAgentContext && Object.hasOwn(realtimeAgentContext, "includeSystemPrompt")) changes.push(`Removed ${configPathPrefix}.realtime.agentContext.includeSystemPrompt.`); return { config, changes, issues }; } /** Normalize legacy voice-call config input without returning migration metadata. */ function normalizeVoiceCallLegacyConfigInput(value) { return migrateVoiceCallLegacyConfigInput({ value }).config; } /** Parse voice-call plugin config after applying legacy normalization. */ function parseVoiceCallPluginConfig(value) { return VoiceCallConfigSchema.parse(normalizeVoiceCallLegacyConfigInput(value)); } //#endregion export { parseVoiceCallPluginConfig as i, migrateVoiceCallLegacyConfigInput as n, normalizeVoiceCallLegacyConfigInput as r, formatVoiceCallLegacyConfigWarnings as t };