UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

140 lines (139 loc) 6.02 kB
import { l as normalizeOptionalString } from "../../string-coerce-CIXf7egm.js"; import { r as extensionForMime } from "../../mime-CVpcq9ju.js"; import { h as resolveProviderOperationTimeoutMs, r as createProviderOperationDeadline } from "../../shared-DCDpYrmy.js"; import "../../string-coerce-runtime-GQa0ehRA.js"; import "../../media-mime-BNY9NrbL.js"; import { a as resolveApiKeyForProvider } from "../../provider-auth-runtime-BqyR7mkf.js"; import "../../provider-http-k9RMI7iG.js"; import { r as generatedMusicAssetFromBase64 } from "../../music-generation-CAe8vdz7.js"; import { n as resolveGoogleGenerativeAiApiOrigin } from "../../provider-policy-BjaZN4xs.js"; import { c as createGoogleMusicGenerationProviderMetadata } from "../../generation-provider-metadata-DFHTgxtH.js"; import "../../api-BIkqybAZ.js"; import { n as toStandardGoogleProviderBase64 } from "../../base64-L17PENqC.js"; import { t as createGoogleGenAI } from "../../google-genai-runtime-BVaj5AYq.js"; //#region extensions/google/music-generation-provider.ts const DEFAULT_TIMEOUT_MS = 18e4; function resolveConfiguredGoogleMusicBaseUrl(req) { const configured = normalizeOptionalString(req.cfg?.models?.providers?.google?.baseUrl); return configured ? resolveGoogleGenerativeAiApiOrigin(configured) : void 0; } function buildMusicPrompt(req) { const parts = [req.prompt.trim()]; const lyrics = normalizeOptionalString(req.lyrics); if (req.instrumental === true) parts.push("Instrumental only. No vocals, no sung lyrics, no spoken word."); if (lyrics) parts.push(`Lyrics:\n${lyrics}`); return parts.join("\n\n"); } function resolveSupportedFormats(model) { return model === "lyria-3-pro-preview" ? ["mp3", "wav"] : ["mp3"]; } function resolveTrackFileName(params) { const ext = extensionForMime(params.mimeType)?.replace(/^\./u, "") || (params.model === "lyria-3-pro-preview" ? "wav" : "mp3"); return `track-${params.index + 1}.${ext}`; } function extractTracks(params) { const lyrics = []; const tracks = []; for (const candidate of params.payload.candidates ?? []) for (const part of candidate.content?.parts ?? []) { const text = normalizeOptionalString(part.text); if (text) { lyrics.push(text); continue; } const inline = part.inlineData ?? part.inline_data; const data = normalizeOptionalString(inline?.data); if (!data) continue; const mimeType = normalizeOptionalString(inline?.mimeType) || normalizeOptionalString(inline?.mime_type) || "audio/mpeg"; const standardAudio = toStandardGoogleProviderBase64(data); if (!standardAudio) throw new Error("Generated music asset contains malformed base64 audio data"); tracks.push(generatedMusicAssetFromBase64({ base64: standardAudio, mimeType, fileName: resolveTrackFileName({ index: tracks.length, mimeType, model: params.model }) })); } return { tracks, lyrics }; } function resolveTerminalNoAudioReason(payload) { const blockReason = normalizeOptionalString(payload.promptFeedback?.blockReason); if (blockReason && !blockReason.endsWith("_UNSPECIFIED")) return `prompt blocked (${blockReason})`; for (const candidate of payload.candidates ?? []) { const finishReason = normalizeOptionalString(candidate.finishReason); if (finishReason && finishReason !== "STOP" && finishReason !== "FINISH_REASON_UNSPECIFIED") return `generation stopped (${finishReason})`; } } function buildGoogleMusicGenerationProvider() { return { ...createGoogleMusicGenerationProviderMetadata(), async generateMusic(req) { if ((req.inputImages?.length ?? 0) > 10) throw new Error(`Google music generation supports at most 10 reference images.`); const auth = await resolveApiKeyForProvider({ provider: "google", cfg: req.cfg, agentDir: req.agentDir, store: req.authStore }); if (!auth.apiKey) throw new Error("Google API key missing"); const model = normalizeOptionalString(req.model) || "lyria-3-clip-preview"; if (req.format) { const supportedFormats = resolveSupportedFormats(model); if (!supportedFormats.includes(req.format)) throw new Error(`Google music generation model ${model} supports ${supportedFormats.join(", ")} output.`); } const configuredBaseUrl = resolveConfiguredGoogleMusicBaseUrl(req); const operationTimeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS; const deadline = createProviderOperationDeadline({ timeoutMs: operationTimeoutMs, label: "Google music generation" }); let generated; for (let attempt = 0; attempt < 2; attempt += 1) { const response = await createGoogleGenAI({ apiKey: auth.apiKey, httpOptions: { ...configuredBaseUrl ? { baseUrl: configuredBaseUrl } : {}, timeout: resolveProviderOperationTimeoutMs({ deadline, defaultTimeoutMs: operationTimeoutMs }) } }).models.generateContent({ model, contents: [{ text: buildMusicPrompt(req) }, ...(req.inputImages ?? []).map((image) => ({ inlineData: { mimeType: normalizeOptionalString(image.mimeType) || "image/png", data: image.buffer?.toString("base64") ?? "" } }))], config: { responseModalities: ["AUDIO", "TEXT"] } }); generated = extractTracks({ payload: response, model }); if (generated.tracks.length > 0) break; const terminalReason = resolveTerminalNoAudioReason(response); if (terminalReason) throw new Error(`Google music generation returned no audio: ${terminalReason}`); } if (!generated || generated.tracks.length === 0) throw new Error("Google music generation response missing audio data"); const { tracks, lyrics } = generated; return { tracks, ...lyrics.length > 0 ? { lyrics } : {}, model, metadata: { inputImageCount: req.inputImages?.length ?? 0, instrumental: req.instrumental === true, ...normalizeOptionalString(req.lyrics) ? { requestedLyrics: true } : {}, ...req.format ? { requestedFormat: req.format } : {} } }; } }; } //#endregion export { buildGoogleMusicGenerationProvider };